use std::rc::Rc; use parsing::{AST, Statement, Expression, Declaration}; use builtin::{BinOp, PrefixOp}; #[derive(Debug)] pub struct ReducedAST(pub Vec); #[derive(Debug, Clone)] pub enum Stmt { PreBinding { name: Rc, func: Func, }, Binding { name: Rc, constant: bool, expr: Expr, }, Expr(Expr), Noop, } #[derive(Debug, Clone)] pub enum Expr { Unit, Lit(Lit), Tuple(Vec), Func(Func), Val(Rc), Call { f: Box, args: Vec, }, Assign { val: Box, expr: Box, }, Conditional { cond: Box, then_clause: Vec, else_clause: Vec, }, UnimplementedSigilValue } #[derive(Debug, Clone)] pub enum Lit { Nat(u64), Int(i64), Float(f64), Bool(bool), StringLit(Rc), Custom(Rc, Vec), } #[derive(Debug, Clone)] pub enum Func { BuiltIn(Rc), UserDefined { name: Option>, params: Vec>, body: Vec, } } impl AST { pub fn reduce(&self) -> ReducedAST { let mut output = vec![]; for statement in self.0.iter() { output.push(statement.reduce()); } ReducedAST(output) } } impl Statement { fn reduce(&self) -> Stmt { use parsing::Statement::*; match self { ExpressionStatement(expr) => Stmt::Expr(expr.reduce()), Declaration(decl) => decl.reduce(), } } } impl Expression { fn reduce(&self) -> Expr { use parsing::ExpressionType::*; let ref input = self.0; match input { NatLiteral(n) => Expr::Lit(Lit::Nat(*n)), FloatLiteral(f) => Expr::Lit(Lit::Float(*f)), StringLiteral(s) => Expr::Lit(Lit::StringLit(s.clone())), BoolLiteral(b) => Expr::Lit(Lit::Bool(*b)), BinExp(binop, lhs, rhs) => binop.reduce(lhs, rhs), PrefixExp(op, arg) => op.reduce(arg), Value(name) => Expr::Val(name.clone()), Call { f, arguments } => Expr::Call { f: Box::new(f.reduce()), args: arguments.iter().map(|arg| arg.reduce()).collect(), }, TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| e.reduce()).collect()), IfExpression(cond, then_clause, else_clause) => Expr::Conditional { cond: Box::new((**cond).reduce()), then_clause: then_clause.iter().map(|expr| expr.reduce()).collect(), else_clause: match else_clause { None => vec![], Some(stmts) => stmts.iter().map(|expr| expr.reduce()).collect(), } }, _ => Expr::UnimplementedSigilValue, } } } impl Declaration { fn reduce(&self) -> Stmt { use self::Declaration::*; use ::parsing::Signature; match self { Binding {name, constant, expr } => Stmt::Binding { name: name.clone(), constant: *constant, expr: expr.reduce() }, FuncDecl(Signature { name, params, .. }, statements) => Stmt::PreBinding { name: name.clone(), func: Func::UserDefined { name: Some(name.clone()), params: params.iter().map(|param| param.0.clone()).collect(), body: statements.iter().map(|stmt| stmt.reduce()).collect(), } }, TypeDecl(_,_) => Stmt::Noop, _ => Stmt::Expr(Expr::UnimplementedSigilValue) } } } impl BinOp { fn reduce(&self, lhs: &Box, rhs: &Box) -> Expr { if **self.sigil() == "=" { Expr::Assign { val: Box::new(lhs.reduce()), expr: Box::new(rhs.reduce()), } } else { let f = Box::new(Expr::Func(Func::BuiltIn(self.sigil().clone()))); Expr::Call { f, args: vec![lhs.reduce(), rhs.reduce()]} } } } impl PrefixOp { fn reduce(&self, arg: &Box) -> Expr { let f = Box::new(Expr::Func(Func::BuiltIn(self.sigil().clone()))); Expr::Call { f, args: vec![arg.reduce()]} } }