diff --git a/examples/custom_types_and_methods.rs b/examples/custom_types_and_methods.rs index 0fce4043..03be0cf1 100644 --- a/examples/custom_types_and_methods.rs +++ b/examples/custom_types_and_methods.rs @@ -24,7 +24,7 @@ fn main() { engine.register_fn("update", TestStruct::update); engine.register_fn("new_ts", TestStruct::new); - if let Ok(result) = engine.eval("var x = new_ts(); x.update(); x").unwrap().downcast::() { + if let Ok(result) = engine.eval::("var x = new_ts(); x.update(); x") { println!("result: {}", result.x); // prints 1001 } } \ No newline at end of file diff --git a/examples/hello.rs b/examples/hello.rs index 029fd925..d6f4e545 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -4,7 +4,7 @@ use rhai::Engine; fn main() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("40 + 2").unwrap().downcast::() { - println!("Answer: {}", *result); // prints 42 + if let Ok(result) = engine.eval::("40 + 2") { + println!("Answer: {}", result); // prints 42 } } \ No newline at end of file diff --git a/examples/reuse_scope.rs b/examples/reuse_scope.rs index 748ee0c6..70661ec4 100644 --- a/examples/reuse_scope.rs +++ b/examples/reuse_scope.rs @@ -5,9 +5,9 @@ fn main() { let mut engine = Engine::new(); let mut scope: Scope = Vec::new(); - if let Ok(_) = engine.eval_with_scope(&mut scope, "var x = 4 + 5") { } else { assert!(false); } + if let Ok(_) = engine.eval_with_scope::<()>(&mut scope, "var x = 4 + 5") { } else { assert!(false); } - if let Ok(result) = engine.eval_with_scope(&mut scope, "x").unwrap().downcast::() { + if let Ok(result) = engine.eval_with_scope::(&mut scope, "x") { println!("result: {}", result); } } diff --git a/examples/rhai_runner.rs b/examples/rhai_runner.rs index 80b1afd9..2a449f21 100644 --- a/examples/rhai_runner.rs +++ b/examples/rhai_runner.rs @@ -27,7 +27,7 @@ fn main() { let mut contents = String::new(); if let Ok(_) = f.read_to_string(&mut contents) { - match engine.eval(&contents) { + match engine.eval::<()>(&contents) { Ok(_) => (), Err(e) => {println!("Error: {:?}", e)} } diff --git a/examples/simple_fn.rs b/examples/simple_fn.rs index f8b56418..483d5c2a 100644 --- a/examples/simple_fn.rs +++ b/examples/simple_fn.rs @@ -10,7 +10,7 @@ fn main() { engine.register_fn("add", add); - if let Ok(result) = engine.eval("add(40, 2)").unwrap().downcast::() { - println!("Answer: {}", *result); // prints 42 + if let Ok(result) = engine.eval::("add(40, 2)") { + println!("Answer: {}", result); // prints 42 } } diff --git a/src/engine.rs b/src/engine.rs index 9e5c7a65..1ca95afd 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -19,7 +19,8 @@ pub enum EvalAltResult { ErrorVariableNotFound(String), ErrorFunctionArityNotSupported, ErrorAssignmentToUnknownLHS, - InternalErrorMalformedDotExpression, + ErrorMismatchOutputType, + InternalErrorMalformedDotExpression, LoopBreak, Return(Box) } @@ -34,6 +35,7 @@ impl Error for EvalAltResult { EvalAltResult::ErrorVariableNotFound(_) => "Variable not found", EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported", EvalAltResult::ErrorAssignmentToUnknownLHS => "Assignment to an unsupported left-hand side", + EvalAltResult::ErrorMismatchOutputType => "Cast of output failed", EvalAltResult::InternalErrorMalformedDotExpression => "[Internal error] Unexpected expression in dot expression", EvalAltResult::LoopBreak => "Loop broken before completion (not an error)", EvalAltResult::Return(_) => "Function returned value (not an error)" @@ -693,13 +695,13 @@ impl Engine { } } - pub fn eval(&mut self, input: &str) -> Result, EvalAltResult> { + pub fn eval(&mut self, input: &str) -> Result { let mut scope: Scope = Vec::new(); self.eval_with_scope(&mut scope, input) } - pub fn eval_with_scope(&mut self, scope: &mut Scope, input: &str) -> Result, EvalAltResult> { + pub fn eval_with_scope(&mut self, scope: &mut Scope, input: &str) -> Result { let tokens = lex(input); let mut peekables = tokens.peekable(); @@ -720,9 +722,21 @@ impl Engine { } for o in os { - x = self.eval_stmt(scope, &o); + x = match self.eval_stmt(scope, &o) { + Ok(v) => Ok(v), + Err(e) => return Err(e) + } + } + + match x { + Ok(v) => { + match v.downcast::() { + Ok(out) => Ok(*out), + Err(_) => Err(EvalAltResult::ErrorMismatchOutputType) + } + } + Err(e) => Err(e) } - x } Err(_) => Err(EvalAltResult::ErrorFunctionArgMismatch) } @@ -800,8 +814,8 @@ impl Engine { fn test_number_literal() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("65").unwrap().downcast::() { - assert_eq!(*result, 65); + if let Ok(result) = engine.eval::("65") { + assert_eq!(result, 65); } else { assert!(false); @@ -812,15 +826,15 @@ fn test_number_literal() { fn test_ops() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("60 + 5").unwrap().downcast::() { - assert_eq!(*result, 65); + if let Ok(result) = engine.eval::("60 + 5") { + assert_eq!(result, 65); } else { assert!(false); } - if let Ok(result) = engine.eval("(1 + 2) * (6 - 4) / 2").unwrap().downcast::() { - assert_eq!(*result, 3); + if let Ok(result) = engine.eval::("(1 + 2) * (6 - 4) / 2") { + assert_eq!(result, 3); } else { assert!(false); @@ -831,8 +845,8 @@ fn test_ops() { fn test_bool_op1() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("true && (false || true)").unwrap().downcast::() { - assert_eq!(*result, true); + if let Ok(result) = engine.eval::("true && (false || true)") { + assert_eq!(result, true); } else { assert!(false); @@ -843,8 +857,8 @@ fn test_bool_op1() { fn test_bool_op2() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("false && (false || true)").unwrap().downcast::() { - assert_eq!(*result, false); + if let Ok(result) = engine.eval::("false && (false || true)") { + assert_eq!(result, false); } else { assert!(false); @@ -855,8 +869,8 @@ fn test_bool_op2() { fn test_op_prec() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("var x = 0; if x == 10 || true { x = 1} x").unwrap().downcast::() { - assert_eq!(*result, 1); + if let Ok(result) = engine.eval::("var x = 0; if x == 10 || true { x = 1} x") { + assert_eq!(result, 1); } else { assert!(false); @@ -867,22 +881,22 @@ fn test_op_prec() { fn test_if() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("if true { 55 }").unwrap().downcast::() { - assert_eq!(*result, 55); + if let Ok(result) = engine.eval::("if true { 55 }") { + assert_eq!(result, 55); } else { assert!(false); } - if let Ok(result) = engine.eval("if false { 55 } else { 44 }").unwrap().downcast::() { - assert_eq!(*result, 44); + if let Ok(result) = engine.eval::("if false { 55 } else { 44 }") { + assert_eq!(result, 44); } else { assert!(false); } - if let Ok(result) = engine.eval("if true { 55 } else { 44 }").unwrap().downcast::() { - assert_eq!(*result, 55); + if let Ok(result) = engine.eval::("if true { 55 } else { 44 }") { + assert_eq!(result, 55); } else { assert!(false); @@ -893,8 +907,8 @@ fn test_if() { 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").unwrap().downcast::() { - assert_eq!(*result, 6); + if let Ok(result) = engine.eval::("var x = 0; while x < 10 { x = x + 1; if x > 5 { break } } x") { + assert_eq!(result, 6); } else { assert!(false); @@ -906,28 +920,28 @@ fn test_var_scope() { let mut engine = Engine::new(); let mut scope: Scope = Vec::new(); - if let Ok(_) = engine.eval_with_scope(&mut scope, "var x = 4 + 5") { } else { assert!(false); } + if let Ok(_) = engine.eval_with_scope::<()>(&mut scope, "var x = 4 + 5") { } else { assert!(false); } - if let Ok(result) = engine.eval_with_scope(&mut scope, "x").unwrap().downcast::() { - assert_eq!(*result, 9); + if let Ok(result) = engine.eval_with_scope::(&mut scope, "x") { + assert_eq!(result, 9); } else { assert!(false); } - if let Ok(_) = engine.eval_with_scope(&mut scope, "x = x + 1; x = x + 2;") { } else { assert!(false); } + if let Ok(_) = engine.eval_with_scope::<()>(&mut scope, "x = x + 1; x = x + 2;") { } else { assert!(false); } - if let Ok(result) = engine.eval_with_scope(&mut scope, "x").unwrap().downcast::() { - assert_eq!(*result, 12); + if let Ok(result) = engine.eval_with_scope::(&mut scope, "x") { + assert_eq!(result, 12); } else { assert!(false); } - if let Ok(_) = engine.eval_with_scope(&mut scope, "{var x = 3}") { } else { assert!(false); } + if let Ok(_) = engine.eval_with_scope::<()>(&mut scope, "{var x = 3}") { } else { assert!(false); } - if let Ok(result) = engine.eval_with_scope(&mut scope, "x").unwrap().downcast::() { - assert_eq!(*result, 12); + if let Ok(result) = engine.eval_with_scope::(&mut scope, "x") { + assert_eq!(result, 12); } else { assert!(false); @@ -958,7 +972,7 @@ fn test_method_call() { engine.register_fn("update", TestStruct::update); engine.register_fn("new_ts", TestStruct::new); - if let Ok(result) = engine.eval("var x = new_ts(); x.update(); x").unwrap().downcast::() { + if let Ok(result) = engine.eval::("var x = new_ts(); x.update(); x") { assert_eq!(result.x, 1001); } else { @@ -996,8 +1010,8 @@ fn test_get_set() { engine.register_fn("set$x", TestStruct::set_x); engine.register_fn("new_ts", TestStruct::new); - if let Ok(result) = engine.eval("var a = new_ts(); a.x = 500; a.x").unwrap().downcast::() { - assert_eq!(*result, 500); + if let Ok(result) = engine.eval::("var a = new_ts(); a.x = 500; a.x") { + assert_eq!(result, 500); } else { assert!(false); @@ -1056,8 +1070,8 @@ fn test_big_get_set() { engine.register_fn("set$child", TestParent::set_child); engine.register_fn("new_tp", TestParent::new); - if let Ok(result) = engine.eval("var a = new_tp(); a.child.x = 500; a.child.x").unwrap().downcast::() { - assert_eq!(*result, 500); + if let Ok(result) = engine.eval::("var a = new_tp(); a.child.x = 500; a.child.x") { + assert_eq!(result, 500); } else { assert!(false); @@ -1068,15 +1082,15 @@ fn test_big_get_set() { fn test_internal_fn() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("fn addme(a, b) { a+b } addme(3, 4)").unwrap().downcast::() { - assert_eq!(*result, 7); + if let Ok(result) = engine.eval::("fn addme(a, b) { a+b } addme(3, 4)") { + assert_eq!(result, 7); } else { assert!(false); } - if let Ok(result) = engine.eval("fn bob() { return 4; 5 } bob()").unwrap().downcast::() { - assert_eq!(*result, 4); + if let Ok(result) = engine.eval::("fn bob() { return 4; 5 } bob()") { + assert_eq!(result, 4); } else { assert!(false); @@ -1087,8 +1101,8 @@ fn test_internal_fn() { fn test_big_internal_fn() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("fn mathme(a, b, c, d, e, f) { a - b * c + d * e - f } mathme(100, 5, 2, 9, 6, 32)").unwrap().downcast::() { - assert_eq!(*result, 112); + if let Ok(result) = engine.eval::("fn mathme(a, b, c, d, e, f) { a - b * c + d * e - f } mathme(100, 5, 2, 9, 6, 32)") { + assert_eq!(result, 112); } else { assert!(false); @@ -1099,8 +1113,8 @@ fn test_big_internal_fn() { fn test_string() { let mut engine = Engine::new(); - if let Ok(result) = engine.eval("\"Test string: \\u2764\"").unwrap().downcast::() { - assert_eq!(*result, "Test string: ❤"); + if let Ok(result) = engine.eval::("\"Test string: \\u2764\"") { + assert_eq!(result, "Test string: ❤"); } else { assert!(false);