Remove unbox/cast step in eval
This commit is contained in:
parent
254f4b081c
commit
cfac566425
@ -24,7 +24,7 @@ fn main() {
|
|||||||
engine.register_fn("update", TestStruct::update);
|
engine.register_fn("update", TestStruct::update);
|
||||||
engine.register_fn("new_ts", TestStruct::new);
|
engine.register_fn("new_ts", TestStruct::new);
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("var x = new_ts(); x.update(); x").unwrap().downcast::<TestStruct>() {
|
if let Ok(result) = engine.eval::<TestStruct>("var x = new_ts(); x.update(); x") {
|
||||||
println!("result: {}", result.x); // prints 1001
|
println!("result: {}", result.x); // prints 1001
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ use rhai::Engine;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("40 + 2").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("40 + 2") {
|
||||||
println!("Answer: {}", *result); // prints 42
|
println!("Answer: {}", result); // prints 42
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,9 +5,9 @@ fn main() {
|
|||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
let mut scope: Scope = Vec::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::<i32>() {
|
if let Ok(result) = engine.eval_with_scope::<i32>(&mut scope, "x") {
|
||||||
println!("result: {}", result);
|
println!("result: {}", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ fn main() {
|
|||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
|
|
||||||
if let Ok(_) = f.read_to_string(&mut contents) {
|
if let Ok(_) = f.read_to_string(&mut contents) {
|
||||||
match engine.eval(&contents) {
|
match engine.eval::<()>(&contents) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => {println!("Error: {:?}", e)}
|
Err(e) => {println!("Error: {:?}", e)}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ fn main() {
|
|||||||
|
|
||||||
engine.register_fn("add", add);
|
engine.register_fn("add", add);
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("add(40, 2)").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("add(40, 2)") {
|
||||||
println!("Answer: {}", *result); // prints 42
|
println!("Answer: {}", result); // prints 42
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
108
src/engine.rs
108
src/engine.rs
@ -19,7 +19,8 @@ pub enum EvalAltResult {
|
|||||||
ErrorVariableNotFound(String),
|
ErrorVariableNotFound(String),
|
||||||
ErrorFunctionArityNotSupported,
|
ErrorFunctionArityNotSupported,
|
||||||
ErrorAssignmentToUnknownLHS,
|
ErrorAssignmentToUnknownLHS,
|
||||||
InternalErrorMalformedDotExpression,
|
ErrorMismatchOutputType,
|
||||||
|
InternalErrorMalformedDotExpression,
|
||||||
LoopBreak,
|
LoopBreak,
|
||||||
Return(Box<Any>)
|
Return(Box<Any>)
|
||||||
}
|
}
|
||||||
@ -34,6 +35,7 @@ impl Error for EvalAltResult {
|
|||||||
EvalAltResult::ErrorVariableNotFound(_) => "Variable not found",
|
EvalAltResult::ErrorVariableNotFound(_) => "Variable not found",
|
||||||
EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported",
|
EvalAltResult::ErrorFunctionArityNotSupported => "Functions of more than 3 parameters are not yet supported",
|
||||||
EvalAltResult::ErrorAssignmentToUnknownLHS => "Assignment to an unsupported left-hand side",
|
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::InternalErrorMalformedDotExpression => "[Internal error] Unexpected expression in dot expression",
|
||||||
EvalAltResult::LoopBreak => "Loop broken before completion (not an error)",
|
EvalAltResult::LoopBreak => "Loop broken before completion (not an error)",
|
||||||
EvalAltResult::Return(_) => "Function returned value (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<Box<Any>, EvalAltResult> {
|
pub fn eval<T:Any+Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> {
|
||||||
let mut scope: Scope = Vec::new();
|
let mut scope: Scope = Vec::new();
|
||||||
|
|
||||||
self.eval_with_scope(&mut scope, input)
|
self.eval_with_scope(&mut scope, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_with_scope(&mut self, scope: &mut Scope, input: &str) -> Result<Box<Any>, EvalAltResult> {
|
pub fn eval_with_scope<T:Any+Clone>(&mut self, scope: &mut Scope, input: &str) -> Result<T, EvalAltResult> {
|
||||||
let tokens = lex(input);
|
let tokens = lex(input);
|
||||||
|
|
||||||
let mut peekables = tokens.peekable();
|
let mut peekables = tokens.peekable();
|
||||||
@ -720,9 +722,21 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for o in os {
|
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::<T>() {
|
||||||
|
Ok(out) => Ok(*out),
|
||||||
|
Err(_) => Err(EvalAltResult::ErrorMismatchOutputType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => Err(e)
|
||||||
}
|
}
|
||||||
x
|
|
||||||
}
|
}
|
||||||
Err(_) => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
Err(_) => Err(EvalAltResult::ErrorFunctionArgMismatch)
|
||||||
}
|
}
|
||||||
@ -800,8 +814,8 @@ impl Engine {
|
|||||||
fn test_number_literal() {
|
fn test_number_literal() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("65").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("65") {
|
||||||
assert_eq!(*result, 65);
|
assert_eq!(result, 65);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -812,15 +826,15 @@ fn test_number_literal() {
|
|||||||
fn test_ops() {
|
fn test_ops() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("60 + 5").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("60 + 5") {
|
||||||
assert_eq!(*result, 65);
|
assert_eq!(result, 65);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("(1 + 2) * (6 - 4) / 2").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("(1 + 2) * (6 - 4) / 2") {
|
||||||
assert_eq!(*result, 3);
|
assert_eq!(result, 3);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -831,8 +845,8 @@ fn test_ops() {
|
|||||||
fn test_bool_op1() {
|
fn test_bool_op1() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("true && (false || true)").unwrap().downcast::<bool>() {
|
if let Ok(result) = engine.eval::<bool>("true && (false || true)") {
|
||||||
assert_eq!(*result, true);
|
assert_eq!(result, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -843,8 +857,8 @@ fn test_bool_op1() {
|
|||||||
fn test_bool_op2() {
|
fn test_bool_op2() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("false && (false || true)").unwrap().downcast::<bool>() {
|
if let Ok(result) = engine.eval::<bool>("false && (false || true)") {
|
||||||
assert_eq!(*result, false);
|
assert_eq!(result, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -855,8 +869,8 @@ fn test_bool_op2() {
|
|||||||
fn test_op_prec() {
|
fn test_op_prec() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("var x = 0; if x == 10 || true { x = 1} x").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("var x = 0; if x == 10 || true { x = 1} x") {
|
||||||
assert_eq!(*result, 1);
|
assert_eq!(result, 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -867,22 +881,22 @@ fn test_op_prec() {
|
|||||||
fn test_if() {
|
fn test_if() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("if true { 55 }").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("if true { 55 }") {
|
||||||
assert_eq!(*result, 55);
|
assert_eq!(result, 55);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("if false { 55 } else { 44 }").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("if false { 55 } else { 44 }") {
|
||||||
assert_eq!(*result, 44);
|
assert_eq!(result, 44);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("if true { 55 } else { 44 }").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("if true { 55 } else { 44 }") {
|
||||||
assert_eq!(*result, 55);
|
assert_eq!(result, 55);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -893,8 +907,8 @@ fn test_if() {
|
|||||||
fn test_while() {
|
fn test_while() {
|
||||||
let mut engine = Engine::new();
|
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::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("var x = 0; while x < 10 { x = x + 1; if x > 5 { break } } x") {
|
||||||
assert_eq!(*result, 6);
|
assert_eq!(result, 6);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -906,28 +920,28 @@ fn test_var_scope() {
|
|||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
let mut scope: Scope = Vec::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::<i32>() {
|
if let Ok(result) = engine.eval_with_scope::<i32>(&mut scope, "x") {
|
||||||
assert_eq!(*result, 9);
|
assert_eq!(result, 9);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
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::<i32>() {
|
if let Ok(result) = engine.eval_with_scope::<i32>(&mut scope, "x") {
|
||||||
assert_eq!(*result, 12);
|
assert_eq!(result, 12);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
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::<i32>() {
|
if let Ok(result) = engine.eval_with_scope::<i32>(&mut scope, "x") {
|
||||||
assert_eq!(*result, 12);
|
assert_eq!(result, 12);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -958,7 +972,7 @@ fn test_method_call() {
|
|||||||
engine.register_fn("update", TestStruct::update);
|
engine.register_fn("update", TestStruct::update);
|
||||||
engine.register_fn("new_ts", TestStruct::new);
|
engine.register_fn("new_ts", TestStruct::new);
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("var x = new_ts(); x.update(); x").unwrap().downcast::<TestStruct>() {
|
if let Ok(result) = engine.eval::<TestStruct>("var x = new_ts(); x.update(); x") {
|
||||||
assert_eq!(result.x, 1001);
|
assert_eq!(result.x, 1001);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -996,8 +1010,8 @@ fn test_get_set() {
|
|||||||
engine.register_fn("set$x", TestStruct::set_x);
|
engine.register_fn("set$x", TestStruct::set_x);
|
||||||
engine.register_fn("new_ts", TestStruct::new);
|
engine.register_fn("new_ts", TestStruct::new);
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("var a = new_ts(); a.x = 500; a.x").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("var a = new_ts(); a.x = 500; a.x") {
|
||||||
assert_eq!(*result, 500);
|
assert_eq!(result, 500);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -1056,8 +1070,8 @@ fn test_big_get_set() {
|
|||||||
engine.register_fn("set$child", TestParent::set_child);
|
engine.register_fn("set$child", TestParent::set_child);
|
||||||
engine.register_fn("new_tp", TestParent::new);
|
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::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("var a = new_tp(); a.child.x = 500; a.child.x") {
|
||||||
assert_eq!(*result, 500);
|
assert_eq!(result, 500);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -1068,15 +1082,15 @@ fn test_big_get_set() {
|
|||||||
fn test_internal_fn() {
|
fn test_internal_fn() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("fn addme(a, b) { a+b } addme(3, 4)").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("fn addme(a, b) { a+b } addme(3, 4)") {
|
||||||
assert_eq!(*result, 7);
|
assert_eq!(result, 7);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("fn bob() { return 4; 5 } bob()").unwrap().downcast::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("fn bob() { return 4; 5 } bob()") {
|
||||||
assert_eq!(*result, 4);
|
assert_eq!(result, 4);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -1087,8 +1101,8 @@ fn test_internal_fn() {
|
|||||||
fn test_big_internal_fn() {
|
fn test_big_internal_fn() {
|
||||||
let mut engine = Engine::new();
|
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::<i32>() {
|
if let Ok(result) = engine.eval::<i32>("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);
|
assert_eq!(result, 112);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
@ -1099,8 +1113,8 @@ fn test_big_internal_fn() {
|
|||||||
fn test_string() {
|
fn test_string() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
if let Ok(result) = engine.eval("\"Test string: \\u2764\"").unwrap().downcast::<String>() {
|
if let Ok(result) = engine.eval::<String>("\"Test string: \\u2764\"") {
|
||||||
assert_eq!(*result, "Test string: ❤");
|
assert_eq!(result, "Test string: ❤");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert!(false);
|
assert!(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user