diff --git a/schala-lang/language/src/tree_walk_eval/mod.rs b/schala-lang/language/src/tree_walk_eval/mod.rs index 8b4e2b8..5fe6edd 100644 --- a/schala-lang/language/src/tree_walk_eval/mod.rs +++ b/schala-lang/language/src/tree_walk_eval/mod.rs @@ -9,7 +9,7 @@ use std::convert::From; mod test; -type EvalResult = Result; +type EvalResult = Result; #[derive(Debug)] pub struct State<'a> { @@ -49,6 +49,14 @@ impl From for RuntimeError { } } +impl From<&str> for RuntimeError { + fn from(msg: &str) -> Self { + Self { + msg: msg.to_string(), + } + } +} + impl RuntimeError { fn get_msg(&self) -> String { format!("Runtime error: {}", self.msg) @@ -160,7 +168,7 @@ impl<'a> State<'a> { }, Ok(_) => (), Err(error) => { - acc.push(Err(error.into())); + acc.push(Err(error.msg)); return acc; } } @@ -210,21 +218,21 @@ impl<'a> State<'a> { // This just checks that the function exists in "memory" by ID, we don't // actually retrieve it until `apply_function()` Some(RuntimeValue::Function(_)) => Primitive::Callable(Function::UserDefined(id.clone())), - x => return Err(format!("Function not found for id: {} : {:?}", id, x)), + x => return Err(format!("Function not found for id: {} : {:?}", id, x).into()), } }, Lookup::Param(n) => { let mem = n.into(); match self.environments.lookup(&mem) { Some(RuntimeValue::Primitive(prim)) => prim.clone(), - e => return Err(format!("Param lookup error, got {:?}", e)), + e => return Err(format!("Param lookup error, got {:?}", e).into()), } }, kind @ Lookup::LocalVar | kind @ Lookup::GlobalVar => { let mem = id.into(); match self.environments.lookup(&mem) { Some(RuntimeValue::Primitive(expr)) => expr.clone(), - _ => return Err(format!("Nothing found for variable lookup {} of kind {:?}", id, kind)), + _ => return Err(format!("Nothing found for variable lookup {} of kind {:?}", id, kind).into()), } }, } @@ -232,19 +240,18 @@ impl<'a> State<'a> { Expression::Assign { ref lval, box rval } => { let mem = lval.into(); let mut env = self.environments.lookup(&mem); - return Err("Assign not implemented".to_string()); + return Err("Assign not implemented".into()); }, Expression::Call { box f, args } => self.call_expression(f, args)?, Expression::Callable(func) => Primitive::Callable(func), Expression::ReductionError(e) => return Err(e.into()), - e => return Err(format!("Can't yet handle {:?}", e)), }) } fn call_expression(&mut self, f: Expression, args: Vec) -> EvalResult { let func = match self.expression(f)? { Primitive::Callable(func) => func, - other => return Err(format!("Trying to call non-function value: {:?}", other)), + other => return Err(format!("Trying to call non-function value: {:?}", other).into()), }; match func { Function::Builtin(builtin) => self.apply_builtin(builtin, args), @@ -255,12 +262,12 @@ impl<'a> State<'a> { let body = body.clone(); //TODO ideally this clone would not happen self.apply_function(body, args) }, - e => Err(format!("Error looking up function with id {}: {:?}", def_id, e)) + e => Err(format!("Error looking up function with id {}: {:?}", def_id, e).into()) } }, Function::Lambda { arity, body } => { if arity as usize != args.len() { - return Err(format!("Lambda expression requries {} arguments, only {} provided", arity, args.len())); + return Err(format!("Lambda expression requries {} arguments, only {} provided", arity, args.len()).into()); } let body = body.clone(); //TODO again ideally, no cloning here self.apply_function(body, args) @@ -279,7 +286,7 @@ impl<'a> State<'a> { Ok(match (builtin, evaled_args.as_slice()) { (FieldAccess, /*&[Node::PrimObject { .. }]*/ _) => { - return Err("Field access unimplemented".to_string()); + return Err("Field access unimplemented".into()); } (binop, &[ref lhs, ref rhs]) => match (binop, lhs, rhs) { (Add, Lit(Nat(l)), Lit(Nat(r))) => Nat(l + r).into(), @@ -288,7 +295,7 @@ impl<'a> State<'a> { (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()); + return Err("Divide-by-zero error".into()); } else { Nat(l / r).into() }, @@ -320,7 +327,7 @@ impl<'a> State<'a> { (GreaterThanOrEqual, Lit(Int(l)), Lit(Int(r))) => Bool(l >= r).into(), (GreaterThanOrEqual, Lit(Float(l)), Lit(Float(r))) => Bool(l >= r).into(), - (binop, lhs, rhs) => return Err(format!("Invalid binop expression {:?} {:?} {:?}", lhs, binop, rhs)), + (binop, lhs, rhs) => return Err(format!("Invalid binop expression {:?} {:?} {:?}", lhs, binop, rhs).into()), }, (prefix, &[ref arg]) => match (prefix, arg) { (BooleanNot, Lit(Bool(true))) => Bool(false), @@ -329,7 +336,7 @@ impl<'a> State<'a> { (Negate, Lit(Int(n))) => Int(-(*n as i64)), (Increment, Lit(Int(n))) => Int(*n), (Increment, Lit(Nat(n))) => Nat(*n), - _ => return Err("No valid prefix op".to_string()) + _ => return Err("No valid prefix op".into()) }.into(), /* builtin functions */ (IOPrint, &[ref anything]) => { @@ -345,7 +352,7 @@ impl<'a> State<'a> { std::io::stdin().read_line(&mut buf).expect("Error readling line in 'getline'"); StringLit(Rc::new(buf.trim().to_string())).into() }, - (x, args) => return Err(format!("bad or unimplemented builtin {:?} | {:?}", x, args)), + (x, args) => return Err(format!("bad or unimplemented builtin {:?} | {:?}", x, args).into()), }) }