From f5fff828e89d811c24b85121afd8bbeba35c6b13 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 18 Apr 2020 00:14:33 +0800 Subject: [PATCH] Box errors to reduce return type footprint. --- examples/repl.rs | 2 +- src/api.rs | 30 ++++-- src/engine.rs | 244 ++++++++++++++++++++++++--------------------- src/error.rs | 4 +- src/fn_register.rs | 8 +- src/optimize.rs | 2 +- src/parser.rs | 56 +++++------ src/result.rs | 12 ++- 8 files changed, 198 insertions(+), 160 deletions(-) diff --git a/examples/repl.rs b/examples/repl.rs index 3813d75d..4c807814 100644 --- a/examples/repl.rs +++ b/examples/repl.rs @@ -130,7 +130,7 @@ fn main() { match engine .compile_with_scope(&scope, &script) - .map_err(EvalAltResult::ErrorParsing) + .map_err(|err| err.into()) .and_then(|r| { ast_u = r.clone(); diff --git a/src/api.rs b/src/api.rs index 90a918c7..f410b815 100644 --- a/src/api.rs +++ b/src/api.rs @@ -396,7 +396,7 @@ impl Engine { ) -> Result { let scripts = [script]; let stream = lex(&scripts); - parse(&mut stream.peekable(), self, scope, optimization_level) + parse(&mut stream.peekable(), self, scope, optimization_level).map_err(|err| *err) } /// Read the contents of a file into a string. @@ -592,7 +592,9 @@ impl Engine { ) -> Result { let scripts = [script]; let stream = lex(&scripts); + parse_global_expr(&mut stream.peekable(), self, scope, self.optimization_level) + .map_err(|err| *err) } /// Evaluate a script file. @@ -798,7 +800,10 @@ impl Engine { scope: &mut Scope, ast: &AST, ) -> Result { - let result = self.eval_ast_with_scope_raw(scope, ast)?; + let result = self + .eval_ast_with_scope_raw(scope, ast) + .map_err(|err| *err)?; + let return_type = self.map_type_name(result.type_name()); return result.try_cast::().ok_or_else(|| { @@ -810,13 +815,13 @@ impl Engine { &self, scope: &mut Scope, ast: &AST, - ) -> Result { + ) -> Result> { ast.0 .iter() .try_fold(Dynamic::from_unit(), |_, stmt| { self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0) }) - .or_else(|err| match err { + .or_else(|err| match *err { EvalAltResult::Return(out, _) => Ok(out), _ => Err(err), }) @@ -875,11 +880,13 @@ impl Engine { .try_fold(Dynamic::from_unit(), |_, stmt| { self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0) }) - .map(|_| ()) - .or_else(|err| match err { - EvalAltResult::Return(_, _) => Ok(()), - _ => Err(err), - }) + .map_or_else( + |err| match *err { + EvalAltResult::Return(_, _) => Ok(()), + err => Err(err), + }, + |_| Ok(()), + ) } /// Call a script function defined in an `AST` with multiple arguments. @@ -930,7 +937,10 @@ impl Engine { let fn_lib = Some(ast.1.as_ref()); let pos = Position::none(); - let result = self.call_fn_raw(Some(scope), fn_lib, name, &mut args, None, pos, 0)?; + let result = self + .call_fn_raw(Some(scope), fn_lib, name, &mut args, None, pos, 0) + .map_err(|err| *err)?; + let return_type = self.map_type_name(result.type_name()); return result diff --git a/src/engine.rs b/src/engine.rs index e91489a4..6c8f1b3e 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -35,9 +35,10 @@ pub type Map = HashMap; pub type FnCallArgs<'a> = [&'a mut Dynamic]; #[cfg(feature = "sync")] -pub type FnAny = dyn Fn(&mut FnCallArgs, Position) -> Result + Send + Sync; +pub type FnAny = + dyn Fn(&mut FnCallArgs, Position) -> Result> + Send + Sync; #[cfg(not(feature = "sync"))] -pub type FnAny = dyn Fn(&mut FnCallArgs, Position) -> Result; +pub type FnAny = dyn Fn(&mut FnCallArgs, Position) -> Result>; #[cfg(feature = "sync")] type IteratorFn = dyn Fn(&Dynamic) -> Box> + Send + Sync; @@ -244,7 +245,7 @@ pub struct Engine { /// Maximum levels of call-stack to prevent infinite recursion. /// - /// Defaults to 32 for debug builds and 256 for non-debug builds. + /// Defaults to 28 for debug builds and 256 for non-debug builds. pub(crate) max_call_stack_depth: usize, } @@ -398,10 +399,10 @@ impl Engine { def_val: Option<&Dynamic>, pos: Position, level: usize, - ) -> Result { + ) -> Result> { // Check for stack overflow if level > self.max_call_stack_depth { - return Err(EvalAltResult::ErrorStackOverflow(pos)); + return Err(Box::new(EvalAltResult::ErrorStackOverflow(pos))); } #[cfg(feature = "no_function")] @@ -427,10 +428,10 @@ impl Engine { // Evaluate the function at one higher level of call depth let result = self .eval_stmt(scope, fn_lib, &fn_def.body, level + 1) - .or_else(|err| match err { + .or_else(|err| match *err { // Convert return statement to return value EvalAltResult::Return(x, _) => Ok(x), - err => Err(err.set_position(pos)), + err => Err(Box::new(err.set_position(pos))), }); scope.rewind(scope_len); @@ -453,19 +454,23 @@ impl Engine { // Evaluate the function at one higher level of call depth return self .eval_stmt(&mut scope, fn_lib, &fn_def.body, level + 1) - .or_else(|err| match err { + .or_else(|err| match *err { // Convert return statement to return value EvalAltResult::Return(x, _) => Ok(x), - err => Err(err.set_position(pos)), + err => Err(Box::new(err.set_position(pos))), }); } } } // Argument must be a string - fn cast_to_string(r: &Dynamic, pos: Position) -> Result<&str, EvalAltResult> { - r.as_str() - .map_err(|type_name| EvalAltResult::ErrorMismatchOutputType(type_name.into(), pos)) + fn cast_to_string(r: &Dynamic, pos: Position) -> Result<&str, Box> { + r.as_str().map_err(|type_name| { + Box::new(EvalAltResult::ErrorMismatchOutputType( + type_name.into(), + pos, + )) + }) } // Search built-in's and external functions @@ -499,10 +504,10 @@ impl Engine { .unwrap_or_else(|| Dynamic::from_unit())), // Getter function not found - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( format!("- property '{}' unknown or write-only", prop), pos, - )), + ))), }; } @@ -517,10 +522,10 @@ impl Engine { } // Setter function not found - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( format!("- property '{}' unknown or read-only", prop), pos, - )), + ))), }; } @@ -536,10 +541,10 @@ impl Engine { .map(|name| self.map_type_name(name)) .collect(); - Err(EvalAltResult::ErrorFunctionNotFound( + Err(Box::new(EvalAltResult::ErrorFunctionNotFound( format!("{} ({})", fn_name, types_list.join(", ")), pos, - )) + ))) } /// Chain-evaluate a dot setter. @@ -550,7 +555,7 @@ impl Engine { target: Target, dot_rhs: &Expr, level: usize, - ) -> Result { + ) -> Result> { match dot_rhs { // xxx.fn_name(arg_expr_list) Expr::FunctionCall(fn_name, arg_expr_list, def_val, pos) => { @@ -589,10 +594,10 @@ impl Engine { } // Syntax error _ => { - return Err(EvalAltResult::ErrorDotExpr( + return Err(Box::new(EvalAltResult::ErrorDotExpr( "".to_string(), dot_rhs.position(), - )) + ))) } }; @@ -625,10 +630,10 @@ impl Engine { } // Syntax error _ => { - return Err(EvalAltResult::ErrorDotExpr( + return Err(Box::new(EvalAltResult::ErrorDotExpr( "".to_string(), dot_rhs.position(), - )) + ))) } }; @@ -638,17 +643,17 @@ impl Engine { }) } // Syntax error - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( "".to_string(), dot_lhs.position(), - )), + ))), }, // Syntax error - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( "".to_string(), dot_rhs.position(), - )), + ))), } } @@ -660,7 +665,7 @@ impl Engine { dot_lhs: &Expr, dot_rhs: &Expr, level: usize, - ) -> Result { + ) -> Result> { match dot_lhs { // id.??? Expr::Variable(id, pos) => { @@ -685,10 +690,10 @@ impl Engine { if let Some(src) = src { match src.typ { ScopeEntryType::Constant => { - return Err(EvalAltResult::ErrorAssignmentToConstant( + return Err(Box::new(EvalAltResult::ErrorAssignmentToConstant( src.name.to_string(), idx_lhs.position(), - )); + ))); } ScopeEntryType::Normal => { @@ -718,10 +723,10 @@ impl Engine { scope: &'a Scope, id: &str, begin: Position, - ) -> Result<(ScopeSource<'a>, Dynamic), EvalAltResult> { + ) -> Result<(ScopeSource<'a>, Dynamic), Box> { scope .get(id) - .ok_or_else(|| EvalAltResult::ErrorVariableNotFound(id.into(), begin)) + .ok_or_else(|| Box::new(EvalAltResult::ErrorVariableNotFound(id.into(), begin))) } /// Get the value at the indexed position of a base type @@ -734,7 +739,7 @@ impl Engine { op_pos: Position, level: usize, only_index: bool, - ) -> Result<(Dynamic, IndexValue), EvalAltResult> { + ) -> Result<(Dynamic, IndexValue), Box> { let idx_pos = idx_expr.position(); let type_name = self.map_type_name(val.type_name()); @@ -758,9 +763,15 @@ impl Engine { IndexValue::from_num(index), ) }) - .ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), index, idx_pos)) + .ok_or_else(|| { + Box::new(EvalAltResult::ErrorArrayBounds(arr.len(), index, idx_pos)) + }) } else { - Err(EvalAltResult::ErrorArrayBounds(arr.len(), index, idx_pos)) + Err(Box::new(EvalAltResult::ErrorArrayBounds( + arr.len(), + index, + idx_pos, + ))) } } @@ -792,27 +803,27 @@ impl Engine { .as_int() .map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?; + let num_chars = s.chars().count(); + if index >= 0 { s.chars() .nth(index as usize) .map(|ch| (Dynamic::from_char(ch), IndexValue::from_num(index))) .ok_or_else(|| { - EvalAltResult::ErrorStringBounds(s.chars().count(), index, idx_pos) + Box::new(EvalAltResult::ErrorStringBounds(num_chars, index, idx_pos)) }) } else { - Err(EvalAltResult::ErrorStringBounds( - s.chars().count(), - index, - idx_pos, - )) + Err(Box::new(EvalAltResult::ErrorStringBounds( + num_chars, index, idx_pos, + ))) } } // Error - cannot be indexed - _ => Err(EvalAltResult::ErrorIndexingType( + _ => Err(Box::new(EvalAltResult::ErrorIndexingType( type_name.to_string(), op_pos, - )), + ))), } } @@ -825,7 +836,7 @@ impl Engine { idx_expr: &Expr, op_pos: Position, level: usize, - ) -> Result<(Option>, IndexValue, Dynamic), EvalAltResult> { + ) -> Result<(Option>, IndexValue, Dynamic), Box> { match lhs { // id[idx_expr] Expr::Variable(id, _) => { @@ -873,7 +884,7 @@ impl Engine { src: ScopeSource, idx: IndexValue, new_val: (Dynamic, Position), - ) -> Result { + ) -> Result> { let target = scope.get_mut(src); match target.get_mut() { @@ -908,7 +919,7 @@ impl Engine { idx: IndexValue, new_val: Dynamic, pos: Position, - ) -> Result { + ) -> Result> { match target.get_mut() { Union::Array(arr) => { arr[idx.as_num()] = new_val; @@ -940,7 +951,7 @@ impl Engine { dot_rhs: &Expr, new_val: (&mut Dynamic, Position), level: usize, - ) -> Result { + ) -> Result> { match dot_rhs { // xxx.id Expr::Property(id, pos) => { @@ -970,10 +981,10 @@ impl Engine { } // All others - syntax error for setters chain - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( "for assignment".to_string(), *op_pos, - )), + ))), }, // xxx.lhs.{...} @@ -1022,24 +1033,24 @@ impl Engine { } // All others - syntax error for setters chain - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( "for assignment".to_string(), *op_pos, - )), + ))), }, // All others - syntax error for setters chain - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( "for assignment".to_string(), lhs.position(), - )), + ))), }, // Syntax error - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( "for assignment".to_string(), dot_rhs.position(), - )), + ))), } } @@ -1053,16 +1064,15 @@ impl Engine { new_val: (&mut Dynamic, Position), op_pos: Position, level: usize, - ) -> Result { + ) -> Result> { match dot_lhs { // id.??? Expr::Variable(id, pos) => { let (src, mut target) = Self::search_scope(scope, id, *pos)?; match src.typ { - ScopeEntryType::Constant => Err(EvalAltResult::ErrorAssignmentToConstant( - id.to_string(), - op_pos, + ScopeEntryType::Constant => Err(Box::new( + EvalAltResult::ErrorAssignmentToConstant(id.to_string(), op_pos), )), _ => { // Avoid referencing scope which is used below as mut @@ -1093,10 +1103,10 @@ impl Engine { if let Some(src) = src { match src.typ { ScopeEntryType::Constant => { - return Err(EvalAltResult::ErrorAssignmentToConstant( + return Err(Box::new(EvalAltResult::ErrorAssignmentToConstant( src.name.to_string(), lhs.position(), - )); + ))); } ScopeEntryType::Normal => { @@ -1114,10 +1124,10 @@ impl Engine { } // Syntax error - _ => Err(EvalAltResult::ErrorDotExpr( + _ => Err(Box::new(EvalAltResult::ErrorDotExpr( "for assignment".to_string(), dot_lhs.position(), - )), + ))), } } @@ -1129,7 +1139,7 @@ impl Engine { lhs: &Expr, rhs: &Expr, level: usize, - ) -> Result { + ) -> Result> { let mut lhs_value = self.eval_expr(scope, fn_lib, lhs, level)?; let rhs_value = self.eval_expr(scope, fn_lib, rhs, level)?; @@ -1161,7 +1171,7 @@ impl Engine { Dynamic(Union::Char(c)) => { Ok(Dynamic::from_bool(rhs_value.contains_key(&c.to_string()))) } - _ => Err(EvalAltResult::ErrorInExpr(lhs.position())), + _ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))), } } Dynamic(Union::Str(rhs_value)) => { @@ -1169,10 +1179,10 @@ impl Engine { match lhs_value { Dynamic(Union::Str(s)) => Ok(Dynamic::from_bool(rhs_value.contains(&s))), Dynamic(Union::Char(c)) => Ok(Dynamic::from_bool(rhs_value.contains(c))), - _ => Err(EvalAltResult::ErrorInExpr(lhs.position())), + _ => Err(Box::new(EvalAltResult::ErrorInExpr(lhs.position()))), } } - _ => Err(EvalAltResult::ErrorInExpr(rhs.position())), + _ => Err(Box::new(EvalAltResult::ErrorInExpr(rhs.position()))), } } @@ -1183,7 +1193,7 @@ impl Engine { fn_lib: Option<&FunctionsLib>, expr: &Expr, level: usize, - ) -> Result { + ) -> Result> { match expr { Expr::IntegerConstant(i, _) => Ok(Dynamic::from_int(*i)), #[cfg(not(feature = "no_float"))] @@ -1204,10 +1214,10 @@ impl Engine { // name = rhs Expr::Variable(name, pos) => match scope.get(name) { None => { - return Err(EvalAltResult::ErrorVariableNotFound( + return Err(Box::new(EvalAltResult::ErrorVariableNotFound( name.to_string(), *pos, - )) + ))) } Some(( @@ -1231,10 +1241,10 @@ impl Engine { .. }, _, - )) => Err(EvalAltResult::ErrorAssignmentToConstant( + )) => Err(Box::new(EvalAltResult::ErrorAssignmentToConstant( name.to_string(), *op_pos, - )), + ))), }, // idx_lhs[idx_expr] = rhs @@ -1244,15 +1254,15 @@ impl Engine { self.eval_index_expr(scope, fn_lib, idx_lhs, idx_expr, *op_pos, level)?; match src.map(|x| x.typ) { - None => Err(EvalAltResult::ErrorAssignmentToUnknownLHS( + None => Err(Box::new(EvalAltResult::ErrorAssignmentToUnknownLHS( idx_lhs.position(), - )), + ))), Some(ScopeEntryType::Constant) => { - Err(EvalAltResult::ErrorAssignmentToConstant( + Err(Box::new(EvalAltResult::ErrorAssignmentToConstant( src.unwrap().name.to_string(), idx_lhs.position(), - )) + ))) } Some(ScopeEntryType::Normal) => Ok(Self::update_indexed_var_in_scope( @@ -1272,13 +1282,17 @@ impl Engine { } // Error assignment to constant - expr if expr.is_constant() => Err(EvalAltResult::ErrorAssignmentToConstant( - expr.get_constant_str(), - lhs.position(), - )), + expr if expr.is_constant() => { + Err(Box::new(EvalAltResult::ErrorAssignmentToConstant( + expr.get_constant_str(), + lhs.position(), + ))) + } // Syntax error - _ => Err(EvalAltResult::ErrorAssignmentToUnknownLHS(lhs.position())), + _ => Err(Box::new(EvalAltResult::ErrorAssignmentToUnknownLHS( + lhs.position(), + ))), } } @@ -1362,13 +1376,13 @@ impl Engine { script, OptimizationLevel::None, ) - .map_err(EvalAltResult::ErrorParsing)?; + .map_err(|err| EvalAltResult::ErrorParsing(Box::new(err)))?; // If new functions are defined within the eval string, it is an error if ast.1.len() > 0 { - return Err(EvalAltResult::ErrorParsing( + return Err(Box::new(EvalAltResult::ErrorParsing( ParseErrorType::WrongFnDefinition.into_err(pos), - )); + ))); } if let Some(lib) = fn_lib { @@ -1384,7 +1398,7 @@ impl Engine { // Evaluate the AST self.eval_ast_with_scope_raw(scope, &ast) - .map_err(|err| err.set_position(pos)) + .map_err(|err| Box::new(err.set_position(pos))) } // Normal function call @@ -1452,7 +1466,7 @@ impl Engine { fn_lib: Option<&FunctionsLib>, stmt: &Stmt, level: usize, - ) -> Result { + ) -> Result> { match stmt { // No-op Stmt::Noop(_) => Ok(Dynamic::from_unit()), @@ -1486,7 +1500,7 @@ impl Engine { Stmt::IfThenElse(guard, if_body, else_body) => self .eval_expr(scope, fn_lib, guard, level)? .as_bool() - .map_err(|_| EvalAltResult::ErrorLogicGuard(guard.position())) + .map_err(|_| Box::new(EvalAltResult::ErrorLogicGuard(guard.position()))) .and_then(|guard_val| { if guard_val { self.eval_stmt(scope, fn_lib, if_body, level) @@ -1500,26 +1514,32 @@ impl Engine { // While loop Stmt::While(guard, body) => loop { match self.eval_expr(scope, fn_lib, guard, level)?.as_bool() { - Ok(guard_val) if guard_val => { - match self.eval_stmt(scope, fn_lib, body, level) { - Ok(_) | Err(EvalAltResult::ErrorLoopBreak(false, _)) => (), - Err(EvalAltResult::ErrorLoopBreak(true, _)) => { + Ok(true) => match self.eval_stmt(scope, fn_lib, body, level) { + Ok(_) => (), + Err(err) => match *err { + EvalAltResult::ErrorLoopBreak(false, _) => (), + EvalAltResult::ErrorLoopBreak(true, _) => { return Ok(Dynamic::from_unit()) } - Err(x) => return Err(x), - } + _ => return Err(err), + }, + }, + Ok(false) => return Ok(Dynamic::from_unit()), + Err(_) => { + return Err(Box::new(EvalAltResult::ErrorLogicGuard(guard.position()))) } - Ok(_) => return Ok(Dynamic::from_unit()), - Err(_) => return Err(EvalAltResult::ErrorLogicGuard(guard.position())), } }, // Loop statement Stmt::Loop(body) => loop { match self.eval_stmt(scope, fn_lib, body, level) { - Ok(_) | Err(EvalAltResult::ErrorLoopBreak(false, _)) => (), - Err(EvalAltResult::ErrorLoopBreak(true, _)) => return Ok(Dynamic::from_unit()), - Err(x) => return Err(x), + Ok(_) => (), + Err(err) => match *err { + EvalAltResult::ErrorLoopBreak(false, _) => (), + EvalAltResult::ErrorLoopBreak(true, _) => return Ok(Dynamic::from_unit()), + _ => return Err(err), + }, } }, @@ -1543,48 +1563,50 @@ impl Engine { *scope.get_mut(entry) = a; match self.eval_stmt(scope, fn_lib, body, level) { - Ok(_) | Err(EvalAltResult::ErrorLoopBreak(false, _)) => (), - Err(EvalAltResult::ErrorLoopBreak(true, _)) => break, - Err(x) => return Err(x), + Ok(_) => (), + Err(err) => match *err { + EvalAltResult::ErrorLoopBreak(false, _) => (), + EvalAltResult::ErrorLoopBreak(true, _) => break, + _ => return Err(err), + }, } } scope.rewind(scope.len() - 1); Ok(Dynamic::from_unit()) } else { - Err(EvalAltResult::ErrorFor(expr.position())) + Err(Box::new(EvalAltResult::ErrorFor(expr.position()))) } } // Continue statement - Stmt::Continue(pos) => Err(EvalAltResult::ErrorLoopBreak(false, *pos)), + Stmt::Continue(pos) => Err(Box::new(EvalAltResult::ErrorLoopBreak(false, *pos))), // Break statement - Stmt::Break(pos) => Err(EvalAltResult::ErrorLoopBreak(true, *pos)), + Stmt::Break(pos) => Err(Box::new(EvalAltResult::ErrorLoopBreak(true, *pos))), // Empty return Stmt::ReturnWithVal(None, ReturnType::Return, pos) => { - Err(EvalAltResult::Return(Dynamic::from_unit(), *pos)) + Err(Box::new(EvalAltResult::Return(Dynamic::from_unit(), *pos))) } // Return value - Stmt::ReturnWithVal(Some(a), ReturnType::Return, pos) => Err(EvalAltResult::Return( - self.eval_expr(scope, fn_lib, a, level)?, - *pos, + Stmt::ReturnWithVal(Some(a), ReturnType::Return, pos) => Err(Box::new( + EvalAltResult::Return(self.eval_expr(scope, fn_lib, a, level)?, *pos), )), // Empty throw Stmt::ReturnWithVal(None, ReturnType::Exception, pos) => { - Err(EvalAltResult::ErrorRuntime("".into(), *pos)) + Err(Box::new(EvalAltResult::ErrorRuntime("".into(), *pos))) } // Throw value Stmt::ReturnWithVal(Some(a), ReturnType::Exception, pos) => { let val = self.eval_expr(scope, fn_lib, a, level)?; - Err(EvalAltResult::ErrorRuntime( + Err(Box::new(EvalAltResult::ErrorRuntime( val.take_string().unwrap_or_else(|_| "".to_string()), *pos, - )) + ))) } // Let statement diff --git a/src/error.rs b/src/error.rs index b3e6be13..4de71bbf 100644 --- a/src/error.rs +++ b/src/error.rs @@ -107,8 +107,8 @@ pub enum ParseErrorType { impl ParseErrorType { /// Make a `ParseError` using the current type and position. - pub(crate) fn into_err(self, pos: Position) -> ParseError { - ParseError(self, pos) + pub(crate) fn into_err(self, pos: Position) -> Box { + Box::new(ParseError(self, pos)) } } diff --git a/src/fn_register.rs b/src/fn_register.rs index 08bf9109..5941095e 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -156,7 +156,7 @@ macro_rules! def_register { const NUM_ARGS: usize = count_args!($($par)*); if args.len() != NUM_ARGS { - return Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos)); + return Err(Box::new(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos))); } #[allow(unused_variables, unused_mut)] @@ -194,7 +194,7 @@ macro_rules! def_register { const NUM_ARGS: usize = count_args!($($par)*); if args.len() != NUM_ARGS { - return Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos)); + return Err(Box::new(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos))); } #[allow(unused_variables, unused_mut)] @@ -231,7 +231,7 @@ macro_rules! def_register { const NUM_ARGS: usize = count_args!($($par)*); if args.len() != NUM_ARGS { - return Err(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos)); + return Err(Box::new(EvalAltResult::ErrorFunctionArgsMismatch(fn_name.clone(), NUM_ARGS, args.len(), pos))); } #[allow(unused_variables, unused_mut)] @@ -244,7 +244,7 @@ macro_rules! def_register { // Call the user-supplied function using ($clone) to // potentially clone the value, otherwise pass the reference. f($(($clone)($par)),*).map(|r| r.into_dynamic()) - .map_err(|err| err.set_position(pos)) + .map_err(|err| Box::new(err.set_position(pos))) }; self.register_fn_raw(name, vec![$(TypeId::of::<$par>()),*], Box::new(func)); } diff --git a/src/optimize.rs b/src/optimize.rs index 1e8161e7..d12b161a 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -114,7 +114,7 @@ fn call_fn( fn_name: &str, args: &mut FnCallArgs, pos: Position, -) -> Result, EvalAltResult> { +) -> Result, Box> { // Search built-in's and external functions functions .and_then(|f| f.get(&calc_fn_spec(fn_name, args.iter().map(|a| a.type_id())))) diff --git a/src/parser.rs b/src/parser.rs index d50a5a60..978de38d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -522,7 +522,7 @@ fn eat_token(input: &mut Peekable, token: Token) -> Position { } /// Match a particular token, consuming it if matched. -fn match_token(input: &mut Peekable, token: Token) -> Result { +fn match_token(input: &mut Peekable, token: Token) -> Result> { let (t, _) = input.peek().unwrap(); if *t == token { eat_token(input, token); @@ -537,7 +537,7 @@ fn parse_paren_expr<'a>( input: &mut Peekable>, begin: Position, allow_stmt_expr: bool, -) -> Result { +) -> Result> { if match_token(input, Token::RightParen)? { return Ok(Expr::Unit(begin)); } @@ -562,7 +562,7 @@ fn parse_call_expr<'a, S: Into> + Display>( input: &mut Peekable>, begin: Position, allow_stmt_expr: bool, -) -> Result { +) -> Result> { let mut args_expr_list = Vec::new(); match input.peek().unwrap() { @@ -618,7 +618,7 @@ fn parse_index_expr<'a>( input: &mut Peekable>, pos: Position, allow_stmt_expr: bool, -) -> Result { +) -> Result> { let idx_expr = parse_expr(input, allow_stmt_expr)?; // Check type of indexing - must be integer or string @@ -742,7 +742,7 @@ fn parse_array_literal<'a>( input: &mut Peekable>, begin: Position, allow_stmt_expr: bool, -) -> Result { +) -> Result> { let mut arr = Vec::new(); if !match_token(input, Token::RightBracket)? { @@ -780,7 +780,7 @@ fn parse_map_literal<'a>( input: &mut Peekable>, begin: Position, allow_stmt_expr: bool, -) -> Result { +) -> Result> { let mut map = Vec::new(); if !match_token(input, Token::RightBrace)? { @@ -857,7 +857,7 @@ fn parse_map_literal<'a>( fn parse_primary<'a>( input: &mut Peekable>, allow_stmt_expr: bool, -) -> Result { +) -> Result> { let (token, pos) = match input.peek().unwrap() { // { - block statement as expression (Token::LeftBrace, pos) if allow_stmt_expr => { @@ -921,7 +921,7 @@ fn parse_primary<'a>( fn parse_unary<'a>( input: &mut Peekable>, allow_stmt_expr: bool, -) -> Result { +) -> Result> { match input.peek().unwrap() { // If statement is allowed to act as expressions (Token::If, pos) => { @@ -986,9 +986,9 @@ fn parse_unary<'a>( } /// Parse an assignment. -fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result { +fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result> { // Is the LHS in a valid format for an assignment target? - fn valid_assignment_chain(expr: &Expr, is_top: bool) -> Option { + fn valid_assignment_chain(expr: &Expr, is_top: bool) -> Option> { match expr { // var Expr::Variable(_, _) => { @@ -1056,7 +1056,7 @@ fn parse_op_assignment>>( lhs: Expr, rhs: Expr, pos: Position, -) -> Result { +) -> Result> { let lhs_copy = lhs.clone(); // lhs op= rhs -> lhs = op(lhs, rhs) @@ -1068,7 +1068,7 @@ fn parse_op_assignment>>( } /// Parse an 'in' expression. -fn parse_in_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result { +fn parse_in_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result> { match (&lhs, &rhs) { (_, Expr::IntegerConstant(_, pos)) | (_, Expr::FloatConstant(_, pos)) @@ -1202,7 +1202,7 @@ fn parse_binary_op<'a>( parent_precedence: u8, lhs: Expr, allow_stmt_expr: bool, -) -> Result { +) -> Result> { let mut current_lhs = lhs; loop { @@ -1253,7 +1253,7 @@ fn parse_binary_op<'a>( #[cfg(not(feature = "no_object"))] Token::Period => { - fn check_property(expr: Expr) -> Result { + fn check_property(expr: Expr) -> Result> { match expr { // xxx.lhs.rhs Expr::Dot(lhs, rhs, pos) => Ok(Expr::Dot( @@ -1353,7 +1353,7 @@ fn parse_binary_op<'a>( fn parse_expr<'a>( input: &mut Peekable>, allow_stmt_expr: bool, -) -> Result { +) -> Result> { // Parse a real expression let lhs = parse_unary(input, allow_stmt_expr)?; parse_binary_op(input, 1, lhs, allow_stmt_expr) @@ -1363,7 +1363,7 @@ fn parse_expr<'a>( fn ensure_not_statement_expr<'a>( input: &mut Peekable>, type_name: &str, -) -> Result<(), ParseError> { +) -> Result<(), Box> { match input.peek().unwrap() { // Disallow statement expressions (Token::LeftBrace, pos) | (Token::EOF, pos) => { @@ -1379,7 +1379,7 @@ fn parse_if<'a>( input: &mut Peekable>, breakable: bool, allow_stmt_expr: bool, -) -> Result { +) -> Result> { // if ... eat_token(input, Token::If); @@ -1412,7 +1412,7 @@ fn parse_if<'a>( fn parse_while<'a>( input: &mut Peekable>, allow_stmt_expr: bool, -) -> Result { +) -> Result> { // while ... eat_token(input, Token::While); @@ -1428,7 +1428,7 @@ fn parse_while<'a>( fn parse_loop<'a>( input: &mut Peekable>, allow_stmt_expr: bool, -) -> Result { +) -> Result> { // loop ... eat_token(input, Token::Loop); @@ -1442,7 +1442,7 @@ fn parse_loop<'a>( fn parse_for<'a>( input: &mut Peekable>, allow_stmt_expr: bool, -) -> Result { +) -> Result> { // for ... eat_token(input, Token::For); @@ -1482,7 +1482,7 @@ fn parse_let<'a>( input: &mut Peekable>, var_type: ScopeEntryType, allow_stmt_expr: bool, -) -> Result { +) -> Result> { // let/const... (specified in `var_type`) input.next(); @@ -1521,7 +1521,7 @@ fn parse_block<'a>( input: &mut Peekable>, breakable: bool, allow_stmt_expr: bool, -) -> Result { +) -> Result> { // Must start with { let pos = match input.next().unwrap() { (Token::LeftBrace, pos) => pos, @@ -1575,7 +1575,7 @@ fn parse_block<'a>( fn parse_expr_stmt<'a>( input: &mut Peekable>, allow_stmt_expr: bool, -) -> Result { +) -> Result> { Ok(Stmt::Expr(Box::new(parse_expr(input, allow_stmt_expr)?))) } @@ -1584,7 +1584,7 @@ fn parse_stmt<'a>( input: &mut Peekable>, breakable: bool, allow_stmt_expr: bool, -) -> Result { +) -> Result> { let (token, pos) = match input.peek().unwrap() { (Token::EOF, pos) => return Ok(Stmt::Noop(*pos)), x => x, @@ -1649,7 +1649,7 @@ fn parse_stmt<'a>( fn parse_fn<'a>( input: &mut Peekable>, allow_stmt_expr: bool, -) -> Result { +) -> Result> { let pos = input.next().expect("should be fn").1; let name = match input.next().unwrap() { @@ -1721,7 +1721,7 @@ pub fn parse_global_expr<'a>( engine: &Engine, scope: &Scope, optimization_level: OptimizationLevel, -) -> Result { +) -> Result> { let expr = parse_expr(input, false)?; match input.peek().unwrap() { @@ -1747,7 +1747,7 @@ pub fn parse_global_expr<'a>( /// Parse the global level statements. fn parse_global_level<'a>( input: &mut Peekable>, -) -> Result<(Vec, HashMap), ParseError> { +) -> Result<(Vec, HashMap), Box> { let mut statements = Vec::::new(); let mut functions = HashMap::::new(); @@ -1800,7 +1800,7 @@ pub fn parse<'a>( engine: &Engine, scope: &Scope, optimization_level: OptimizationLevel, -) -> Result { +) -> Result> { let (statements, functions) = parse_global_level(input)?; let fn_lib = functions.into_iter().map(|(_, v)| v).collect(); diff --git a/src/result.rs b/src/result.rs index 9d443f82..21fe7ef8 100644 --- a/src/result.rs +++ b/src/result.rs @@ -22,7 +22,7 @@ use crate::stdlib::path::PathBuf; #[derive(Debug)] pub enum EvalAltResult { /// Syntax error. - ErrorParsing(ParseError), + ErrorParsing(Box), /// Error reading from a script file. Wrapped value is the path of the script file. /// @@ -230,6 +230,11 @@ impl fmt::Display for EvalAltResult { impl From for EvalAltResult { fn from(err: ParseError) -> Self { + Self::ErrorParsing(Box::new(err)) + } +} +impl From> for EvalAltResult { + fn from(err: Box) -> Self { Self::ErrorParsing(err) } } @@ -280,8 +285,9 @@ impl EvalAltResult { #[cfg(not(feature = "no_std"))] Self::ErrorReadingScriptFile(_, _) => (), - Self::ErrorParsing(ParseError(_, pos)) - | Self::ErrorFunctionNotFound(_, pos) + Self::ErrorParsing(err) => err.1 = new_position, + + Self::ErrorFunctionNotFound(_, pos) | Self::ErrorFunctionArgsMismatch(_, _, _, pos) | Self::ErrorBooleanArgMismatch(_, pos) | Self::ErrorCharMismatch(pos)