diff --git a/src/expr.rs b/src/expr.rs index a8a8a8d6c4b73e533e3739c4b1ba6df3a8fac16b..c1652e2e54cbab0d3d5c4599f31ee65d1c3efcaa 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1,8 +1,14 @@ #[derive(Debug)] pub enum Expr { - Lambda(Box<Expr>), Abs(Box<Expr>), App(Box<Expr>, Box<Expr>), Var(usize), DefinitionName(String), } + +#[derive(Debug)] +pub enum FlattenedExpr { + Abs(Box<FlattenedExpr>), + App(Box<FlattenedExpr>, Box<FlattenedExpr>), + Var(usize), +} diff --git a/src/flatten.rs b/src/flatten.rs new file mode 100644 index 0000000000000000000000000000000000000000..53e54322216c7149814fc28a6ffbb56219da29f1 --- /dev/null +++ b/src/flatten.rs @@ -0,0 +1,57 @@ +use std::collections::{HashMap, HashSet}; + +use crate::expr::{Expr, FlattenedExpr}; + +pub struct Flattener { + funcs: HashMap<String, Expr>, +} + +impl Flattener { + pub fn new(funcs: HashMap<String, Expr>) -> Self { + Self { funcs } + } + + pub fn flatten(&mut self, main: &Expr) -> Option<FlattenedExpr> { + self.flatten_expr(&main, HashSet::new()) + } + + fn flatten_expr<'a>( + &self, + expr: &'a Expr, + mut names: HashSet<&'a str>, + ) -> Option<FlattenedExpr> { + let ret = match expr { + Expr::Abs(expr) => FlattenedExpr::Abs(Box::new(self.flatten_expr(expr, names)?)), + Expr::App(left, right) => FlattenedExpr::App( + Box::new(self.flatten_expr(left, names.clone())?), + Box::new(self.flatten_expr(right, names)?), + ), + Expr::Var(x) => FlattenedExpr::Var(*x), + Expr::DefinitionName(name) => { + if names.contains(name.as_str()) { + self.print_error(&format!("Recursive definition for ${}", name)); + return None; + } + + let expr = match self.funcs.get(name) { + Some(x) => x, + None => { + self.print_error(&format!("Unknown definition ${}", name)); + + return None; + } + }; + + names.insert(name); + + self.flatten_expr(expr, names)? + } + }; + + Some(ret) + } + + fn print_error(&self, err: &str) { + eprintln!("Error: {err}"); + } +} diff --git a/src/main.rs b/src/main.rs index 4de6c3e3e9a7aae9a53abb07ed1e1c12b820030b..5c2028210b9c56d6f34ce09e50690eb930663218 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ +use flatten::Flattener; use parser::Parser; use scanner::Scanner; mod expr; +mod flatten; mod parser; mod scanner; mod token; @@ -10,7 +12,6 @@ fn main() { let scanner = Scanner::new( " $false = λtf.f -# mrow! $true = λtf.t λa.(a $true) @@ -19,13 +20,11 @@ $true = λtf.t let tokens = scanner.scan_tokens().unwrap(); - for t in &tokens { - println!("{} {:?}", t.line, t.token_type); - } - let mut parser = Parser::new(tokens); let (funcs, main) = parser.parse().unwrap(); - dbg!(funcs); - dbg!(main); + let mut flattener = Flattener::new(funcs); + let flat = flattener.flatten(&main); + + dbg!(flat); } diff --git a/src/parser.rs b/src/parser.rs index 8dd05f8e37f9c35b0f98ea258223d98d3b6acc4d..076388a2c7ae9ce63e75bcea0755e1d5a7e66512 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -122,7 +122,7 @@ impl Parser { for _ in 0..abs_count { self.env.pop().unwrap(); - expr = Expr::Lambda(Box::new(expr)); + expr = Expr::Abs(Box::new(expr)); } Some(expr)