Refine code.
This commit is contained in:
parent
01c0b51017
commit
c17dc34f86
79
src/api.rs
79
src/api.rs
@ -24,12 +24,7 @@ use crate::stdlib::{fs::File, io::prelude::*, path::PathBuf};
|
|||||||
|
|
||||||
impl<'e> Engine<'e> {
|
impl<'e> Engine<'e> {
|
||||||
/// Register a custom function.
|
/// Register a custom function.
|
||||||
pub(crate) fn register_fn_raw(
|
pub(crate) fn register_fn_raw(&mut self, fn_name: &str, args: Vec<TypeId>, f: Box<FnAny>) {
|
||||||
&mut self,
|
|
||||||
fn_name: &str,
|
|
||||||
args: Option<Vec<TypeId>>,
|
|
||||||
f: Box<FnAny>,
|
|
||||||
) {
|
|
||||||
let spec = FnSpec {
|
let spec = FnSpec {
|
||||||
name: fn_name.to_string().into(),
|
name: fn_name.to_string().into(),
|
||||||
args,
|
args,
|
||||||
@ -180,8 +175,7 @@ impl<'e> Engine<'e> {
|
|||||||
name: &str,
|
name: &str,
|
||||||
callback: impl Fn(&mut T) -> U + 'static,
|
callback: impl Fn(&mut T) -> U + 'static,
|
||||||
) {
|
) {
|
||||||
let get_fn_name = make_getter(name);
|
self.register_fn(&make_getter(name), callback);
|
||||||
self.register_fn(&get_fn_name, callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a setter function for a member of a registered type with the `Engine`.
|
/// Register a setter function for a member of a registered type with the `Engine`.
|
||||||
@ -226,8 +220,7 @@ impl<'e> Engine<'e> {
|
|||||||
name: &str,
|
name: &str,
|
||||||
callback: impl Fn(&mut T, U) -> () + 'static,
|
callback: impl Fn(&mut T, U) -> () + 'static,
|
||||||
) {
|
) {
|
||||||
let set_fn_name = make_setter(name);
|
self.register_fn(&make_setter(name), callback);
|
||||||
self.register_fn(&set_fn_name, callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shorthand for registering both getter and setter functions
|
/// Shorthand for registering both getter and setter functions
|
||||||
@ -353,8 +346,9 @@ impl<'e> Engine<'e> {
|
|||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
|
|
||||||
f.read_to_string(&mut contents)
|
f.read_to_string(&mut contents)
|
||||||
.map_err(|err| EvalAltResult::ErrorReadingScriptFile(path.clone(), err))
|
.map_err(|err| EvalAltResult::ErrorReadingScriptFile(path.clone(), err))?;
|
||||||
.map(|_| contents)
|
|
||||||
|
Ok(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a script file into an `AST`, which can be used later for evaluation.
|
/// Compile a script file into an `AST`, which can be used later for evaluation.
|
||||||
@ -559,8 +553,7 @@ impl<'e> Engine<'e> {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn eval<T: Any + Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> {
|
pub fn eval<T: Any + Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> {
|
||||||
let mut scope = Scope::new();
|
self.eval_with_scope(&mut Scope::new(), input)
|
||||||
self.eval_with_scope(&mut scope, input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate a string with own scope.
|
/// Evaluate a string with own scope.
|
||||||
@ -609,8 +602,7 @@ impl<'e> Engine<'e> {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn eval_expression<T: Any + Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> {
|
pub fn eval_expression<T: Any + Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> {
|
||||||
let mut scope = Scope::new();
|
self.eval_expression_with_scope(&mut Scope::new(), input)
|
||||||
self.eval_expression_with_scope(&mut scope, input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate a string containing an expression with own scope.
|
/// Evaluate a string containing an expression with own scope.
|
||||||
@ -662,8 +654,7 @@ impl<'e> Engine<'e> {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn eval_ast<T: Any + Clone>(&mut self, ast: &AST) -> Result<T, EvalAltResult> {
|
pub fn eval_ast<T: Any + Clone>(&mut self, ast: &AST) -> Result<T, EvalAltResult> {
|
||||||
let mut scope = Scope::new();
|
self.eval_ast_with_scope(&mut Scope::new(), ast)
|
||||||
self.eval_ast_with_scope(&mut scope, ast)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate an `AST` with own scope.
|
/// Evaluate an `AST` with own scope.
|
||||||
@ -701,8 +692,8 @@ impl<'e> Engine<'e> {
|
|||||||
ast: &AST,
|
ast: &AST,
|
||||||
) -> Result<T, EvalAltResult> {
|
) -> Result<T, EvalAltResult> {
|
||||||
self.eval_ast_with_scope_raw(scope, false, ast)
|
self.eval_ast_with_scope_raw(scope, false, ast)
|
||||||
.and_then(|out| {
|
.and_then(|result| {
|
||||||
out.downcast::<T>().map(|v| *v).map_err(|a| {
|
result.downcast::<T>().map(|v| *v).map_err(|a| {
|
||||||
EvalAltResult::ErrorMismatchOutputType(
|
EvalAltResult::ErrorMismatchOutputType(
|
||||||
self.map_type_name((*a).type_name()).to_string(),
|
self.map_type_name((*a).type_name()).to_string(),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
@ -717,34 +708,25 @@ impl<'e> Engine<'e> {
|
|||||||
retain_functions: bool,
|
retain_functions: bool,
|
||||||
ast: &AST,
|
ast: &AST,
|
||||||
) -> Result<Dynamic, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
fn eval_ast_internal(
|
if !retain_functions {
|
||||||
engine: &mut Engine,
|
self.clear_functions();
|
||||||
scope: &mut Scope,
|
|
||||||
retain_functions: bool,
|
|
||||||
ast: &AST,
|
|
||||||
) -> Result<Dynamic, EvalAltResult> {
|
|
||||||
if !retain_functions {
|
|
||||||
engine.clear_functions();
|
|
||||||
}
|
|
||||||
|
|
||||||
let statements = {
|
|
||||||
let AST(statements, functions) = ast;
|
|
||||||
engine.load_script_functions(functions);
|
|
||||||
statements
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = statements.iter().try_fold(().into_dynamic(), |_, stmt| {
|
|
||||||
engine.eval_stmt(scope, stmt, 0)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
if !retain_functions {
|
|
||||||
engine.clear_functions();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_ast_internal(self, scope, retain_functions, ast).or_else(|err| match err {
|
let statements = {
|
||||||
|
let AST(statements, functions) = ast;
|
||||||
|
self.load_script_functions(functions);
|
||||||
|
statements
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = statements
|
||||||
|
.iter()
|
||||||
|
.try_fold(().into_dynamic(), |_, stmt| self.eval_stmt(scope, stmt, 0));
|
||||||
|
|
||||||
|
if !retain_functions {
|
||||||
|
self.clear_functions();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.or_else(|err| match err {
|
||||||
EvalAltResult::Return(out, _) => Ok(out),
|
EvalAltResult::Return(out, _) => Ok(out),
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
})
|
})
|
||||||
@ -834,14 +816,13 @@ impl<'e> Engine<'e> {
|
|||||||
|
|
||||||
let result = statements
|
let result = statements
|
||||||
.iter()
|
.iter()
|
||||||
.try_fold(().into_dynamic(), |_, stmt| self.eval_stmt(scope, stmt, 0))
|
.try_fold(().into_dynamic(), |_, stmt| self.eval_stmt(scope, stmt, 0));
|
||||||
.map(|_| ());
|
|
||||||
|
|
||||||
if !retain_functions {
|
if !retain_functions {
|
||||||
self.clear_functions();
|
self.clear_functions();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.or_else(|err| match err {
|
result.map(|_| ()).or_else(|err| match err {
|
||||||
EvalAltResult::Return(_, _) => Ok(()),
|
EvalAltResult::Return(_, _) => Ok(()),
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
})
|
})
|
||||||
|
220
src/engine.rs
220
src/engine.rs
@ -48,17 +48,65 @@ pub(crate) const FUNC_SETTER: &str = "set$";
|
|||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
enum IndexSourceType {
|
enum IndexSourceType {
|
||||||
|
Expression,
|
||||||
|
String,
|
||||||
Array,
|
Array,
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Map,
|
Map,
|
||||||
String,
|
}
|
||||||
Expression,
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||||
|
enum IndexValue {
|
||||||
|
Num(usize),
|
||||||
|
Str(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexValue {
|
||||||
|
fn from_num(idx: INT) -> Self {
|
||||||
|
Self::Num(idx as usize)
|
||||||
|
}
|
||||||
|
fn from_str(name: String) -> Self {
|
||||||
|
Self::Str(name)
|
||||||
|
}
|
||||||
|
fn as_num(self) -> usize {
|
||||||
|
match self {
|
||||||
|
Self::Num(n) => n,
|
||||||
|
_ => panic!("index value is numeric"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn as_str(self) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Str(s) => s,
|
||||||
|
_ => panic!("index value is string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Target<'a> {
|
||||||
|
Scope(ScopeSource<'a>),
|
||||||
|
Value(&'a mut Variant),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Target<'a> {
|
||||||
|
fn from(value: &'a mut Variant) -> Self {
|
||||||
|
Self::Value(value)
|
||||||
|
}
|
||||||
|
fn from_src(src: ScopeSource<'a>) -> Self {
|
||||||
|
Self::Scope(src)
|
||||||
|
}
|
||||||
|
fn get_mut(self, scope: &'a mut Scope) -> &'a mut Variant {
|
||||||
|
match self {
|
||||||
|
Self::Value(t) => t,
|
||||||
|
Self::Scope(src) => scope.get_mut(src).as_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||||
pub struct FnSpec<'a> {
|
pub struct FnSpec<'a> {
|
||||||
pub name: Cow<'a, str>,
|
pub name: Cow<'a, str>,
|
||||||
pub args: Option<Vec<TypeId>>,
|
pub args: Vec<TypeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type that holds a library of script-defined functions.
|
/// A type that holds a library of script-defined functions.
|
||||||
@ -143,9 +191,9 @@ pub struct Engine<'e> {
|
|||||||
/// A hashmap mapping type names to pretty-print names.
|
/// A hashmap mapping type names to pretty-print names.
|
||||||
pub(crate) type_names: HashMap<String, String>,
|
pub(crate) type_names: HashMap<String, String>,
|
||||||
|
|
||||||
/// Closure for implementing the print commands.
|
/// Closure for implementing the `print` command.
|
||||||
pub(crate) on_print: Box<dyn FnMut(&str) + 'e>,
|
pub(crate) on_print: Box<dyn FnMut(&str) + 'e>,
|
||||||
/// Closure for implementing the debug commands.
|
/// Closure for implementing the `debug` command.
|
||||||
pub(crate) on_debug: Box<dyn FnMut(&str) + 'e>,
|
pub(crate) on_debug: Box<dyn FnMut(&str) + 'e>,
|
||||||
|
|
||||||
/// Optimize the AST after compilation.
|
/// Optimize the AST after compilation.
|
||||||
@ -256,7 +304,7 @@ impl Engine<'_> {
|
|||||||
) -> Result<Option<Dynamic>, EvalAltResult> {
|
) -> Result<Option<Dynamic>, EvalAltResult> {
|
||||||
let spec = FnSpec {
|
let spec = FnSpec {
|
||||||
name: fn_name.into(),
|
name: fn_name.into(),
|
||||||
args: Some(args.iter().map(|a| Any::type_id(&**a)).collect()),
|
args: args.iter().map(|a| Any::type_id(&**a)).collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Search built-in's and external functions
|
// Search built-in's and external functions
|
||||||
@ -303,7 +351,7 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
let spec = FnSpec {
|
let spec = FnSpec {
|
||||||
name: fn_name.into(),
|
name: fn_name.into(),
|
||||||
args: Some(args.iter().map(|a| Any::type_id(&**a)).collect()),
|
args: args.iter().map(|a| Any::type_id(&**a)).collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Argument must be a string
|
// Argument must be a string
|
||||||
@ -386,40 +434,14 @@ impl Engine<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Chain-evaluate a dot setter.
|
/// Chain-evaluate a dot setter.
|
||||||
///
|
|
||||||
/// Either `src` or `target` should be `Some`.
|
|
||||||
///
|
|
||||||
/// If `target` is `Some`, then it is taken as the reference to use for `this`.
|
|
||||||
///
|
|
||||||
/// Otherwise, if `src` is `Some`, then it holds a name and index into `scope`; using `get_mut` on
|
|
||||||
/// `scope` can retrieve a mutable reference to the variable's value to use as `this`.
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
fn get_dot_val_helper(
|
fn get_dot_val_helper(
|
||||||
&mut self,
|
&mut self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
src: Option<ScopeSource>,
|
target: Target,
|
||||||
target: Option<&mut Variant>,
|
|
||||||
dot_rhs: &Expr,
|
dot_rhs: &Expr,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<Dynamic, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
// Get the `this` reference. Either `src` or `target` should be `Some`.
|
|
||||||
fn get_this_ptr<'a>(
|
|
||||||
scope: &'a mut Scope,
|
|
||||||
src: Option<ScopeSource>,
|
|
||||||
target: Option<&'a mut Variant>,
|
|
||||||
) -> &'a mut Variant {
|
|
||||||
if let Some(t) = target {
|
|
||||||
// If `target` is `Some`, then it is returned.
|
|
||||||
t
|
|
||||||
} else {
|
|
||||||
// Otherwise, if `src` is `Some`, then it holds a name and index into `scope`;
|
|
||||||
// using `get_mut` on `scope` to retrieve a mutable reference for return.
|
|
||||||
scope
|
|
||||||
.get_mut(src.expect("expected source in scope"))
|
|
||||||
.as_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match dot_rhs {
|
match dot_rhs {
|
||||||
// xxx.fn_name(args)
|
// xxx.fn_name(args)
|
||||||
Expr::FunctionCall(fn_name, arg_expr_list, def_val, pos) => {
|
Expr::FunctionCall(fn_name, arg_expr_list, def_val, pos) => {
|
||||||
@ -428,7 +450,7 @@ impl Engine<'_> {
|
|||||||
.map(|arg_expr| self.eval_expr(scope, arg_expr, level))
|
.map(|arg_expr| self.eval_expr(scope, arg_expr, level))
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
let this_ptr = target.get_mut(scope);
|
||||||
|
|
||||||
let mut arg_values: Vec<_> = once(this_ptr)
|
let mut arg_values: Vec<_> = once(this_ptr)
|
||||||
.chain(values.iter_mut().map(Dynamic::as_mut))
|
.chain(values.iter_mut().map(Dynamic::as_mut))
|
||||||
@ -439,9 +461,8 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = make_getter(id);
|
let this_ptr = target.get_mut(scope);
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// xxx.idx_lhs[idx_expr]
|
// xxx.idx_lhs[idx_expr]
|
||||||
@ -450,13 +471,12 @@ impl Engine<'_> {
|
|||||||
let val = match idx_lhs.as_ref() {
|
let val = match idx_lhs.as_ref() {
|
||||||
// xxx.id[idx_expr]
|
// xxx.id[idx_expr]
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = make_getter(id);
|
let this_ptr = target.get_mut(scope);
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)?
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)?
|
|
||||||
}
|
}
|
||||||
// xxx.???[???][idx_expr]
|
// xxx.???[???][idx_expr]
|
||||||
Expr::Index(_, _, _) => {
|
Expr::Index(_, _, _) => {
|
||||||
self.get_dot_val_helper(scope, src, target, idx_lhs, level)?
|
self.get_dot_val_helper(scope, target, idx_lhs, level)?
|
||||||
}
|
}
|
||||||
// Syntax error
|
// Syntax error
|
||||||
_ => {
|
_ => {
|
||||||
@ -475,12 +495,10 @@ impl Engine<'_> {
|
|||||||
Expr::Dot(dot_lhs, rhs, _) => match dot_lhs.as_ref() {
|
Expr::Dot(dot_lhs, rhs, _) => match dot_lhs.as_ref() {
|
||||||
// xxx.id.rhs
|
// xxx.id.rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = make_getter(id);
|
let this_ptr = target.get_mut(scope);
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
||||||
|
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
self.get_dot_val_helper(scope, None, Some(v.as_mut()), rhs, level)
|
self.get_dot_val_helper(scope, Target::from(v.as_mut()), rhs, level)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// xxx.idx_lhs[idx_expr].rhs
|
// xxx.idx_lhs[idx_expr].rhs
|
||||||
@ -489,13 +507,12 @@ impl Engine<'_> {
|
|||||||
let val = match idx_lhs.as_ref() {
|
let val = match idx_lhs.as_ref() {
|
||||||
// xxx.id[idx_expr].rhs
|
// xxx.id[idx_expr].rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = make_getter(id);
|
let this_ptr = target.get_mut(scope);
|
||||||
let this_ptr = get_this_ptr(scope, src, target);
|
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)?
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)?
|
|
||||||
}
|
}
|
||||||
// xxx.???[???][idx_expr].rhs
|
// xxx.???[???][idx_expr].rhs
|
||||||
Expr::Index(_, _, _) => {
|
Expr::Index(_, _, _) => {
|
||||||
self.get_dot_val_helper(scope, src, target, idx_lhs, level)?
|
self.get_dot_val_helper(scope, target, idx_lhs, level)?
|
||||||
}
|
}
|
||||||
// Syntax error
|
// Syntax error
|
||||||
_ => {
|
_ => {
|
||||||
@ -508,7 +525,7 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
self.get_indexed_value(scope, &val, idx_expr, *op_pos, level)
|
self.get_indexed_value(scope, &val, idx_expr, *op_pos, level)
|
||||||
.and_then(|(mut v, _, _)| {
|
.and_then(|(mut v, _, _)| {
|
||||||
self.get_dot_val_helper(scope, None, Some(v.as_mut()), rhs, level)
|
self.get_dot_val_helper(scope, Target::from(v.as_mut()), rhs, level)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// Syntax error
|
// Syntax error
|
||||||
@ -545,16 +562,16 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
// This is a variable property access (potential function call).
|
// This is a variable property access (potential function call).
|
||||||
// Use a direct index into `scope` to directly mutate the variable value.
|
// Use a direct index into `scope` to directly mutate the variable value.
|
||||||
self.get_dot_val_helper(scope, Some(entry), None, dot_rhs, level)
|
self.get_dot_val_helper(scope, Target::from_src(entry), dot_rhs, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
// idx_lhs[idx_expr].???
|
// idx_lhs[idx_expr].???
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Index(idx_lhs, idx_expr, op_pos) => {
|
Expr::Index(idx_lhs, idx_expr, op_pos) => {
|
||||||
let (idx_src_type, src, idx, mut target) =
|
let (idx_src_type, src, idx, mut value) =
|
||||||
self.eval_index_expr(scope, idx_lhs, idx_expr, *op_pos, level)?;
|
self.eval_index_expr(scope, idx_lhs, idx_expr, *op_pos, level)?;
|
||||||
let this_ptr = target.as_mut();
|
let val =
|
||||||
let val = self.get_dot_val_helper(scope, None, Some(this_ptr), dot_rhs, level);
|
self.get_dot_val_helper(scope, Target::from(value.as_mut()), dot_rhs, level);
|
||||||
|
|
||||||
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
|
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
|
||||||
if let Some(src) = src {
|
if let Some(src) = src {
|
||||||
@ -571,7 +588,7 @@ impl Engine<'_> {
|
|||||||
scope,
|
scope,
|
||||||
src,
|
src,
|
||||||
idx,
|
idx,
|
||||||
(target, dot_rhs.position()),
|
(value, dot_rhs.position()),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -582,9 +599,8 @@ impl Engine<'_> {
|
|||||||
|
|
||||||
// {expr}.???
|
// {expr}.???
|
||||||
expr => {
|
expr => {
|
||||||
let mut target = self.eval_expr(scope, expr, level)?;
|
let mut value = self.eval_expr(scope, expr, level)?;
|
||||||
let this_ptr = target.as_mut();
|
self.get_dot_val_helper(scope, Target::from(value.as_mut()), dot_rhs, level)
|
||||||
self.get_dot_val_helper(scope, None, Some(this_ptr), dot_rhs, level)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -609,7 +625,7 @@ impl Engine<'_> {
|
|||||||
idx_expr: &Expr,
|
idx_expr: &Expr,
|
||||||
op_pos: Position,
|
op_pos: Position,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<(Dynamic, IndexSourceType, (Option<usize>, Option<String>)), EvalAltResult> {
|
) -> Result<(Dynamic, IndexSourceType, IndexValue), EvalAltResult> {
|
||||||
let idx_pos = idx_expr.position();
|
let idx_pos = idx_expr.position();
|
||||||
|
|
||||||
if val.is::<Array>() {
|
if val.is::<Array>() {
|
||||||
@ -624,7 +640,7 @@ impl Engine<'_> {
|
|||||||
return if idx >= 0 {
|
return if idx >= 0 {
|
||||||
arr.get(idx as usize)
|
arr.get(idx as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|v| (v, IndexSourceType::Array, (Some(idx as usize), None)))
|
.map(|v| (v, IndexSourceType::Array, IndexValue::from_num(idx)))
|
||||||
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), idx, idx_pos))
|
.ok_or_else(|| EvalAltResult::ErrorArrayBounds(arr.len(), idx, idx_pos))
|
||||||
} else {
|
} else {
|
||||||
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx, idx_pos))
|
Err(EvalAltResult::ErrorArrayBounds(arr.len(), idx, idx_pos))
|
||||||
@ -645,7 +661,7 @@ impl Engine<'_> {
|
|||||||
return Ok((
|
return Ok((
|
||||||
map.get(&idx).cloned().unwrap_or_else(|| ().into_dynamic()),
|
map.get(&idx).cloned().unwrap_or_else(|| ().into_dynamic()),
|
||||||
IndexSourceType::Map,
|
IndexSourceType::Map,
|
||||||
(None, Some(idx)),
|
IndexValue::from_str(idx),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -666,7 +682,7 @@ impl Engine<'_> {
|
|||||||
(
|
(
|
||||||
ch.into_dynamic(),
|
ch.into_dynamic(),
|
||||||
IndexSourceType::String,
|
IndexSourceType::String,
|
||||||
(Some(idx as usize), None),
|
IndexValue::from_num(idx),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
@ -701,7 +717,7 @@ impl Engine<'_> {
|
|||||||
(
|
(
|
||||||
IndexSourceType,
|
IndexSourceType,
|
||||||
Option<ScopeSource<'a>>,
|
Option<ScopeSource<'a>>,
|
||||||
(Option<usize>, Option<String>),
|
IndexValue,
|
||||||
Dynamic,
|
Dynamic,
|
||||||
),
|
),
|
||||||
EvalAltResult,
|
EvalAltResult,
|
||||||
@ -763,14 +779,14 @@ impl Engine<'_> {
|
|||||||
idx_src_type: IndexSourceType,
|
idx_src_type: IndexSourceType,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
src: ScopeSource,
|
src: ScopeSource,
|
||||||
idx: (Option<usize>, Option<String>),
|
idx: IndexValue,
|
||||||
new_val: (Dynamic, Position),
|
new_val: (Dynamic, Position),
|
||||||
) -> Result<Dynamic, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
match idx_src_type {
|
match idx_src_type {
|
||||||
// array_id[idx] = val
|
// array_id[idx] = val
|
||||||
IndexSourceType::Array => {
|
IndexSourceType::Array => {
|
||||||
let arr = scope.get_mut_by_type::<Array>(src);
|
let arr = scope.get_mut_by_type::<Array>(src);
|
||||||
arr[idx.0.expect("should be Some")] = new_val.0;
|
arr[idx.as_num()] = new_val.0;
|
||||||
Ok(().into_dynamic())
|
Ok(().into_dynamic())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,7 +794,7 @@ impl Engine<'_> {
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
IndexSourceType::Map => {
|
IndexSourceType::Map => {
|
||||||
let arr = scope.get_mut_by_type::<Map>(src);
|
let arr = scope.get_mut_by_type::<Map>(src);
|
||||||
arr.insert(idx.1.expect("should be Some"), new_val.0);
|
arr.insert(idx.as_str(), new_val.0);
|
||||||
Ok(().into_dynamic())
|
Ok(().into_dynamic())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,7 +807,7 @@ impl Engine<'_> {
|
|||||||
.0
|
.0
|
||||||
.downcast::<char>()
|
.downcast::<char>()
|
||||||
.map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?;
|
.map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?;
|
||||||
Self::str_replace_char(s, idx.0.expect("should be Some"), ch);
|
Self::str_replace_char(s, idx.as_num(), ch);
|
||||||
Ok(().into_dynamic())
|
Ok(().into_dynamic())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,13 +819,13 @@ impl Engine<'_> {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
fn update_indexed_value(
|
fn update_indexed_value(
|
||||||
mut target: Dynamic,
|
mut target: Dynamic,
|
||||||
idx: (Option<usize>, Option<String>),
|
idx: IndexValue,
|
||||||
new_val: Dynamic,
|
new_val: Dynamic,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> Result<Dynamic, EvalAltResult> {
|
) -> Result<Dynamic, EvalAltResult> {
|
||||||
if target.is::<Array>() {
|
if target.is::<Array>() {
|
||||||
let arr = target.downcast_mut::<Array>().expect("array expected");
|
let arr = target.downcast_mut::<Array>().expect("array expected");
|
||||||
arr[idx.0.expect("should be Some")] = new_val;
|
arr[idx.as_num()] = new_val;
|
||||||
return Ok(target);
|
return Ok(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,7 +833,7 @@ impl Engine<'_> {
|
|||||||
{
|
{
|
||||||
if target.is::<Map>() {
|
if target.is::<Map>() {
|
||||||
let map = target.downcast_mut::<Map>().expect("array expected");
|
let map = target.downcast_mut::<Map>().expect("array expected");
|
||||||
map.insert(idx.1.expect("should be Some"), new_val);
|
map.insert(idx.as_str(), new_val);
|
||||||
return Ok(target);
|
return Ok(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -828,7 +844,7 @@ impl Engine<'_> {
|
|||||||
let ch = *new_val
|
let ch = *new_val
|
||||||
.downcast::<char>()
|
.downcast::<char>()
|
||||||
.map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?;
|
.map_err(|_| EvalAltResult::ErrorCharMismatch(pos))?;
|
||||||
Self::str_replace_char(s, idx.0.expect("should be Some"), ch);
|
Self::str_replace_char(s, idx.as_num(), ch);
|
||||||
return Ok(target);
|
return Ok(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,9 +865,8 @@ impl Engine<'_> {
|
|||||||
match dot_rhs {
|
match dot_rhs {
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let set_fn_name = make_setter(id);
|
|
||||||
let mut args = [this_ptr, new_val.0.as_mut()];
|
let mut args = [this_ptr, new_val.0.as_mut()];
|
||||||
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
self.call_fn_raw(&make_setter(id), &mut args, None, *pos, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xxx.lhs[idx_expr]
|
// xxx.lhs[idx_expr]
|
||||||
@ -859,22 +874,18 @@ impl Engine<'_> {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
||||||
// xxx.id[idx_expr]
|
// xxx.id[idx_expr]
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => self
|
||||||
let get_fn_name = make_getter(id);
|
.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
||||||
|
.and_then(|v| {
|
||||||
|
let (_, _, idx) =
|
||||||
|
self.get_indexed_value(scope, &v, idx_expr, *op_pos, level)?;
|
||||||
|
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
Self::update_indexed_value(v, idx, new_val.0.clone(), new_val.1)
|
||||||
.and_then(|v| {
|
})
|
||||||
let (_, _, idx) =
|
.and_then(|mut v| {
|
||||||
self.get_indexed_value(scope, &v, idx_expr, *op_pos, level)?;
|
let mut args = [this_ptr, v.as_mut()];
|
||||||
|
self.call_fn_raw(&make_setter(id), &mut args, None, *pos, 0)
|
||||||
Self::update_indexed_value(v, idx, new_val.0.clone(), new_val.1)
|
}),
|
||||||
})
|
|
||||||
.and_then(|mut v| {
|
|
||||||
let set_fn_name = make_setter(id);
|
|
||||||
let mut args = [this_ptr, v.as_mut()];
|
|
||||||
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// All others - syntax error for setters chain
|
// All others - syntax error for setters chain
|
||||||
_ => Err(EvalAltResult::ErrorDotExpr(
|
_ => Err(EvalAltResult::ErrorDotExpr(
|
||||||
@ -887,17 +898,14 @@ impl Engine<'_> {
|
|||||||
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
Expr::Dot(lhs, rhs, _) => match lhs.as_ref() {
|
||||||
// xxx.id.rhs
|
// xxx.id.rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = make_getter(id);
|
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
||||||
|
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
self.set_dot_val_helper(scope, v.as_mut(), rhs, new_val, level)
|
self.set_dot_val_helper(scope, v.as_mut(), rhs, new_val, level)
|
||||||
.map(|_| v) // Discard Ok return value
|
.map(|_| v) // Discard Ok return value
|
||||||
})
|
})
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
let set_fn_name = make_setter(id);
|
|
||||||
let mut args = [this_ptr, v.as_mut()];
|
let mut args = [this_ptr, v.as_mut()];
|
||||||
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
self.call_fn_raw(&make_setter(id), &mut args, None, *pos, 0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,24 +915,26 @@ impl Engine<'_> {
|
|||||||
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
Expr::Index(lhs, idx_expr, op_pos) => match lhs.as_ref() {
|
||||||
// xxx.id[idx_expr].rhs
|
// xxx.id[idx_expr].rhs
|
||||||
Expr::Property(id, pos) => {
|
Expr::Property(id, pos) => {
|
||||||
let get_fn_name = make_getter(id);
|
self.call_fn_raw(&make_getter(id), &mut [this_ptr], None, *pos, 0)
|
||||||
|
|
||||||
self.call_fn_raw(&get_fn_name, &mut [this_ptr], None, *pos, 0)
|
|
||||||
.and_then(|v| {
|
.and_then(|v| {
|
||||||
let (mut target, _, idx) =
|
let (mut value, _, idx) =
|
||||||
self.get_indexed_value(scope, &v, idx_expr, *op_pos, level)?;
|
self.get_indexed_value(scope, &v, idx_expr, *op_pos, level)?;
|
||||||
|
|
||||||
let val_pos = new_val.1;
|
let val_pos = new_val.1;
|
||||||
let this_ptr = target.as_mut();
|
let this_ptr = value.as_mut();
|
||||||
self.set_dot_val_helper(scope, this_ptr, rhs, new_val, level)?;
|
self.set_dot_val_helper(scope, this_ptr, rhs, new_val, level)?;
|
||||||
|
|
||||||
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
|
// In case the expression mutated `target`, we need to update it back into the scope because it is cloned.
|
||||||
Self::update_indexed_value(v, idx, target, val_pos)
|
Self::update_indexed_value(v, idx, value, val_pos)
|
||||||
})
|
})
|
||||||
.and_then(|mut v| {
|
.and_then(|mut v| {
|
||||||
let set_fn_name = make_setter(id);
|
self.call_fn_raw(
|
||||||
let mut args = [this_ptr, v.as_mut()];
|
&make_setter(id),
|
||||||
self.call_fn_raw(&set_fn_name, &mut args, None, *pos, 0)
|
&mut [this_ptr, v.as_mut()],
|
||||||
|
None,
|
||||||
|
*pos,
|
||||||
|
0,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,7 +1178,7 @@ impl Engine<'_> {
|
|||||||
fn has_override(engine: &Engine, name: &str) -> bool {
|
fn has_override(engine: &Engine, name: &str) -> bool {
|
||||||
let spec = FnSpec {
|
let spec = FnSpec {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
args: Some(vec![TypeId::of::<String>()]),
|
args: vec![TypeId::of::<String>()],
|
||||||
};
|
};
|
||||||
|
|
||||||
engine.functions.contains_key(&spec) || engine.fn_lib.has_function(name, 1)
|
engine.functions.contains_key(&spec) || engine.fn_lib.has_function(name, 1)
|
||||||
|
@ -165,7 +165,7 @@ macro_rules! def_register {
|
|||||||
let r = f($(($clone)($par)),*);
|
let r = f($(($clone)($par)),*);
|
||||||
Ok(Box::new(r) as Dynamic)
|
Ok(Box::new(r) as Dynamic)
|
||||||
};
|
};
|
||||||
self.register_fn_raw(name, Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
self.register_fn_raw(name, vec![$(TypeId::of::<$par>()),*], Box::new(fun));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ macro_rules! def_register {
|
|||||||
// potentially clone the value, otherwise pass the reference.
|
// potentially clone the value, otherwise pass the reference.
|
||||||
Ok(f($(($clone)($par)),*))
|
Ok(f($(($clone)($par)),*))
|
||||||
};
|
};
|
||||||
self.register_fn_raw(name, Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
self.register_fn_raw(name, vec![$(TypeId::of::<$par>()),*], Box::new(fun));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ macro_rules! def_register {
|
|||||||
f($(($clone)($par)),*).map(|r| Box::new(r) as Dynamic)
|
f($(($clone)($par)),*).map(|r| Box::new(r) as Dynamic)
|
||||||
.map_err(|err| err.set_position(pos))
|
.map_err(|err| err.set_position(pos))
|
||||||
};
|
};
|
||||||
self.register_fn_raw(name, Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
self.register_fn_raw(name, vec![$(TypeId::of::<$par>()),*], Box::new(fun));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,11 @@ use crate::stdlib::path::PathBuf;
|
|||||||
pub enum EvalAltResult {
|
pub enum EvalAltResult {
|
||||||
/// Syntax error.
|
/// Syntax error.
|
||||||
ErrorParsing(ParseError),
|
ErrorParsing(ParseError),
|
||||||
|
|
||||||
|
/// Error reading from a script file. Wrapped value is the path of the script file.
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
ErrorReadingScriptFile(PathBuf, std::io::Error),
|
||||||
|
|
||||||
/// Call to an unknown function. Wrapped value is the name of the function.
|
/// Call to an unknown function. Wrapped value is the name of the function.
|
||||||
ErrorFunctionNotFound(String, Position),
|
ErrorFunctionNotFound(String, Position),
|
||||||
/// Function call has incorrect number of arguments.
|
/// Function call has incorrect number of arguments.
|
||||||
@ -55,9 +60,6 @@ pub enum EvalAltResult {
|
|||||||
/// Returned type is not the same as the required output type.
|
/// Returned type is not the same as the required output type.
|
||||||
/// Wrapped value is the type of the actual result.
|
/// Wrapped value is the type of the actual result.
|
||||||
ErrorMismatchOutputType(String, Position),
|
ErrorMismatchOutputType(String, Position),
|
||||||
/// Error reading from a script file. Wrapped value is the path of the script file.
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
ErrorReadingScriptFile(PathBuf, std::io::Error),
|
|
||||||
/// Inappropriate member access.
|
/// Inappropriate member access.
|
||||||
ErrorDotExpr(String, Position),
|
ErrorDotExpr(String, Position),
|
||||||
/// Arithmetic error encountered. Wrapped value is the error message.
|
/// Arithmetic error encountered. Wrapped value is the error message.
|
||||||
@ -66,6 +68,7 @@ pub enum EvalAltResult {
|
|||||||
ErrorStackOverflow(Position),
|
ErrorStackOverflow(Position),
|
||||||
/// Run-time error encountered. Wrapped value is the error message.
|
/// Run-time error encountered. Wrapped value is the error message.
|
||||||
ErrorRuntime(String, Position),
|
ErrorRuntime(String, Position),
|
||||||
|
|
||||||
/// Breaking out of loops - not an error if within a loop.
|
/// Breaking out of loops - not an error if within a loop.
|
||||||
ErrorLoopBreak(Position),
|
ErrorLoopBreak(Position),
|
||||||
/// Not an error: Value returned from a script via the `return` keyword.
|
/// Not an error: Value returned from a script via the `return` keyword.
|
||||||
@ -76,6 +79,9 @@ pub enum EvalAltResult {
|
|||||||
impl EvalAltResult {
|
impl EvalAltResult {
|
||||||
pub(crate) fn desc(&self) -> &str {
|
pub(crate) fn desc(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
Self::ErrorReadingScriptFile(_, _) => "Cannot read from script file",
|
||||||
|
|
||||||
Self::ErrorParsing(p) => p.desc(),
|
Self::ErrorParsing(p) => p.desc(),
|
||||||
Self::ErrorFunctionNotFound(_, _) => "Function not found",
|
Self::ErrorFunctionNotFound(_, _) => "Function not found",
|
||||||
Self::ErrorFunctionArgsMismatch(_, _, _, _) => {
|
Self::ErrorFunctionArgsMismatch(_, _, _, _) => {
|
||||||
@ -108,8 +114,6 @@ impl EvalAltResult {
|
|||||||
}
|
}
|
||||||
Self::ErrorAssignmentToConstant(_, _) => "Assignment to a constant variable",
|
Self::ErrorAssignmentToConstant(_, _) => "Assignment to a constant variable",
|
||||||
Self::ErrorMismatchOutputType(_, _) => "Output type is incorrect",
|
Self::ErrorMismatchOutputType(_, _) => "Output type is incorrect",
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
Self::ErrorReadingScriptFile(_, _) => "Cannot read from script file",
|
|
||||||
Self::ErrorDotExpr(_, _) => "Malformed dot expression",
|
Self::ErrorDotExpr(_, _) => "Malformed dot expression",
|
||||||
Self::ErrorArithmetic(_, _) => "Arithmetic error",
|
Self::ErrorArithmetic(_, _) => "Arithmetic error",
|
||||||
Self::ErrorStackOverflow(_) => "Stack overflow",
|
Self::ErrorStackOverflow(_) => "Stack overflow",
|
||||||
@ -127,6 +131,13 @@ impl fmt::Display for EvalAltResult {
|
|||||||
let desc = self.desc();
|
let desc = self.desc();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
Self::ErrorReadingScriptFile(path, err) => {
|
||||||
|
write!(f, "{} '{}': {}", desc, path.display(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p),
|
||||||
|
|
||||||
Self::ErrorFunctionNotFound(s, pos) | Self::ErrorVariableNotFound(s, pos) => {
|
Self::ErrorFunctionNotFound(s, pos) | Self::ErrorVariableNotFound(s, pos) => {
|
||||||
write!(f, "{}: '{}' ({})", desc, s, pos)
|
write!(f, "{}: '{}' ({})", desc, s, pos)
|
||||||
}
|
}
|
||||||
@ -141,33 +152,31 @@ impl fmt::Display for EvalAltResult {
|
|||||||
| Self::ErrorDotExpr(_, pos)
|
| Self::ErrorDotExpr(_, pos)
|
||||||
| Self::ErrorStackOverflow(pos) => write!(f, "{} ({})", desc, pos),
|
| Self::ErrorStackOverflow(pos) => write!(f, "{} ({})", desc, pos),
|
||||||
|
|
||||||
Self::ErrorAssignmentToConstant(s, pos) => write!(f, "{}: '{}' ({})", desc, s, pos),
|
|
||||||
Self::ErrorMismatchOutputType(s, pos) => write!(f, "{}: {} ({})", desc, s, pos),
|
|
||||||
Self::ErrorRuntime(s, pos) => {
|
Self::ErrorRuntime(s, pos) => {
|
||||||
write!(f, "{} ({})", if s.is_empty() { desc } else { s }, pos)
|
write!(f, "{} ({})", if s.is_empty() { desc } else { s }, pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Self::ErrorAssignmentToConstant(s, pos) => write!(f, "{}: '{}' ({})", desc, s, pos),
|
||||||
|
Self::ErrorMismatchOutputType(s, pos) => write!(f, "{}: {} ({})", desc, s, pos),
|
||||||
Self::ErrorArithmetic(s, pos) => write!(f, "{} ({})", s, pos),
|
Self::ErrorArithmetic(s, pos) => write!(f, "{} ({})", s, pos),
|
||||||
|
|
||||||
Self::ErrorLoopBreak(pos) => write!(f, "{} ({})", desc, pos),
|
Self::ErrorLoopBreak(pos) => write!(f, "{} ({})", desc, pos),
|
||||||
Self::Return(_, pos) => write!(f, "{} ({})", desc, pos),
|
Self::Return(_, pos) => write!(f, "{} ({})", desc, pos),
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
Self::ErrorReadingScriptFile(path, err) => {
|
Self::ErrorFunctionArgsMismatch(fn_name, 0, n, pos) => write!(
|
||||||
write!(f, "{} '{}': {}", desc, path.display(), err)
|
|
||||||
}
|
|
||||||
Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p),
|
|
||||||
Self::ErrorFunctionArgsMismatch(fun, 0, n, pos) => write!(
|
|
||||||
f,
|
f,
|
||||||
"Function '{}' expects no argument but {} found ({})",
|
"Function '{}' expects no argument but {} found ({})",
|
||||||
fun, n, pos
|
fn_name, n, pos
|
||||||
),
|
),
|
||||||
Self::ErrorFunctionArgsMismatch(fun, 1, n, pos) => write!(
|
Self::ErrorFunctionArgsMismatch(fn_name, 1, n, pos) => write!(
|
||||||
f,
|
f,
|
||||||
"Function '{}' expects one argument but {} found ({})",
|
"Function '{}' expects one argument but {} found ({})",
|
||||||
fun, n, pos
|
fn_name, n, pos
|
||||||
),
|
),
|
||||||
Self::ErrorFunctionArgsMismatch(fun, need, n, pos) => write!(
|
Self::ErrorFunctionArgsMismatch(fn_name, need, n, pos) => write!(
|
||||||
f,
|
f,
|
||||||
"Function '{}' expects {} argument(s) but {} found ({})",
|
"Function '{}' expects {} argument(s) but {} found ({})",
|
||||||
fun, need, n, pos
|
fn_name, need, n, pos
|
||||||
),
|
),
|
||||||
Self::ErrorBooleanArgMismatch(op, pos) => {
|
Self::ErrorBooleanArgMismatch(op, pos) => {
|
||||||
write!(f, "{} operator expects boolean operands ({})", op, pos)
|
write!(f, "{} operator expects boolean operands ({})", op, pos)
|
||||||
|
Loading…
Reference in New Issue
Block a user