Box errors to reduce return type footprint.
This commit is contained in:
parent
4a80997d6c
commit
f5fff828e8
@ -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();
|
||||||
|
|
||||||
|
28
src/api.rs
28
src/api.rs
@ -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
|
||||||
|
240
src/engine.rs
240
src/engine.rs
@ -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
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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()))))
|
||||||
|
@ -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();
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user