Box errors to reduce return type footprint.

This commit is contained in:
Stephen Chung 2020-04-18 00:14:33 +08:00
parent 4a80997d6c
commit f5fff828e8
8 changed files with 198 additions and 160 deletions

View File

@ -130,7 +130,7 @@ fn main() {
match engine match engine
.compile_with_scope(&scope, &script) .compile_with_scope(&scope, &script)
.map_err(EvalAltResult::ErrorParsing) .map_err(|err| err.into())
.and_then(|r| { .and_then(|r| {
ast_u = r.clone(); ast_u = r.clone();

View File

@ -396,7 +396,7 @@ impl Engine {
) -> Result<AST, ParseError> { ) -> Result<AST, ParseError> {
let scripts = [script]; let scripts = [script];
let stream = lex(&scripts); 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. /// Read the contents of a file into a string.
@ -592,7 +592,9 @@ impl Engine {
) -> Result<AST, ParseError> { ) -> Result<AST, ParseError> {
let scripts = [script]; let scripts = [script];
let stream = lex(&scripts); let stream = lex(&scripts);
parse_global_expr(&mut stream.peekable(), self, scope, self.optimization_level) parse_global_expr(&mut stream.peekable(), self, scope, self.optimization_level)
.map_err(|err| *err)
} }
/// Evaluate a script file. /// Evaluate a script file.
@ -798,7 +800,10 @@ impl Engine {
scope: &mut Scope, scope: &mut Scope,
ast: &AST, ast: &AST,
) -> Result<T, EvalAltResult> { ) -> Result<T, EvalAltResult> {
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()); let return_type = self.map_type_name(result.type_name());
return result.try_cast::<T>().ok_or_else(|| { return result.try_cast::<T>().ok_or_else(|| {
@ -810,13 +815,13 @@ impl Engine {
&self, &self,
scope: &mut Scope, scope: &mut Scope,
ast: &AST, ast: &AST,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
ast.0 ast.0
.iter() .iter()
.try_fold(Dynamic::from_unit(), |_, stmt| { .try_fold(Dynamic::from_unit(), |_, stmt| {
self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0) 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), EvalAltResult::Return(out, _) => Ok(out),
_ => Err(err), _ => Err(err),
}) })
@ -875,11 +880,13 @@ impl Engine {
.try_fold(Dynamic::from_unit(), |_, stmt| { .try_fold(Dynamic::from_unit(), |_, stmt| {
self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0) self.eval_stmt(scope, Some(ast.1.as_ref()), stmt, 0)
}) })
.map(|_| ()) .map_or_else(
.or_else(|err| match err { |err| match *err {
EvalAltResult::Return(_, _) => Ok(()), EvalAltResult::Return(_, _) => Ok(()),
_ => Err(err), err => Err(err),
}) },
|_| Ok(()),
)
} }
/// Call a script function defined in an `AST` with multiple arguments. /// 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 fn_lib = Some(ast.1.as_ref());
let pos = Position::none(); 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()); let return_type = self.map_type_name(result.type_name());
return result return result

View File

@ -35,9 +35,10 @@ pub type Map = HashMap<String, Dynamic>;
pub type FnCallArgs<'a> = [&'a mut Dynamic]; pub type FnCallArgs<'a> = [&'a mut Dynamic];
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
pub type FnAny = dyn Fn(&mut FnCallArgs, Position) -> Result<Dynamic, EvalAltResult> + Send + Sync; pub type FnAny =
dyn Fn(&mut FnCallArgs, Position) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync;
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
pub type FnAny = dyn Fn(&mut FnCallArgs, Position) -> Result<Dynamic, EvalAltResult>; pub type FnAny = dyn Fn(&mut FnCallArgs, Position) -> Result<Dynamic, Box<EvalAltResult>>;
#[cfg(feature = "sync")] #[cfg(feature = "sync")]
type IteratorFn = dyn Fn(&Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync; type IteratorFn = dyn Fn(&Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync;
@ -244,7 +245,7 @@ pub struct Engine {
/// Maximum levels of call-stack to prevent infinite recursion. /// 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, pub(crate) max_call_stack_depth: usize,
} }
@ -398,10 +399,10 @@ impl Engine {
def_val: Option<&Dynamic>, def_val: Option<&Dynamic>,
pos: Position, pos: Position,
level: usize, level: usize,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
// Check for stack overflow // Check for stack overflow
if level > self.max_call_stack_depth { if level > self.max_call_stack_depth {
return Err(EvalAltResult::ErrorStackOverflow(pos)); return Err(Box::new(EvalAltResult::ErrorStackOverflow(pos)));
} }
#[cfg(feature = "no_function")] #[cfg(feature = "no_function")]
@ -427,10 +428,10 @@ impl Engine {
// Evaluate the function at one higher level of call depth // Evaluate the function at one higher level of call depth
let result = self let result = self
.eval_stmt(scope, fn_lib, &fn_def.body, level + 1) .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 // Convert return statement to return value
EvalAltResult::Return(x, _) => Ok(x), EvalAltResult::Return(x, _) => Ok(x),
err => Err(err.set_position(pos)), err => Err(Box::new(err.set_position(pos))),
}); });
scope.rewind(scope_len); scope.rewind(scope_len);
@ -453,19 +454,23 @@ impl Engine {
// Evaluate the function at one higher level of call depth // Evaluate the function at one higher level of call depth
return self return self
.eval_stmt(&mut scope, fn_lib, &fn_def.body, level + 1) .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 // Convert return statement to return value
EvalAltResult::Return(x, _) => Ok(x), EvalAltResult::Return(x, _) => Ok(x),
err => Err(err.set_position(pos)), err => Err(Box::new(err.set_position(pos))),
}); });
} }
} }
} }
// Argument must be a string // Argument must be a string
fn cast_to_string(r: &Dynamic, pos: Position) -> Result<&str, EvalAltResult> { fn cast_to_string(r: &Dynamic, pos: Position) -> Result<&str, Box<EvalAltResult>> {
r.as_str() r.as_str().map_err(|type_name| {
.map_err(|type_name| EvalAltResult::ErrorMismatchOutputType(type_name.into(), pos)) Box::new(EvalAltResult::ErrorMismatchOutputType(
type_name.into(),
pos,
))
})
} }
// Search built-in's and external functions // Search built-in's and external functions
@ -499,10 +504,10 @@ impl Engine {
.unwrap_or_else(|| Dynamic::from_unit())), .unwrap_or_else(|| Dynamic::from_unit())),
// Getter function not found // Getter function not found
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
format!("- property '{}' unknown or write-only", prop), format!("- property '{}' unknown or write-only", prop),
pos, pos,
)), ))),
}; };
} }
@ -517,10 +522,10 @@ impl Engine {
} }
// Setter function not found // Setter function not found
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
format!("- property '{}' unknown or read-only", prop), format!("- property '{}' unknown or read-only", prop),
pos, pos,
)), ))),
}; };
} }
@ -536,10 +541,10 @@ impl Engine {
.map(|name| self.map_type_name(name)) .map(|name| self.map_type_name(name))
.collect(); .collect();
Err(EvalAltResult::ErrorFunctionNotFound( Err(Box::new(EvalAltResult::ErrorFunctionNotFound(
format!("{} ({})", fn_name, types_list.join(", ")), format!("{} ({})", fn_name, types_list.join(", ")),
pos, pos,
)) )))
} }
/// Chain-evaluate a dot setter. /// Chain-evaluate a dot setter.
@ -550,7 +555,7 @@ impl Engine {
target: Target, target: Target,
dot_rhs: &Expr, dot_rhs: &Expr,
level: usize, level: usize,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match dot_rhs { match dot_rhs {
// xxx.fn_name(arg_expr_list) // xxx.fn_name(arg_expr_list)
Expr::FunctionCall(fn_name, arg_expr_list, def_val, pos) => { Expr::FunctionCall(fn_name, arg_expr_list, def_val, pos) => {
@ -589,10 +594,10 @@ impl Engine {
} }
// Syntax error // Syntax error
_ => { _ => {
return Err(EvalAltResult::ErrorDotExpr( return Err(Box::new(EvalAltResult::ErrorDotExpr(
"".to_string(), "".to_string(),
dot_rhs.position(), dot_rhs.position(),
)) )))
} }
}; };
@ -625,10 +630,10 @@ impl Engine {
} }
// Syntax error // Syntax error
_ => { _ => {
return Err(EvalAltResult::ErrorDotExpr( return Err(Box::new(EvalAltResult::ErrorDotExpr(
"".to_string(), "".to_string(),
dot_rhs.position(), dot_rhs.position(),
)) )))
} }
}; };
@ -638,17 +643,17 @@ impl Engine {
}) })
} }
// Syntax error // Syntax error
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
"".to_string(), "".to_string(),
dot_lhs.position(), dot_lhs.position(),
)), ))),
}, },
// Syntax error // Syntax error
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
"".to_string(), "".to_string(),
dot_rhs.position(), dot_rhs.position(),
)), ))),
} }
} }
@ -660,7 +665,7 @@ impl Engine {
dot_lhs: &Expr, dot_lhs: &Expr,
dot_rhs: &Expr, dot_rhs: &Expr,
level: usize, level: usize,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match dot_lhs { match dot_lhs {
// id.??? // id.???
Expr::Variable(id, pos) => { Expr::Variable(id, pos) => {
@ -685,10 +690,10 @@ impl Engine {
if let Some(src) = src { if let Some(src) = src {
match src.typ { match src.typ {
ScopeEntryType::Constant => { ScopeEntryType::Constant => {
return Err(EvalAltResult::ErrorAssignmentToConstant( return Err(Box::new(EvalAltResult::ErrorAssignmentToConstant(
src.name.to_string(), src.name.to_string(),
idx_lhs.position(), idx_lhs.position(),
)); )));
} }
ScopeEntryType::Normal => { ScopeEntryType::Normal => {
@ -718,10 +723,10 @@ impl Engine {
scope: &'a Scope, scope: &'a Scope,
id: &str, id: &str,
begin: Position, begin: Position,
) -> Result<(ScopeSource<'a>, Dynamic), EvalAltResult> { ) -> Result<(ScopeSource<'a>, Dynamic), Box<EvalAltResult>> {
scope scope
.get(id) .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 /// Get the value at the indexed position of a base type
@ -734,7 +739,7 @@ impl Engine {
op_pos: Position, op_pos: Position,
level: usize, level: usize,
only_index: bool, only_index: bool,
) -> Result<(Dynamic, IndexValue), EvalAltResult> { ) -> Result<(Dynamic, IndexValue), Box<EvalAltResult>> {
let idx_pos = idx_expr.position(); let idx_pos = idx_expr.position();
let type_name = self.map_type_name(val.type_name()); let type_name = self.map_type_name(val.type_name());
@ -758,9 +763,15 @@ impl Engine {
IndexValue::from_num(index), 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 { } 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() .as_int()
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?; .map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_expr.position()))?;
let num_chars = s.chars().count();
if index >= 0 { if index >= 0 {
s.chars() s.chars()
.nth(index as usize) .nth(index as usize)
.map(|ch| (Dynamic::from_char(ch), IndexValue::from_num(index))) .map(|ch| (Dynamic::from_char(ch), IndexValue::from_num(index)))
.ok_or_else(|| { .ok_or_else(|| {
EvalAltResult::ErrorStringBounds(s.chars().count(), index, idx_pos) Box::new(EvalAltResult::ErrorStringBounds(num_chars, index, idx_pos))
}) })
} else { } else {
Err(EvalAltResult::ErrorStringBounds( Err(Box::new(EvalAltResult::ErrorStringBounds(
s.chars().count(), num_chars, index, idx_pos,
index, )))
idx_pos,
))
} }
} }
// Error - cannot be indexed // Error - cannot be indexed
_ => Err(EvalAltResult::ErrorIndexingType( _ => Err(Box::new(EvalAltResult::ErrorIndexingType(
type_name.to_string(), type_name.to_string(),
op_pos, op_pos,
)), ))),
} }
} }
@ -825,7 +836,7 @@ impl Engine {
idx_expr: &Expr, idx_expr: &Expr,
op_pos: Position, op_pos: Position,
level: usize, level: usize,
) -> Result<(Option<ScopeSource<'a>>, IndexValue, Dynamic), EvalAltResult> { ) -> Result<(Option<ScopeSource<'a>>, IndexValue, Dynamic), Box<EvalAltResult>> {
match lhs { match lhs {
// id[idx_expr] // id[idx_expr]
Expr::Variable(id, _) => { Expr::Variable(id, _) => {
@ -873,7 +884,7 @@ impl Engine {
src: ScopeSource, src: ScopeSource,
idx: IndexValue, idx: IndexValue,
new_val: (Dynamic, Position), new_val: (Dynamic, Position),
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
let target = scope.get_mut(src); let target = scope.get_mut(src);
match target.get_mut() { match target.get_mut() {
@ -908,7 +919,7 @@ impl Engine {
idx: IndexValue, idx: IndexValue,
new_val: Dynamic, new_val: Dynamic,
pos: Position, pos: Position,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match target.get_mut() { match target.get_mut() {
Union::Array(arr) => { Union::Array(arr) => {
arr[idx.as_num()] = new_val; arr[idx.as_num()] = new_val;
@ -940,7 +951,7 @@ impl Engine {
dot_rhs: &Expr, dot_rhs: &Expr,
new_val: (&mut Dynamic, Position), new_val: (&mut Dynamic, Position),
level: usize, level: usize,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match dot_rhs { match dot_rhs {
// xxx.id // xxx.id
Expr::Property(id, pos) => { Expr::Property(id, pos) => {
@ -970,10 +981,10 @@ impl Engine {
} }
// All others - syntax error for setters chain // All others - syntax error for setters chain
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
"for assignment".to_string(), "for assignment".to_string(),
*op_pos, *op_pos,
)), ))),
}, },
// xxx.lhs.{...} // xxx.lhs.{...}
@ -1022,24 +1033,24 @@ impl Engine {
} }
// All others - syntax error for setters chain // All others - syntax error for setters chain
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
"for assignment".to_string(), "for assignment".to_string(),
*op_pos, *op_pos,
)), ))),
}, },
// All others - syntax error for setters chain // All others - syntax error for setters chain
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
"for assignment".to_string(), "for assignment".to_string(),
lhs.position(), lhs.position(),
)), ))),
}, },
// Syntax error // Syntax error
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
"for assignment".to_string(), "for assignment".to_string(),
dot_rhs.position(), dot_rhs.position(),
)), ))),
} }
} }
@ -1053,16 +1064,15 @@ impl Engine {
new_val: (&mut Dynamic, Position), new_val: (&mut Dynamic, Position),
op_pos: Position, op_pos: Position,
level: usize, level: usize,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match dot_lhs { match dot_lhs {
// id.??? // id.???
Expr::Variable(id, pos) => { Expr::Variable(id, pos) => {
let (src, mut target) = Self::search_scope(scope, id, *pos)?; let (src, mut target) = Self::search_scope(scope, id, *pos)?;
match src.typ { match src.typ {
ScopeEntryType::Constant => Err(EvalAltResult::ErrorAssignmentToConstant( ScopeEntryType::Constant => Err(Box::new(
id.to_string(), EvalAltResult::ErrorAssignmentToConstant(id.to_string(), op_pos),
op_pos,
)), )),
_ => { _ => {
// Avoid referencing scope which is used below as mut // Avoid referencing scope which is used below as mut
@ -1093,10 +1103,10 @@ impl Engine {
if let Some(src) = src { if let Some(src) = src {
match src.typ { match src.typ {
ScopeEntryType::Constant => { ScopeEntryType::Constant => {
return Err(EvalAltResult::ErrorAssignmentToConstant( return Err(Box::new(EvalAltResult::ErrorAssignmentToConstant(
src.name.to_string(), src.name.to_string(),
lhs.position(), lhs.position(),
)); )));
} }
ScopeEntryType::Normal => { ScopeEntryType::Normal => {
@ -1114,10 +1124,10 @@ impl Engine {
} }
// Syntax error // Syntax error
_ => Err(EvalAltResult::ErrorDotExpr( _ => Err(Box::new(EvalAltResult::ErrorDotExpr(
"for assignment".to_string(), "for assignment".to_string(),
dot_lhs.position(), dot_lhs.position(),
)), ))),
} }
} }
@ -1129,7 +1139,7 @@ impl Engine {
lhs: &Expr, lhs: &Expr,
rhs: &Expr, rhs: &Expr,
level: usize, level: usize,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
let mut lhs_value = self.eval_expr(scope, fn_lib, lhs, level)?; let mut lhs_value = self.eval_expr(scope, fn_lib, lhs, level)?;
let rhs_value = self.eval_expr(scope, fn_lib, rhs, level)?; let rhs_value = self.eval_expr(scope, fn_lib, rhs, level)?;
@ -1161,7 +1171,7 @@ impl Engine {
Dynamic(Union::Char(c)) => { Dynamic(Union::Char(c)) => {
Ok(Dynamic::from_bool(rhs_value.contains_key(&c.to_string()))) 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)) => { Dynamic(Union::Str(rhs_value)) => {
@ -1169,10 +1179,10 @@ impl Engine {
match lhs_value { match lhs_value {
Dynamic(Union::Str(s)) => Ok(Dynamic::from_bool(rhs_value.contains(&s))), Dynamic(Union::Str(s)) => Ok(Dynamic::from_bool(rhs_value.contains(&s))),
Dynamic(Union::Char(c)) => Ok(Dynamic::from_bool(rhs_value.contains(c))), 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>, fn_lib: Option<&FunctionsLib>,
expr: &Expr, expr: &Expr,
level: usize, level: usize,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match expr { match expr {
Expr::IntegerConstant(i, _) => Ok(Dynamic::from_int(*i)), Expr::IntegerConstant(i, _) => Ok(Dynamic::from_int(*i)),
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
@ -1204,10 +1214,10 @@ impl Engine {
// name = rhs // name = rhs
Expr::Variable(name, pos) => match scope.get(name) { Expr::Variable(name, pos) => match scope.get(name) {
None => { None => {
return Err(EvalAltResult::ErrorVariableNotFound( return Err(Box::new(EvalAltResult::ErrorVariableNotFound(
name.to_string(), name.to_string(),
*pos, *pos,
)) )))
} }
Some(( Some((
@ -1231,10 +1241,10 @@ impl Engine {
.. ..
}, },
_, _,
)) => Err(EvalAltResult::ErrorAssignmentToConstant( )) => Err(Box::new(EvalAltResult::ErrorAssignmentToConstant(
name.to_string(), name.to_string(),
*op_pos, *op_pos,
)), ))),
}, },
// idx_lhs[idx_expr] = rhs // 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)?; self.eval_index_expr(scope, fn_lib, idx_lhs, idx_expr, *op_pos, level)?;
match src.map(|x| x.typ) { match src.map(|x| x.typ) {
None => Err(EvalAltResult::ErrorAssignmentToUnknownLHS( None => Err(Box::new(EvalAltResult::ErrorAssignmentToUnknownLHS(
idx_lhs.position(), idx_lhs.position(),
)), ))),
Some(ScopeEntryType::Constant) => { Some(ScopeEntryType::Constant) => {
Err(EvalAltResult::ErrorAssignmentToConstant( Err(Box::new(EvalAltResult::ErrorAssignmentToConstant(
src.unwrap().name.to_string(), src.unwrap().name.to_string(),
idx_lhs.position(), idx_lhs.position(),
)) )))
} }
Some(ScopeEntryType::Normal) => Ok(Self::update_indexed_var_in_scope( Some(ScopeEntryType::Normal) => Ok(Self::update_indexed_var_in_scope(
@ -1272,13 +1282,17 @@ impl Engine {
} }
// Error assignment to constant // Error assignment to constant
expr if expr.is_constant() => Err(EvalAltResult::ErrorAssignmentToConstant( expr if expr.is_constant() => {
Err(Box::new(EvalAltResult::ErrorAssignmentToConstant(
expr.get_constant_str(), expr.get_constant_str(),
lhs.position(), lhs.position(),
)), )))
}
// Syntax error // Syntax error
_ => Err(EvalAltResult::ErrorAssignmentToUnknownLHS(lhs.position())), _ => Err(Box::new(EvalAltResult::ErrorAssignmentToUnknownLHS(
lhs.position(),
))),
} }
} }
@ -1362,13 +1376,13 @@ impl Engine {
script, script,
OptimizationLevel::None, 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 new functions are defined within the eval string, it is an error
if ast.1.len() > 0 { if ast.1.len() > 0 {
return Err(EvalAltResult::ErrorParsing( return Err(Box::new(EvalAltResult::ErrorParsing(
ParseErrorType::WrongFnDefinition.into_err(pos), ParseErrorType::WrongFnDefinition.into_err(pos),
)); )));
} }
if let Some(lib) = fn_lib { if let Some(lib) = fn_lib {
@ -1384,7 +1398,7 @@ impl Engine {
// Evaluate the AST // Evaluate the AST
self.eval_ast_with_scope_raw(scope, &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 // Normal function call
@ -1452,7 +1466,7 @@ impl Engine {
fn_lib: Option<&FunctionsLib>, fn_lib: Option<&FunctionsLib>,
stmt: &Stmt, stmt: &Stmt,
level: usize, level: usize,
) -> Result<Dynamic, EvalAltResult> { ) -> Result<Dynamic, Box<EvalAltResult>> {
match stmt { match stmt {
// No-op // No-op
Stmt::Noop(_) => Ok(Dynamic::from_unit()), Stmt::Noop(_) => Ok(Dynamic::from_unit()),
@ -1486,7 +1500,7 @@ impl Engine {
Stmt::IfThenElse(guard, if_body, else_body) => self Stmt::IfThenElse(guard, if_body, else_body) => self
.eval_expr(scope, fn_lib, guard, level)? .eval_expr(scope, fn_lib, guard, level)?
.as_bool() .as_bool()
.map_err(|_| EvalAltResult::ErrorLogicGuard(guard.position())) .map_err(|_| Box::new(EvalAltResult::ErrorLogicGuard(guard.position())))
.and_then(|guard_val| { .and_then(|guard_val| {
if guard_val { if guard_val {
self.eval_stmt(scope, fn_lib, if_body, level) self.eval_stmt(scope, fn_lib, if_body, level)
@ -1500,26 +1514,32 @@ impl Engine {
// While loop // While loop
Stmt::While(guard, body) => loop { Stmt::While(guard, body) => loop {
match self.eval_expr(scope, fn_lib, guard, level)?.as_bool() { match self.eval_expr(scope, fn_lib, guard, level)?.as_bool() {
Ok(guard_val) if guard_val => { Ok(true) => match self.eval_stmt(scope, fn_lib, body, level) {
match self.eval_stmt(scope, fn_lib, body, level) { Ok(_) => (),
Ok(_) | Err(EvalAltResult::ErrorLoopBreak(false, _)) => (), Err(err) => match *err {
Err(EvalAltResult::ErrorLoopBreak(true, _)) => { EvalAltResult::ErrorLoopBreak(false, _) => (),
EvalAltResult::ErrorLoopBreak(true, _) => {
return Ok(Dynamic::from_unit()) 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 // Loop statement
Stmt::Loop(body) => loop { Stmt::Loop(body) => loop {
match self.eval_stmt(scope, fn_lib, body, level) { match self.eval_stmt(scope, fn_lib, body, level) {
Ok(_) | Err(EvalAltResult::ErrorLoopBreak(false, _)) => (), Ok(_) => (),
Err(EvalAltResult::ErrorLoopBreak(true, _)) => return Ok(Dynamic::from_unit()), Err(err) => match *err {
Err(x) => return Err(x), 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; *scope.get_mut(entry) = a;
match self.eval_stmt(scope, fn_lib, body, level) { match self.eval_stmt(scope, fn_lib, body, level) {
Ok(_) | Err(EvalAltResult::ErrorLoopBreak(false, _)) => (), Ok(_) => (),
Err(EvalAltResult::ErrorLoopBreak(true, _)) => break, Err(err) => match *err {
Err(x) => return Err(x), EvalAltResult::ErrorLoopBreak(false, _) => (),
EvalAltResult::ErrorLoopBreak(true, _) => break,
_ => return Err(err),
},
} }
} }
scope.rewind(scope.len() - 1); scope.rewind(scope.len() - 1);
Ok(Dynamic::from_unit()) Ok(Dynamic::from_unit())
} else { } else {
Err(EvalAltResult::ErrorFor(expr.position())) Err(Box::new(EvalAltResult::ErrorFor(expr.position())))
} }
} }
// Continue statement // Continue statement
Stmt::Continue(pos) => Err(EvalAltResult::ErrorLoopBreak(false, *pos)), Stmt::Continue(pos) => Err(Box::new(EvalAltResult::ErrorLoopBreak(false, *pos))),
// Break statement // Break statement
Stmt::Break(pos) => Err(EvalAltResult::ErrorLoopBreak(true, *pos)), Stmt::Break(pos) => Err(Box::new(EvalAltResult::ErrorLoopBreak(true, *pos))),
// Empty return // Empty return
Stmt::ReturnWithVal(None, ReturnType::Return, pos) => { Stmt::ReturnWithVal(None, ReturnType::Return, pos) => {
Err(EvalAltResult::Return(Dynamic::from_unit(), *pos)) Err(Box::new(EvalAltResult::Return(Dynamic::from_unit(), *pos)))
} }
// Return value // Return value
Stmt::ReturnWithVal(Some(a), ReturnType::Return, pos) => Err(EvalAltResult::Return( Stmt::ReturnWithVal(Some(a), ReturnType::Return, pos) => Err(Box::new(
self.eval_expr(scope, fn_lib, a, level)?, EvalAltResult::Return(self.eval_expr(scope, fn_lib, a, level)?, *pos),
*pos,
)), )),
// Empty throw // Empty throw
Stmt::ReturnWithVal(None, ReturnType::Exception, pos) => { Stmt::ReturnWithVal(None, ReturnType::Exception, pos) => {
Err(EvalAltResult::ErrorRuntime("".into(), *pos)) Err(Box::new(EvalAltResult::ErrorRuntime("".into(), *pos)))
} }
// Throw value // Throw value
Stmt::ReturnWithVal(Some(a), ReturnType::Exception, pos) => { Stmt::ReturnWithVal(Some(a), ReturnType::Exception, pos) => {
let val = self.eval_expr(scope, fn_lib, a, level)?; 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()), val.take_string().unwrap_or_else(|_| "".to_string()),
*pos, *pos,
)) )))
} }
// Let statement // Let statement

View File

@ -107,8 +107,8 @@ pub enum ParseErrorType {
impl ParseErrorType { impl ParseErrorType {
/// Make a `ParseError` using the current type and position. /// Make a `ParseError` using the current type and position.
pub(crate) fn into_err(self, pos: Position) -> ParseError { pub(crate) fn into_err(self, pos: Position) -> Box<ParseError> {
ParseError(self, pos) Box::new(ParseError(self, pos))
} }
} }

View File

@ -156,7 +156,7 @@ macro_rules! def_register {
const NUM_ARGS: usize = count_args!($($par)*); const NUM_ARGS: usize = count_args!($($par)*);
if args.len() != NUM_ARGS { 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)] #[allow(unused_variables, unused_mut)]
@ -194,7 +194,7 @@ macro_rules! def_register {
const NUM_ARGS: usize = count_args!($($par)*); const NUM_ARGS: usize = count_args!($($par)*);
if args.len() != NUM_ARGS { 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)] #[allow(unused_variables, unused_mut)]
@ -231,7 +231,7 @@ macro_rules! def_register {
const NUM_ARGS: usize = count_args!($($par)*); const NUM_ARGS: usize = count_args!($($par)*);
if args.len() != NUM_ARGS { 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)] #[allow(unused_variables, unused_mut)]
@ -244,7 +244,7 @@ macro_rules! def_register {
// Call the user-supplied function using ($clone) to // Call the user-supplied function using ($clone) to
// potentially clone the value, otherwise pass the reference. // potentially clone the value, otherwise pass the reference.
f($(($clone)($par)),*).map(|r| r.into_dynamic()) 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)); self.register_fn_raw(name, vec![$(TypeId::of::<$par>()),*], Box::new(func));
} }

View File

@ -114,7 +114,7 @@ fn call_fn(
fn_name: &str, fn_name: &str,
args: &mut FnCallArgs, args: &mut FnCallArgs,
pos: Position, pos: Position,
) -> Result<Option<Dynamic>, EvalAltResult> { ) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
// Search built-in's and external functions // Search built-in's and external functions
functions functions
.and_then(|f| f.get(&calc_fn_spec(fn_name, args.iter().map(|a| a.type_id())))) .and_then(|f| f.get(&calc_fn_spec(fn_name, args.iter().map(|a| a.type_id()))))

View File

@ -522,7 +522,7 @@ fn eat_token(input: &mut Peekable<TokenIterator>, token: Token) -> Position {
} }
/// Match a particular token, consuming it if matched. /// Match a particular token, consuming it if matched.
fn match_token(input: &mut Peekable<TokenIterator>, token: Token) -> Result<bool, ParseError> { fn match_token(input: &mut Peekable<TokenIterator>, token: Token) -> Result<bool, Box<ParseError>> {
let (t, _) = input.peek().unwrap(); let (t, _) = input.peek().unwrap();
if *t == token { if *t == token {
eat_token(input, token); eat_token(input, token);
@ -537,7 +537,7 @@ fn parse_paren_expr<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
begin: Position, begin: Position,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
if match_token(input, Token::RightParen)? { if match_token(input, Token::RightParen)? {
return Ok(Expr::Unit(begin)); return Ok(Expr::Unit(begin));
} }
@ -562,7 +562,7 @@ fn parse_call_expr<'a, S: Into<Cow<'static, str>> + Display>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
begin: Position, begin: Position,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
let mut args_expr_list = Vec::new(); let mut args_expr_list = Vec::new();
match input.peek().unwrap() { match input.peek().unwrap() {
@ -618,7 +618,7 @@ fn parse_index_expr<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
pos: Position, pos: Position,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
let idx_expr = parse_expr(input, allow_stmt_expr)?; let idx_expr = parse_expr(input, allow_stmt_expr)?;
// Check type of indexing - must be integer or string // Check type of indexing - must be integer or string
@ -742,7 +742,7 @@ fn parse_array_literal<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
begin: Position, begin: Position,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
let mut arr = Vec::new(); let mut arr = Vec::new();
if !match_token(input, Token::RightBracket)? { if !match_token(input, Token::RightBracket)? {
@ -780,7 +780,7 @@ fn parse_map_literal<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
begin: Position, begin: Position,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
let mut map = Vec::new(); let mut map = Vec::new();
if !match_token(input, Token::RightBrace)? { if !match_token(input, Token::RightBrace)? {
@ -857,7 +857,7 @@ fn parse_map_literal<'a>(
fn parse_primary<'a>( fn parse_primary<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
let (token, pos) = match input.peek().unwrap() { let (token, pos) = match input.peek().unwrap() {
// { - block statement as expression // { - block statement as expression
(Token::LeftBrace, pos) if allow_stmt_expr => { (Token::LeftBrace, pos) if allow_stmt_expr => {
@ -921,7 +921,7 @@ fn parse_primary<'a>(
fn parse_unary<'a>( fn parse_unary<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
match input.peek().unwrap() { match input.peek().unwrap() {
// If statement is allowed to act as expressions // If statement is allowed to act as expressions
(Token::If, pos) => { (Token::If, pos) => {
@ -986,9 +986,9 @@ fn parse_unary<'a>(
} }
/// Parse an assignment. /// Parse an assignment.
fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result<Expr, ParseError> { fn parse_assignment(lhs: Expr, rhs: Expr, pos: Position) -> Result<Expr, Box<ParseError>> {
// Is the LHS in a valid format for an assignment target? // Is the LHS in a valid format for an assignment target?
fn valid_assignment_chain(expr: &Expr, is_top: bool) -> Option<ParseError> { fn valid_assignment_chain(expr: &Expr, is_top: bool) -> Option<Box<ParseError>> {
match expr { match expr {
// var // var
Expr::Variable(_, _) => { Expr::Variable(_, _) => {
@ -1056,7 +1056,7 @@ fn parse_op_assignment<S: Into<Cow<'static, str>>>(
lhs: Expr, lhs: Expr,
rhs: Expr, rhs: Expr,
pos: Position, pos: Position,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
let lhs_copy = lhs.clone(); let lhs_copy = lhs.clone();
// lhs op= rhs -> lhs = op(lhs, rhs) // lhs op= rhs -> lhs = op(lhs, rhs)
@ -1068,7 +1068,7 @@ fn parse_op_assignment<S: Into<Cow<'static, str>>>(
} }
/// Parse an 'in' expression. /// Parse an 'in' expression.
fn parse_in_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result<Expr, ParseError> { fn parse_in_expr(lhs: Expr, rhs: Expr, op_pos: Position) -> Result<Expr, Box<ParseError>> {
match (&lhs, &rhs) { match (&lhs, &rhs) {
(_, Expr::IntegerConstant(_, pos)) (_, Expr::IntegerConstant(_, pos))
| (_, Expr::FloatConstant(_, pos)) | (_, Expr::FloatConstant(_, pos))
@ -1202,7 +1202,7 @@ fn parse_binary_op<'a>(
parent_precedence: u8, parent_precedence: u8,
lhs: Expr, lhs: Expr,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
let mut current_lhs = lhs; let mut current_lhs = lhs;
loop { loop {
@ -1253,7 +1253,7 @@ fn parse_binary_op<'a>(
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Token::Period => { Token::Period => {
fn check_property(expr: Expr) -> Result<Expr, ParseError> { fn check_property(expr: Expr) -> Result<Expr, Box<ParseError>> {
match expr { match expr {
// xxx.lhs.rhs // xxx.lhs.rhs
Expr::Dot(lhs, rhs, pos) => Ok(Expr::Dot( Expr::Dot(lhs, rhs, pos) => Ok(Expr::Dot(
@ -1353,7 +1353,7 @@ fn parse_binary_op<'a>(
fn parse_expr<'a>( fn parse_expr<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Expr, ParseError> { ) -> Result<Expr, Box<ParseError>> {
// Parse a real expression // Parse a real expression
let lhs = parse_unary(input, allow_stmt_expr)?; let lhs = parse_unary(input, allow_stmt_expr)?;
parse_binary_op(input, 1, lhs, 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>( fn ensure_not_statement_expr<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
type_name: &str, type_name: &str,
) -> Result<(), ParseError> { ) -> Result<(), Box<ParseError>> {
match input.peek().unwrap() { match input.peek().unwrap() {
// Disallow statement expressions // Disallow statement expressions
(Token::LeftBrace, pos) | (Token::EOF, pos) => { (Token::LeftBrace, pos) | (Token::EOF, pos) => {
@ -1379,7 +1379,7 @@ fn parse_if<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
breakable: bool, breakable: bool,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, Box<ParseError>> {
// if ... // if ...
eat_token(input, Token::If); eat_token(input, Token::If);
@ -1412,7 +1412,7 @@ fn parse_if<'a>(
fn parse_while<'a>( fn parse_while<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, Box<ParseError>> {
// while ... // while ...
eat_token(input, Token::While); eat_token(input, Token::While);
@ -1428,7 +1428,7 @@ fn parse_while<'a>(
fn parse_loop<'a>( fn parse_loop<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, Box<ParseError>> {
// loop ... // loop ...
eat_token(input, Token::Loop); eat_token(input, Token::Loop);
@ -1442,7 +1442,7 @@ fn parse_loop<'a>(
fn parse_for<'a>( fn parse_for<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, Box<ParseError>> {
// for ... // for ...
eat_token(input, Token::For); eat_token(input, Token::For);
@ -1482,7 +1482,7 @@ fn parse_let<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
var_type: ScopeEntryType, var_type: ScopeEntryType,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, Box<ParseError>> {
// let/const... (specified in `var_type`) // let/const... (specified in `var_type`)
input.next(); input.next();
@ -1521,7 +1521,7 @@ fn parse_block<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
breakable: bool, breakable: bool,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, Box<ParseError>> {
// Must start with { // Must start with {
let pos = match input.next().unwrap() { let pos = match input.next().unwrap() {
(Token::LeftBrace, pos) => pos, (Token::LeftBrace, pos) => pos,
@ -1575,7 +1575,7 @@ fn parse_block<'a>(
fn parse_expr_stmt<'a>( fn parse_expr_stmt<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, Box<ParseError>> {
Ok(Stmt::Expr(Box::new(parse_expr(input, allow_stmt_expr)?))) Ok(Stmt::Expr(Box::new(parse_expr(input, allow_stmt_expr)?)))
} }
@ -1584,7 +1584,7 @@ fn parse_stmt<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
breakable: bool, breakable: bool,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<Stmt, ParseError> { ) -> Result<Stmt, Box<ParseError>> {
let (token, pos) = match input.peek().unwrap() { let (token, pos) = match input.peek().unwrap() {
(Token::EOF, pos) => return Ok(Stmt::Noop(*pos)), (Token::EOF, pos) => return Ok(Stmt::Noop(*pos)),
x => x, x => x,
@ -1649,7 +1649,7 @@ fn parse_stmt<'a>(
fn parse_fn<'a>( fn parse_fn<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
allow_stmt_expr: bool, allow_stmt_expr: bool,
) -> Result<FnDef, ParseError> { ) -> Result<FnDef, Box<ParseError>> {
let pos = input.next().expect("should be fn").1; let pos = input.next().expect("should be fn").1;
let name = match input.next().unwrap() { let name = match input.next().unwrap() {
@ -1721,7 +1721,7 @@ pub fn parse_global_expr<'a>(
engine: &Engine, engine: &Engine,
scope: &Scope, scope: &Scope,
optimization_level: OptimizationLevel, optimization_level: OptimizationLevel,
) -> Result<AST, ParseError> { ) -> Result<AST, Box<ParseError>> {
let expr = parse_expr(input, false)?; let expr = parse_expr(input, false)?;
match input.peek().unwrap() { match input.peek().unwrap() {
@ -1747,7 +1747,7 @@ pub fn parse_global_expr<'a>(
/// Parse the global level statements. /// Parse the global level statements.
fn parse_global_level<'a>( fn parse_global_level<'a>(
input: &mut Peekable<TokenIterator<'a>>, input: &mut Peekable<TokenIterator<'a>>,
) -> Result<(Vec<Stmt>, HashMap<u64, FnDef>), ParseError> { ) -> Result<(Vec<Stmt>, HashMap<u64, FnDef>), Box<ParseError>> {
let mut statements = Vec::<Stmt>::new(); let mut statements = Vec::<Stmt>::new();
let mut functions = HashMap::<u64, FnDef>::new(); let mut functions = HashMap::<u64, FnDef>::new();
@ -1800,7 +1800,7 @@ pub fn parse<'a>(
engine: &Engine, engine: &Engine,
scope: &Scope, scope: &Scope,
optimization_level: OptimizationLevel, optimization_level: OptimizationLevel,
) -> Result<AST, ParseError> { ) -> Result<AST, Box<ParseError>> {
let (statements, functions) = parse_global_level(input)?; let (statements, functions) = parse_global_level(input)?;
let fn_lib = functions.into_iter().map(|(_, v)| v).collect(); let fn_lib = functions.into_iter().map(|(_, v)| v).collect();

View File

@ -22,7 +22,7 @@ use crate::stdlib::path::PathBuf;
#[derive(Debug)] #[derive(Debug)]
pub enum EvalAltResult { pub enum EvalAltResult {
/// Syntax error. /// Syntax error.
ErrorParsing(ParseError), ErrorParsing(Box<ParseError>),
/// Error reading from a script file. Wrapped value is the path of the script file. /// 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<ParseError> for EvalAltResult { impl From<ParseError> for EvalAltResult {
fn from(err: ParseError) -> Self { fn from(err: ParseError) -> Self {
Self::ErrorParsing(Box::new(err))
}
}
impl From<Box<ParseError>> for EvalAltResult {
fn from(err: Box<ParseError>) -> Self {
Self::ErrorParsing(err) Self::ErrorParsing(err)
} }
} }
@ -280,8 +285,9 @@ impl EvalAltResult {
#[cfg(not(feature = "no_std"))] #[cfg(not(feature = "no_std"))]
Self::ErrorReadingScriptFile(_, _) => (), Self::ErrorReadingScriptFile(_, _) => (),
Self::ErrorParsing(ParseError(_, pos)) Self::ErrorParsing(err) => err.1 = new_position,
| Self::ErrorFunctionNotFound(_, pos)
Self::ErrorFunctionNotFound(_, pos)
| Self::ErrorFunctionArgsMismatch(_, _, _, pos) | Self::ErrorFunctionArgsMismatch(_, _, _, pos)
| Self::ErrorBooleanArgMismatch(_, pos) | Self::ErrorBooleanArgMismatch(_, pos)
| Self::ErrorCharMismatch(pos) | Self::ErrorCharMismatch(pos)