diff --git a/schala-lang/language/src/tree_walk_eval/mod.rs b/schala-lang/language/src/tree_walk_eval/mod.rs index 8edb576..455a741 100644 --- a/schala-lang/language/src/tree_walk_eval/mod.rs +++ b/schala-lang/language/src/tree_walk_eval/mod.rs @@ -4,6 +4,7 @@ use crate::util::ScopeStack; use crate::builtin::Builtin; use std::fmt::Write; +use std::rc::Rc; use std::convert::From; type EvalResult = Result; @@ -72,7 +73,6 @@ impl From for RuntimeValue { fn expr_to_repl(expr: &Expression) -> String { match expr { - Expression::Unimplemented => format!("Expression {:?} not implemented", expr), Expression::Literal(lit) => match lit { Literal::Nat(n) => format!("{}", n), Literal::Int(i) => format!("{}", i), @@ -103,7 +103,6 @@ enum Primitive { Tuple(Vec), Literal(Literal), Callable(Function), - Unimplemented, /* PrimObject { name: Rc, @@ -113,13 +112,18 @@ enum Primitive { */ } +impl From for Primitive { + fn from(lit: Literal) -> Self { + Primitive::Literal(lit) + } +} + impl Primitive { fn to_expr(&self) -> Expression { match self { Primitive::Tuple(items) => Expression::Tuple(items.iter().map(|item| item.to_expr()).collect()), Primitive::Literal(lit) => Expression::Literal(lit.clone()), Primitive::Callable(function) => Expression::Callable(function.clone()), - Primitive::Unimplemented => Expression::Unimplemented, } } } @@ -171,7 +175,6 @@ impl<'a> State<'a> { } fn expression(&mut self, expression: Expression) -> EvalResult { - use Expression::Unimplemented; Ok(match expression { Expression::Literal(lit) => Primitive::Literal(lit), Expression::Tuple(items) => Primitive::Tuple(items.into_iter().map(|expr| self.expression(expr)).collect::>>()?), @@ -194,10 +197,10 @@ impl<'a> State<'a> { Expression::Assign { ref lval, box rval } => { let mem = lval.into(); let mut env = self.environments.lookup(&mem); - Primitive::Unimplemented + return Err("Assign not implemented".to_string()); }, Expression::Call { box f, args } => self.call_expression(f, args)?, - Unimplemented => Primitive::Unimplemented, + Expression::Callable(func) => Primitive::Callable(func), Expression::ReductionError(e) => return Err(e.into()), e => return Err(format!("Can't yet handle {:?}", e)), }) @@ -215,7 +218,33 @@ impl<'a> State<'a> { } fn apply_builtin(&mut self, builtin: Builtin, args: Vec) -> EvalResult { - return Err("unimplemented apply-builtin".to_string()); + use Builtin::*; + use Literal::*; + use Expression::Literal as Lit; + + let evaled_args: EvalResult> = + args.into_iter().map(|arg| self.expression(arg).map(|prim| prim.to_expr())).collect(); + let evaled_args = evaled_args?; + + Ok(match (builtin, evaled_args.as_slice()) { + (FieldAccess, /*&[Node::PrimObject { .. }]*/ _) => { + return Err("Field access unimplemented".to_string()); + } + (binop, &[ref lhs, ref rhs]) => match (binop, lhs, rhs) { + (Add, Lit(Nat(l)), Lit(Nat(r))) => Nat(l + r).into(), + (Concatenate, Lit(StringLit(ref s1)), Lit(StringLit(ref s2))) => StringLit(Rc::new(format!("{}{}", s1, s2))).into(), + (Subtract, Lit(Nat(l)), Lit(Nat(r))) => Nat(l - r).into(), + (Multiply, Lit(Nat(l)), Lit(Nat(r))) => Nat(l * r).into(), + (Divide, Lit(Nat(l)), Lit(Nat(r))) => Float((*l as f64)/ (*r as f64)).into(), + (Quotient, Lit(Nat(l)), Lit(Nat(r))) => if *r == 0 { + return Err("Divide-by-zero error".to_string()); + } else { + Nat(l / r).into() + }, + (binop, lhs, rhs) => return Err(format!("Invalid binop expression {:?} {:?} {:?}", lhs, binop, rhs)), + }, + (x, args) => return Err(format!("bad or unimplemented builtin {:?} | {:?}", x, args)), + }) } fn apply_function(&mut self, def_id: DefId, args: Vec) -> EvalResult {