diff --git a/src/engine.rs b/src/engine.rs index 9aacee67..1e66575e 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -11,24 +11,28 @@ use std::ops::{Add, Sub, Mul, Div}; use std::cmp::{Ord, Eq}; #[derive(Debug)] -pub enum EvalError { - FunctionNotFound, - FunctionArgMismatch, - FunctionCallNotSupported, - IfGuardMismatch, - VariableNotFound, - FunctionArityNotSupported +pub enum EvalAltResult { + ErrorFunctionNotFound, + ErrorFunctionArgMismatch, + ErrorFunctionCallNotSupported, + ErrorIfGuardMismatch, + ErrorVariableNotFound, + ErrorFunctionArityNotSupported, + LoopBreak, + Return(Box) } -impl Error for EvalError { +impl Error for EvalAltResult { fn description(&self) -> &str { match *self { - EvalError::FunctionNotFound => "Function not found", - EvalError::FunctionArgMismatch => "Function argument types do not match", - EvalError::FunctionCallNotSupported => "Function call with > 2 argument not supported", - EvalError::IfGuardMismatch => "If guards expect boolean expression", - EvalError::VariableNotFound => "Variable not found", - EvalError::FunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported" + EvalAltResult::ErrorFunctionNotFound => "Function not found", + EvalAltResult::ErrorFunctionArgMismatch => "Function argument types do not match", + EvalAltResult::ErrorFunctionCallNotSupported => "Function call with > 2 argument not supported", + EvalAltResult::ErrorIfGuardMismatch => "If guards expect boolean expression", + EvalAltResult::ErrorVariableNotFound => "Variable not found", + EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported", + EvalAltResult::LoopBreak => "Loop broken before completion (not an error)", + EvalAltResult::Return(_) => "Function returned value (not an error)" } } @@ -37,20 +41,20 @@ impl Error for EvalError { } } -impl fmt::Display for EvalError { +impl fmt::Display for EvalAltResult { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.description()) } } pub enum FnType { - ExternalFn0(BoxResult, EvalError>>), - ExternalFn1(Box)->Result, EvalError>>), - ExternalFn2(Box, &mut Box)->Result, EvalError>>), - ExternalFn3(Box, &mut Box, &mut Box)->Result, EvalError>>), - ExternalFn4(Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), - ExternalFn5(Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), - ExternalFn6(Box, &mut Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>>), + ExternalFn0(BoxResult, EvalAltResult>>), + ExternalFn1(Box)->Result, EvalAltResult>>), + ExternalFn2(Box, &mut Box)->Result, EvalAltResult>>), + ExternalFn3(Box, &mut Box, &mut Box)->Result, EvalAltResult>>), + ExternalFn4(Box, &mut Box, &mut Box, &mut Box)->Result, EvalAltResult>>), + ExternalFn5(Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalAltResult>>), + ExternalFn6(Box, &mut Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalAltResult>>), InternalFn(FnDef) } @@ -63,7 +67,7 @@ pub type Scope = Vec<(String, Box)>; impl Engine { fn call_fn(&self, name: &str, arg1: Option<&mut Box>, arg2: Option<&mut Box>, arg3: Option<&mut Box>, - arg4: Option<&mut Box>, arg5: Option<&mut Box>, arg6: Option<&mut Box>) -> Result, EvalError> { + arg4: Option<&mut Box>, arg5: Option<&mut Box>, arg6: Option<&mut Box>) -> Result, EvalAltResult> { match self.fns.get(name) { Some(ref vf) => { @@ -78,6 +82,8 @@ impl Engine { } } & FnType::InternalFn(ref f) => { + if f.params.len() != 6 { return Err(EvalAltResult::ErrorFunctionArgMismatch); } + let mut new_scope: Scope = Vec::new(); let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None); let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None); @@ -95,14 +101,17 @@ impl Engine { new_scope.push((f.params[4].clone(), r5)); new_scope.push((f.params[5].clone(), r6)); }, - _ => return Err(EvalError::FunctionArgMismatch) - } - return self.eval_stmt(&mut new_scope, &*f.body); + _ => return Err(EvalAltResult::ErrorFunctionArgMismatch) + } + match self.eval_stmt(&mut new_scope, &*f.body) { + Err(EvalAltResult::Return(x)) => return Ok(x), + x => return x + } } _ => () } } - return Err(EvalError::FunctionArgMismatch); + return Err(EvalAltResult::ErrorFunctionArgMismatch); } (Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), Some(ref mut a5), None) => { for arr_f in *vf { @@ -114,6 +123,8 @@ impl Engine { } } & FnType::InternalFn(ref f) => { + if f.params.len() != 5 { return Err(EvalAltResult::ErrorFunctionArgMismatch); } + let mut new_scope: Scope = Vec::new(); let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None); let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None); @@ -129,14 +140,17 @@ impl Engine { new_scope.push((f.params[3].clone(), r4)); new_scope.push((f.params[4].clone(), r5)); }, - _ => return Err(EvalError::FunctionArgMismatch) + _ => return Err(EvalAltResult::ErrorFunctionArgMismatch) } - return self.eval_stmt(&mut new_scope, &*f.body); + match self.eval_stmt(&mut new_scope, &*f.body) { + Err(EvalAltResult::Return(x)) => return Ok(x), + x => return x + } } _ => () } } - return Err(EvalError::FunctionArgMismatch); + return Err(EvalAltResult::ErrorFunctionArgMismatch); } (Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), Some(ref mut a4), None, None) => { for arr_f in *vf { @@ -148,6 +162,8 @@ impl Engine { } } & FnType::InternalFn(ref f) => { + if f.params.len() != 4 { return Err(EvalAltResult::ErrorFunctionArgMismatch); } + let mut new_scope: Scope = Vec::new(); let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None); let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None); @@ -160,14 +176,17 @@ impl Engine { new_scope.push((f.params[2].clone(), r3)); new_scope.push((f.params[3].clone(), r4)); }, - _ => return Err(EvalError::FunctionArgMismatch) + _ => return Err(EvalAltResult::ErrorFunctionArgMismatch) } - return self.eval_stmt(&mut new_scope, &*f.body); + match self.eval_stmt(&mut new_scope, &*f.body) { + Err(EvalAltResult::Return(x)) => return Ok(x), + x => return x + } } _ => () } } - return Err(EvalError::FunctionArgMismatch); + return Err(EvalAltResult::ErrorFunctionArgMismatch); } (Some(ref mut a1), Some(ref mut a2), Some(ref mut a3), None, None, None) => { for arr_f in *vf { @@ -179,6 +198,8 @@ impl Engine { } } & FnType::InternalFn(ref f) => { + if f.params.len() != 3 { return Err(EvalAltResult::ErrorFunctionArgMismatch); } + let mut new_scope: Scope = Vec::new(); let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None); let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None); @@ -189,14 +210,17 @@ impl Engine { new_scope.push((f.params[1].clone(), r2)); new_scope.push((f.params[2].clone(), r3)); }, - _ => return Err(EvalError::FunctionArgMismatch) + _ => return Err(EvalAltResult::ErrorFunctionArgMismatch) } - return self.eval_stmt(&mut new_scope, &*f.body); + match self.eval_stmt(&mut new_scope, &*f.body) { + Err(EvalAltResult::Return(x)) => return Ok(x), + x => return x + } } _ => () } } - return Err(EvalError::FunctionArgMismatch); + return Err(EvalAltResult::ErrorFunctionArgMismatch); } (Some(ref mut a1), Some(ref mut a2), None, None, None, None) => { for arr_f in *vf { @@ -208,6 +232,8 @@ impl Engine { } } & FnType::InternalFn(ref f) => { + if f.params.len() != 2 { return Err(EvalAltResult::ErrorFunctionArgMismatch); } + let mut new_scope: Scope = Vec::new(); let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None); let result2 = self.call_fn("clone", Some(a2), None, None, None, None, None); @@ -216,14 +242,17 @@ impl Engine { new_scope.push((f.params[0].clone(), r1)); new_scope.push((f.params[1].clone(), r2)); }, - _ => return Err(EvalError::FunctionArgMismatch) + _ => return Err(EvalAltResult::ErrorFunctionArgMismatch) } - return self.eval_stmt(&mut new_scope, &*f.body); + match self.eval_stmt(&mut new_scope, &*f.body) { + Err(EvalAltResult::Return(x)) => return Ok(x), + x => return x + } } _ => () } } - return Err(EvalError::FunctionArgMismatch); + return Err(EvalAltResult::ErrorFunctionArgMismatch); } (Some(ref mut a1), None, None, None, None, None) => { for arr_f in *vf { @@ -235,20 +264,25 @@ impl Engine { } } & FnType::InternalFn(ref f) => { + if f.params.len() != 1 { return Err(EvalAltResult::ErrorFunctionArgMismatch); } + let mut new_scope: Scope = Vec::new(); let result1 = self.call_fn("clone", Some(a1), None, None, None, None, None); match result1 { Ok(r1) => { new_scope.push((f.params[0].clone(), r1)); }, - _ => return Err(EvalError::FunctionArgMismatch) + _ => return Err(EvalAltResult::ErrorFunctionArgMismatch) } - return self.eval_stmt(&mut new_scope, &*f.body); + match self.eval_stmt(&mut new_scope, &*f.body) { + Err(EvalAltResult::Return(x)) => return Ok(x), + x => return x + } } _ => () } } - return Err(EvalError::FunctionArgMismatch); + return Err(EvalAltResult::ErrorFunctionArgMismatch); } _ => { for arr_f in *vf { @@ -260,17 +294,22 @@ impl Engine { } } & FnType::InternalFn(ref f) => { + if f.params.len() != 0 { return Err(EvalAltResult::ErrorFunctionArgMismatch); } + let mut new_scope: Scope = Vec::new(); - return self.eval_stmt(&mut new_scope, &*f.body); + match self.eval_stmt(&mut new_scope, &*f.body) { + Err(EvalAltResult::Return(x)) => return Ok(x), + x => return x + } } _ => () } } - return Err(EvalError::FunctionArgMismatch); + return Err(EvalAltResult::ErrorFunctionArgMismatch); } } } - None => Err(EvalError::FunctionNotFound) + None => Err(EvalAltResult::ErrorFunctionNotFound) } } @@ -280,7 +319,7 @@ impl Engine { &(clone_helper as fn(T)->T).register(self, "clone"); } - fn eval_expr(&self, scope: &mut Scope, expr: &Expr) -> Result, EvalError> { + fn eval_expr(&self, scope: &mut Scope, expr: &Expr) -> Result, EvalAltResult> { match *expr { Expr::IntConst(i) => Ok(Box::new(i)), Expr::StringConst(ref s) => Ok(Box::new(s.clone())), @@ -290,7 +329,7 @@ impl Engine { return self.call_fn("clone", Some(val), None, None, None, None, None); } } - Err(EvalError::VariableNotFound) + Err(EvalAltResult::ErrorVariableNotFound) } Expr::Assignment(ref id, ref rhs) => { match **id { @@ -304,9 +343,9 @@ impl Engine { return Ok(Box::new(())); } } - Err(EvalError::VariableNotFound) + Err(EvalAltResult::ErrorVariableNotFound) } - _ => Err(EvalError::VariableNotFound) + _ => Err(EvalAltResult::ErrorVariableNotFound) } } Expr::FnCall(ref fn_name, ref args) => { @@ -361,7 +400,7 @@ impl Engine { Some(&mut arg5), Some(&mut arg6)) } else { - Err(EvalError::FunctionCallNotSupported) + Err(EvalAltResult::ErrorFunctionCallNotSupported) } } Expr::MethodCall(ref target, ref fn_name, ref args) => { @@ -371,7 +410,7 @@ impl Engine { return self.call_fn(&fn_name, Some(val), None, None, None, None, None); } } - Err(EvalError::VariableNotFound) + Err(EvalAltResult::ErrorVariableNotFound) } else if args.len() == 1 { let mut arg = try!(self.eval_expr(scope, &args[0])); @@ -381,7 +420,7 @@ impl Engine { return self.call_fn(&fn_name, Some(val), Some(&mut arg), None, None, None, None); } } - Err(EvalError::VariableNotFound) + Err(EvalAltResult::ErrorVariableNotFound) } else if args.len() == 2 { let mut arg1 = try!(self.eval_expr(scope, &args[0])); @@ -392,7 +431,7 @@ impl Engine { return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), None, None, None); } } - Err(EvalError::VariableNotFound) + Err(EvalAltResult::ErrorVariableNotFound) } else if args.len() == 3 { let mut arg1 = try!(self.eval_expr(scope, &args[0])); @@ -404,7 +443,7 @@ impl Engine { return self.call_fn(&fn_name, Some(val), Some(&mut arg1), Some(&mut arg2), Some(&mut arg3), None, None); } } - Err(EvalError::VariableNotFound) + Err(EvalAltResult::ErrorVariableNotFound) } else if args.len() == 4 { let mut arg1 = try!(self.eval_expr(scope, &args[0])); @@ -418,7 +457,7 @@ impl Engine { Some(&mut arg4), None); } } - Err(EvalError::VariableNotFound) + Err(EvalAltResult::ErrorVariableNotFound) } else if args.len() == 5 { let mut arg1 = try!(self.eval_expr(scope, &args[0])); @@ -433,10 +472,10 @@ impl Engine { Some(&mut arg4), Some(&mut arg5)); } } - Err(EvalError::VariableNotFound) + Err(EvalAltResult::ErrorVariableNotFound) } else { - Err(EvalError::FunctionCallNotSupported) + Err(EvalAltResult::ErrorFunctionCallNotSupported) } } Expr::True => { @@ -448,17 +487,21 @@ impl Engine { } } - fn eval_stmt(&self, scope: &mut Scope, stmt: &Stmt) -> Result, EvalError> { + fn eval_stmt(&self, scope: &mut Scope, stmt: &Stmt) -> Result, EvalAltResult> { match *stmt { Stmt::Expr(ref e) => { self.eval_expr(scope, e) } Stmt::Block(ref b) => { let prev_len = scope.len(); - let mut last_result : Result, EvalError> = Ok(Box::new(0)); + let mut last_result : Result, EvalAltResult> = Ok(Box::new(())); for s in b.iter() { - last_result = self.eval_stmt(scope, s) + last_result = self.eval_stmt(scope, s); + match last_result { + Err(x) => {last_result = Err(x); break}, + _ => () + } } while scope.len() > prev_len { @@ -478,7 +521,7 @@ impl Engine { Ok(Box::new(())) } } - Err(_) => Err(EvalError::IfGuardMismatch) + Err(_) => Err(EvalAltResult::ErrorIfGuardMismatch) } } Stmt::IfElse(ref guard, ref body, ref else_body) => { @@ -492,7 +535,7 @@ impl Engine { self.eval_stmt(scope, else_body) } } - Err(_) => Err(EvalError::IfGuardMismatch) + Err(_) => Err(EvalAltResult::ErrorIfGuardMismatch) } } Stmt::While(ref guard, ref body) => { @@ -501,16 +544,26 @@ impl Engine { match guard_result.downcast::() { Ok(g) => { if *g { - try!(self.eval_stmt(scope, body)); + match self.eval_stmt(scope, body) { + Err(EvalAltResult::LoopBreak) => { return Ok(Box::new(())); } + Err(x) => { return Err(x); } + _ => () + } } else { return Ok(Box::new(())); } } - Err(_) => return Err(EvalError::IfGuardMismatch) + Err(_) => return Err(EvalAltResult::ErrorIfGuardMismatch) } } } + Stmt::Break => return Err(EvalAltResult::LoopBreak), + Stmt::Return => return Err(EvalAltResult::Return(Box::new(()))), + Stmt::ReturnWithVal(ref a) => { + let result = try!(self.eval_expr(scope, a)); + return Err(EvalAltResult::Return(result)); + } Stmt::Var(ref name, ref init) => { match init { & Some(ref v) => { @@ -526,13 +579,13 @@ impl Engine { } } - pub fn eval(&mut self, input: String) -> Result, EvalError> { + pub fn eval(&mut self, input: String) -> Result, EvalAltResult> { let mut scope: Scope = Vec::new(); self.eval_with_scope(&mut scope, input) } - pub fn eval_with_scope(&mut self, scope: &mut Scope, input: String) -> Result, EvalError> { + pub fn eval_with_scope(&mut self, scope: &mut Scope, input: String) -> Result, EvalAltResult> { let tokens = lex(&input); let mut peekables = tokens.peekable(); @@ -540,11 +593,11 @@ impl Engine { match tree { Ok((ref os, ref fns)) => { - let mut x: Result, EvalError> = Ok(Box::new(())); + let mut x: Result, EvalAltResult> = Ok(Box::new(())); for f in fns { if f.params.len() > 6 { - return Err(EvalError::FunctionArityNotSupported); + return Err(EvalAltResult::ErrorFunctionArityNotSupported); } let name = f.name.clone(); let local_f = f.clone(); @@ -557,7 +610,7 @@ impl Engine { } x } - Err(_) => Err(EvalError::FunctionArgMismatch) + Err(_) => Err(EvalAltResult::ErrorFunctionArgMismatch) } } @@ -716,7 +769,18 @@ fn test_if() { } #[test] +fn test_while() { + let mut engine = Engine::new(); + if let Ok(result) = engine.eval("var x = 0; while x < 10 { x = x + 1; if x > 5 { break } } x".to_string()).unwrap().downcast::() { + assert_eq!(*result, 6); + } + else { + assert!(false); + } +} + +#[test] fn test_var_scope() { let mut engine = Engine::new(); let mut scope: Scope = Vec::new(); @@ -792,6 +856,13 @@ fn test_internal_fn() { else { assert!(false); } + + if let Ok(result) = engine.eval("fn bob() { return 4; 5 } bob()".to_string()).unwrap().downcast::() { + assert_eq!(*result, 4); + } + else { + assert!(false); + } } #[test] diff --git a/src/fn_register.rs b/src/fn_register.rs index c50af38b..1aeee4a1 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -1,7 +1,7 @@ use std::any::Any; use std::boxed::Box; -use engine::{EvalError, Engine, FnType}; +use engine::{EvalAltResult, Engine, FnType}; pub trait FnRegister { fn register(self, engine: &mut Engine, name: &str); @@ -10,7 +10,7 @@ pub trait FnRegister { impl FnRegister for fn(&mut T, U, V, W, X, Y)->Z { fn register(self, engine: &mut Engine, name: &str) { let wrapped : Box, &mut Box, &mut Box, &mut Box, &mut Box, - &mut Box)->Result, EvalError>> = + &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box, arg3: &mut Box, arg4: &mut Box, @@ -26,7 +26,7 @@ impl Ok(Box::new(self(b, c.clone(), d.clone(), e.clone(), f.clone(), g.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -39,7 +39,7 @@ impl FnRegister for fn(T, U, V, W, X, Y)->Z { fn register(self, engine: &mut Engine, name: &str) { let wrapped : Box, &mut Box, &mut Box, &mut Box, &mut Box, - &mut Box)->Result, EvalError>> = + &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box, arg3: &mut Box, arg4: &mut Box, @@ -55,7 +55,7 @@ impl Ok(Box::new(self(b.clone(), c.clone(), d.clone(), e.clone(), f.clone(), g.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -67,7 +67,7 @@ impl FnRegister for fn(&mut T, U, V, W, X)->Y { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>> = + let wrapped : Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box, arg3: &mut Box, arg4: &mut Box, arg5: &mut Box| { @@ -81,7 +81,7 @@ impl Ok(Box::new(self(b, c.clone(), d.clone(), e.clone(), f.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -93,7 +93,7 @@ impl FnRegister for fn(T, U, V, W, X)->Y { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>> = + let wrapped : Box, &mut Box, &mut Box, &mut Box, &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box, arg3: &mut Box, arg4: &mut Box, arg5: &mut Box| { @@ -107,7 +107,7 @@ impl Ok(Box::new(self(b.clone(), c.clone(), d.clone(), e.clone(), f.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -119,7 +119,7 @@ impl FnRegister for fn(&mut T, U, V, W)->X { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>> = + let wrapped : Box, &mut Box, &mut Box, &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box, arg3: &mut Box, arg4: &mut Box| { let inside1 = (*arg1).downcast_mut() as Option<&mut T>; @@ -129,7 +129,7 @@ impl FnReg match (inside1, inside2, inside3, inside4) { (Some(b), Some(c), Some(d), Some(e)) => Ok(Box::new(self(b, c.clone(), d.clone(), e.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -141,7 +141,7 @@ impl FnReg impl FnRegister for fn(T, U, V, W)->X { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box, &mut Box, &mut Box, &mut Box)->Result, EvalError>> = + let wrapped : Box, &mut Box, &mut Box, &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box, arg3: &mut Box, arg4: &mut Box| { let inside1 = (*arg1).downcast_mut() as Option<&mut T>; @@ -151,7 +151,7 @@ impl FnReg match (inside1, inside2, inside3, inside4) { (Some(b), Some(c), Some(d), Some(e)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone(), e.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -163,7 +163,7 @@ impl FnReg impl FnRegister for fn(&mut T, U, V)->W { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box, &mut Box, &mut Box)->Result, EvalError>> = + let wrapped : Box, &mut Box, &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box, arg3: &mut Box| { let inside1 = (*arg1).downcast_mut() as Option<&mut T>; @@ -172,7 +172,7 @@ impl FnRegister for fn(& match (inside1, inside2, inside3) { (Some(b), Some(c), Some(d)) => Ok(Box::new(self(b, c.clone(), d.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -184,7 +184,7 @@ impl FnRegister for fn(& impl FnRegister for fn(T, U, V)->W { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box, &mut Box, &mut Box)->Result, EvalError>> = + let wrapped : Box, &mut Box, &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box, arg3: &mut Box| { let inside1 = (*arg1).downcast_mut() as Option<&mut T>; @@ -193,7 +193,7 @@ impl FnRegister for fn(T match (inside1, inside2, inside3) { (Some(b), Some(c), Some(d)) => Ok(Box::new(self(b.clone(), c.clone(), d.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -205,7 +205,7 @@ impl FnRegister for fn(T impl FnRegister for fn(&mut T, U)->V { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box, &mut Box)->Result, EvalError>> = + let wrapped : Box, &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box| { let inside1 = (*arg1).downcast_mut() as Option<&mut T>; @@ -213,7 +213,7 @@ impl FnRegister for fn(&mut T, U)->V { match (inside1, inside2) { (Some(b), Some(c)) => Ok(Box::new(self(b, c.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -225,7 +225,7 @@ impl FnRegister for fn(&mut T, U)->V { impl FnRegister for fn(T, U)->V { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box, &mut Box)->Result, EvalError>> = + let wrapped : Box, &mut Box)->Result, EvalAltResult>> = Box::new( move |arg1: &mut Box, arg2: &mut Box| { let inside1 = (*arg1).downcast_mut() as Option<&mut T>; @@ -233,7 +233,7 @@ impl FnRegister for fn(T, U)->V { match (inside1, inside2) { (Some(b), Some(c)) => Ok(Box::new(self(b.clone(), c.clone())) as Box), - _ => Err(EvalError::FunctionArgMismatch) + _ => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -245,14 +245,14 @@ impl FnRegister for fn(T, U)->V { impl FnRegister for fn(&mut T)->U { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box)->Result, EvalError>> = + let wrapped : Box)->Result, EvalAltResult>> = Box::new( move |arg: &mut Box| { let inside = (*arg).downcast_mut() as Option<&mut T>; match inside { Some(b) => Ok(Box::new(self(b)) as Box), - None => Err(EvalError::FunctionArgMismatch) + None => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -264,13 +264,13 @@ impl FnRegister for fn(&mut T)->U { impl FnRegister for fn(T)->U { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : Box)->Result, EvalError>> = + let wrapped : Box)->Result, EvalAltResult>> = Box::new( move |arg: &mut Box| { let inside = (*arg).downcast_mut() as Option<&mut T>; match inside { Some(b) => Ok(Box::new(self(b.clone())) as Box), - None => Err(EvalError::FunctionArgMismatch) + None => Err(EvalAltResult::ErrorFunctionArgMismatch) } } ); @@ -282,7 +282,7 @@ impl FnRegister for fn(T)->U { impl FnRegister for fn()->T { fn register(self, engine: &mut Engine, name: &str) { - let wrapped : BoxResult, EvalError>> = + let wrapped : BoxResult, EvalAltResult>> = Box::new( move || { Ok(Box::new(self()) as Box) } ); diff --git a/src/main.rs b/src/main.rs index c5cfb599..31ded9a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,6 @@ mod parser; // * How it works // * Vectors // * Return -// * Break // * Tighten parser? // * Errors with positions? // * Remove empty box values? diff --git a/src/parser.rs b/src/parser.rs index ce624f4c..272ae8fa 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -85,7 +85,7 @@ pub struct FnDef { #[derive(Debug, Clone)] pub enum Stmt { If(Box, Box), IfElse(Box, Box, Box), While(Box, Box), - Var(String, Option>), Block(Box>), Expr(Box) } + Var(String, Option>), Block(Box>), Expr(Box), Break, Return, ReturnWithVal(Box) } #[derive(Debug, Clone)] pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(String, Box>), @@ -95,7 +95,7 @@ pub enum Expr { IntConst(i32), Identifier(String), StringConst(String), FnCall(S pub enum Token { IntConst(i32), Identifier(String), StringConst(String), LCurly, RCurly, LParen, RParen, LSquare, RSquare, Plus, Minus, Multiply, Divide, Semicolon, Colon, Comma, Period, Equals, True, False, Var, If, Else, While, LessThan, GreaterThan, Bang, LessThanEqual, GreaterThanEqual, EqualTo, NotEqualTo, Pipe, Or, Ampersand, And, Fn, - LexErr(LexError) } + Break, Return, LexErr(LexError) } pub struct TokenIterator<'a> { char_stream: Peekable> @@ -157,6 +157,12 @@ impl<'a> Iterator for TokenIterator<'a> { else if out == "while" { return Some(Token::While); } + else if out == "break" { + return Some(Token::Break); + } + else if out == "return" { + return Some(Token::Return); + } else if out == "fn" { return Some(Token::Fn); } @@ -569,6 +575,14 @@ fn parse_stmt<'a>(input: &mut Peekable>) -> Result parse_if(input), Some(& Token::While) => parse_while(input), + Some(& Token::Break) => {input.next(); Ok(Stmt::Break)}, + Some(& Token::Return) => { + input.next(); + match input.peek() { + Some(& Token::Semicolon) => Ok(Stmt::Return), + _ => {let ret = try!(parse_expr(input)); Ok(Stmt::ReturnWithVal(Box::new(ret))) } + } + } Some(& Token::LCurly) => parse_block(input), Some(& Token::Var) => parse_var(input), _ => parse_expr_stmt(input)