Better handling of errors during function calls.
This commit is contained in:
parent
9d8d074940
commit
cabceb7498
@ -1017,7 +1017,8 @@ impl Engine {
|
|||||||
|
|
||||||
let state = State::new(fn_lib);
|
let state = State::new(fn_lib);
|
||||||
|
|
||||||
let result = self.call_script_fn(Some(scope), &state, fn_def, args.as_mut(), pos, 0)?;
|
let result =
|
||||||
|
self.call_script_fn(Some(scope), &state, name, fn_def, args.as_mut(), pos, 0)?;
|
||||||
|
|
||||||
let return_type = self.map_type_name(result.type_name());
|
let return_type = self.map_type_name(result.type_name());
|
||||||
|
|
||||||
|
@ -543,7 +543,7 @@ impl Engine {
|
|||||||
if hashes.1 > 0 {
|
if hashes.1 > 0 {
|
||||||
if let Some(fn_def) = state.get_function(hashes.1) {
|
if let Some(fn_def) = state.get_function(hashes.1) {
|
||||||
return self
|
return self
|
||||||
.call_script_fn(scope, state, fn_def, args, pos, level)
|
.call_script_fn(scope, state, fn_name, fn_def, args, pos, level)
|
||||||
.map(|v| (v, false));
|
.map(|v| (v, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -569,7 +569,7 @@ impl Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Run external function
|
// Run external function
|
||||||
let result = match func.call(args, pos) {
|
let result = match func.call(args) {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
// Restore the backup value for the first argument since it has been consumed!
|
// Restore the backup value for the first argument since it has been consumed!
|
||||||
if restore {
|
if restore {
|
||||||
@ -577,7 +577,9 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err),
|
Err(err) => {
|
||||||
|
return Err(err.new_position(pos));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// See if the function match print/debug (which requires special processing)
|
// See if the function match print/debug (which requires special processing)
|
||||||
@ -658,6 +660,7 @@ impl Engine {
|
|||||||
&self,
|
&self,
|
||||||
scope: Option<&mut Scope>,
|
scope: Option<&mut Scope>,
|
||||||
state: &State,
|
state: &State,
|
||||||
|
fn_name: &str,
|
||||||
fn_def: &FnDef,
|
fn_def: &FnDef,
|
||||||
args: &mut FnCallArgs,
|
args: &mut FnCallArgs,
|
||||||
pos: Position,
|
pos: Position,
|
||||||
@ -687,7 +690,18 @@ impl Engine {
|
|||||||
.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(EvalAltResult::set_position(err, pos)),
|
EvalAltResult::ErrorInFunctionCall(name, err, _) => {
|
||||||
|
Err(Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
|
format!("{} > {}", fn_name, name),
|
||||||
|
err,
|
||||||
|
pos,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
_ => Err(Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
|
fn_name.to_string(),
|
||||||
|
err,
|
||||||
|
pos,
|
||||||
|
))),
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.rewind(scope_len);
|
scope.rewind(scope_len);
|
||||||
@ -717,7 +731,18 @@ impl Engine {
|
|||||||
.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(EvalAltResult::set_position(err, pos)),
|
EvalAltResult::ErrorInFunctionCall(name, err, _) => {
|
||||||
|
Err(Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
|
format!("{} > {}", fn_name, name),
|
||||||
|
err,
|
||||||
|
pos,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
_ => Err(Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
|
fn_name.to_string(),
|
||||||
|
err,
|
||||||
|
pos,
|
||||||
|
))),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -809,7 +834,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| EvalAltResult::set_position(err, pos))
|
.map_err(|err| err.new_position(pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Chain-evaluate a dot/index chain.
|
/// Chain-evaluate a dot/index chain.
|
||||||
@ -1415,7 +1440,7 @@ impl Engine {
|
|||||||
|
|
||||||
// First search in script-defined functions (can override built-in)
|
// First search in script-defined functions (can override built-in)
|
||||||
if let Some(fn_def) = module.get_qualified_scripted_fn(*hash_fn_def) {
|
if let Some(fn_def) = module.get_qualified_scripted_fn(*hash_fn_def) {
|
||||||
self.call_script_fn(None, state, fn_def, args.as_mut(), *pos, level)
|
self.call_script_fn(None, state, name, fn_def, args.as_mut(), *pos, level)
|
||||||
} else {
|
} else {
|
||||||
// Then search in Rust functions
|
// Then search in Rust functions
|
||||||
|
|
||||||
@ -1428,8 +1453,10 @@ impl Engine {
|
|||||||
// 3) The final hash is the XOR of the two hashes.
|
// 3) The final hash is the XOR of the two hashes.
|
||||||
let hash_fn_native = *hash_fn_def ^ hash_fn_args;
|
let hash_fn_native = *hash_fn_def ^ hash_fn_args;
|
||||||
|
|
||||||
match module.get_qualified_fn(name, hash_fn_native, *pos) {
|
match module.get_qualified_fn(name, hash_fn_native) {
|
||||||
Ok(func) => func.call(args.as_mut(), *pos),
|
Ok(func) => func
|
||||||
|
.call(args.as_mut())
|
||||||
|
.map_err(|err| err.new_position(*pos)),
|
||||||
Err(_) if def_val.is_some() => Ok(def_val.clone().unwrap()),
|
Err(_) if def_val.is_some() => Ok(def_val.clone().unwrap()),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
use crate::any::Dynamic;
|
use crate::any::Dynamic;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
|
||||||
|
|
||||||
use crate::stdlib::{boxed::Box, rc::Rc, sync::Arc};
|
use crate::stdlib::{boxed::Box, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub type FnAny =
|
pub type FnAny = dyn Fn(&mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync;
|
||||||
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, Box<EvalAltResult>>;
|
pub type FnAny = dyn Fn(&mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync;
|
pub type IteratorFn = dyn Fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>> + Send + Sync;
|
||||||
@ -85,7 +83,7 @@ pub trait NativeCallable {
|
|||||||
/// Get the ABI type of a native Rust function.
|
/// Get the ABI type of a native Rust function.
|
||||||
fn abi(&self) -> NativeFunctionABI;
|
fn abi(&self) -> NativeFunctionABI;
|
||||||
/// Call a native Rust function.
|
/// Call a native Rust function.
|
||||||
fn call(&self, args: &mut FnCallArgs, pos: Position) -> Result<Dynamic, Box<EvalAltResult>>;
|
fn call(&self, args: &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait implemented by all native Rust functions that are callable by Rhai.
|
/// A trait implemented by all native Rust functions that are callable by Rhai.
|
||||||
@ -94,7 +92,7 @@ pub trait NativeCallable: Send + Sync {
|
|||||||
/// Get the ABI type of a native Rust function.
|
/// Get the ABI type of a native Rust function.
|
||||||
fn abi(&self) -> NativeFunctionABI;
|
fn abi(&self) -> NativeFunctionABI;
|
||||||
/// Call a native Rust function.
|
/// Call a native Rust function.
|
||||||
fn call(&self, args: &mut FnCallArgs, pos: Position) -> Result<Dynamic, Box<EvalAltResult>>;
|
fn call(&self, args: &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A type encapsulating a native Rust function callable by Rhai.
|
/// A type encapsulating a native Rust function callable by Rhai.
|
||||||
@ -104,8 +102,8 @@ impl NativeCallable for NativeFunction {
|
|||||||
fn abi(&self) -> NativeFunctionABI {
|
fn abi(&self) -> NativeFunctionABI {
|
||||||
self.1
|
self.1
|
||||||
}
|
}
|
||||||
fn call(&self, args: &mut FnCallArgs, pos: Position) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, args: &mut FnCallArgs) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
(self.0)(args, pos)
|
(self.0)(args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,9 +7,8 @@ use crate::engine::Engine;
|
|||||||
use crate::fn_native::{FnCallArgs, NativeFunctionABI::*};
|
use crate::fn_native::{FnCallArgs, NativeFunctionABI::*};
|
||||||
use crate::parser::FnAccess;
|
use crate::parser::FnAccess;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
|
||||||
|
|
||||||
use crate::stdlib::{any::TypeId, boxed::Box, iter::empty, mem, string::ToString};
|
use crate::stdlib::{any::TypeId, boxed::Box, mem, string::ToString};
|
||||||
|
|
||||||
/// A trait to register custom functions with the `Engine`.
|
/// A trait to register custom functions with the `Engine`.
|
||||||
pub trait RegisterFn<FN, ARGS, RET> {
|
pub trait RegisterFn<FN, ARGS, RET> {
|
||||||
@ -140,7 +139,7 @@ macro_rules! make_func {
|
|||||||
// ^ function parameter generic type name (A, B, C etc.)
|
// ^ function parameter generic type name (A, B, C etc.)
|
||||||
// ^ dereferencing function
|
// ^ dereferencing function
|
||||||
|
|
||||||
Box::new(move |args: &mut FnCallArgs, pos: Position| {
|
Box::new(move |args: &mut FnCallArgs| {
|
||||||
// The arguments are assumed to be of the correct number and types!
|
// The arguments are assumed to be of the correct number and types!
|
||||||
|
|
||||||
#[allow(unused_variables, unused_mut)]
|
#[allow(unused_variables, unused_mut)]
|
||||||
@ -155,23 +154,20 @@ macro_rules! make_func {
|
|||||||
let r = $fn($($par),*);
|
let r = $fn($($par),*);
|
||||||
|
|
||||||
// Map the result
|
// Map the result
|
||||||
$map(r, pos)
|
$map(r)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To Dynamic mapping function.
|
/// To Dynamic mapping function.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn map_dynamic<T: Variant + Clone>(
|
pub fn map_dynamic<T: Variant + Clone>(data: T) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
data: T,
|
|
||||||
_pos: Position,
|
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
Ok(data.into_dynamic())
|
Ok(data.into_dynamic())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// To Dynamic mapping function.
|
/// To Dynamic mapping function.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn map_identity(data: Dynamic, _pos: Position) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn map_identity(data: Dynamic) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,10 +175,8 @@ pub fn map_identity(data: Dynamic, _pos: Position) -> Result<Dynamic, Box<EvalAl
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn map_result<T: Variant + Clone>(
|
pub fn map_result<T: Variant + Clone>(
|
||||||
data: Result<T, Box<EvalAltResult>>,
|
data: Result<T, Box<EvalAltResult>>,
|
||||||
pos: Position,
|
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
data.map(|v| v.into_dynamic())
|
data.map(|v| v.into_dynamic())
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! def_register {
|
macro_rules! def_register {
|
||||||
|
@ -317,11 +317,7 @@ impl Module {
|
|||||||
#[cfg(not(feature = "sync"))] func: impl Fn() -> FuncReturn<T> + 'static,
|
#[cfg(not(feature = "sync"))] func: impl Fn() -> FuncReturn<T> + 'static,
|
||||||
#[cfg(feature = "sync")] func: impl Fn() -> FuncReturn<T> + Send + Sync + 'static,
|
#[cfg(feature = "sync")] func: impl Fn() -> FuncReturn<T> + Send + Sync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |_: &mut FnCallArgs, pos| {
|
let f = move |_: &mut FnCallArgs| func().map(Dynamic::from);
|
||||||
func()
|
|
||||||
.map(Dynamic::from)
|
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
};
|
|
||||||
let arg_types = [];
|
let arg_types = [];
|
||||||
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
||||||
}
|
}
|
||||||
@ -345,11 +341,8 @@ impl Module {
|
|||||||
#[cfg(not(feature = "sync"))] func: impl Fn(A) -> FuncReturn<T> + 'static,
|
#[cfg(not(feature = "sync"))] func: impl Fn(A) -> FuncReturn<T> + 'static,
|
||||||
#[cfg(feature = "sync")] func: impl Fn(A) -> FuncReturn<T> + Send + Sync + 'static,
|
#[cfg(feature = "sync")] func: impl Fn(A) -> FuncReturn<T> + Send + Sync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |args: &mut FnCallArgs, pos| {
|
let f =
|
||||||
func(mem::take(args[0]).cast::<A>())
|
move |args: &mut FnCallArgs| func(mem::take(args[0]).cast::<A>()).map(Dynamic::from);
|
||||||
.map(Dynamic::from)
|
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
};
|
|
||||||
let arg_types = [TypeId::of::<A>()];
|
let arg_types = [TypeId::of::<A>()];
|
||||||
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
||||||
}
|
}
|
||||||
@ -373,10 +366,8 @@ impl Module {
|
|||||||
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A) -> FuncReturn<T> + 'static,
|
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A) -> FuncReturn<T> + 'static,
|
||||||
#[cfg(feature = "sync")] func: impl Fn(&mut A) -> FuncReturn<T> + Send + Sync + 'static,
|
#[cfg(feature = "sync")] func: impl Fn(&mut A) -> FuncReturn<T> + Send + Sync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |args: &mut FnCallArgs, pos| {
|
let f = move |args: &mut FnCallArgs| {
|
||||||
func(args[0].downcast_mut::<A>().unwrap())
|
func(args[0].downcast_mut::<A>().unwrap()).map(Dynamic::from)
|
||||||
.map(Dynamic::from)
|
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>()];
|
let arg_types = [TypeId::of::<A>()];
|
||||||
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
||||||
@ -403,13 +394,11 @@ impl Module {
|
|||||||
#[cfg(not(feature = "sync"))] func: impl Fn(A, B) -> FuncReturn<T> + 'static,
|
#[cfg(not(feature = "sync"))] func: impl Fn(A, B) -> FuncReturn<T> + 'static,
|
||||||
#[cfg(feature = "sync")] func: impl Fn(A, B) -> FuncReturn<T> + Send + Sync + 'static,
|
#[cfg(feature = "sync")] func: impl Fn(A, B) -> FuncReturn<T> + Send + Sync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |args: &mut FnCallArgs, pos| {
|
let f = move |args: &mut FnCallArgs| {
|
||||||
let a = mem::take(args[0]).cast::<A>();
|
let a = mem::take(args[0]).cast::<A>();
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
|
|
||||||
func(a, b)
|
func(a, b).map(Dynamic::from)
|
||||||
.map(Dynamic::from)
|
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
||||||
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
||||||
@ -440,13 +429,11 @@ impl Module {
|
|||||||
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B) -> FuncReturn<T> + 'static,
|
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B) -> FuncReturn<T> + 'static,
|
||||||
#[cfg(feature = "sync")] func: impl Fn(&mut A, B) -> FuncReturn<T> + Send + Sync + 'static,
|
#[cfg(feature = "sync")] func: impl Fn(&mut A, B) -> FuncReturn<T> + Send + Sync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |args: &mut FnCallArgs, pos| {
|
let f = move |args: &mut FnCallArgs| {
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let a = args[0].downcast_mut::<A>().unwrap();
|
let a = args[0].downcast_mut::<A>().unwrap();
|
||||||
|
|
||||||
func(a, b)
|
func(a, b).map(Dynamic::from)
|
||||||
.map(Dynamic::from)
|
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>()];
|
||||||
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
||||||
@ -479,14 +466,12 @@ impl Module {
|
|||||||
#[cfg(not(feature = "sync"))] func: impl Fn(A, B, C) -> FuncReturn<T> + 'static,
|
#[cfg(not(feature = "sync"))] func: impl Fn(A, B, C) -> FuncReturn<T> + 'static,
|
||||||
#[cfg(feature = "sync")] func: impl Fn(A, B, C) -> FuncReturn<T> + Send + Sync + 'static,
|
#[cfg(feature = "sync")] func: impl Fn(A, B, C) -> FuncReturn<T> + Send + Sync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |args: &mut FnCallArgs, pos| {
|
let f = move |args: &mut FnCallArgs| {
|
||||||
let a = mem::take(args[0]).cast::<A>();
|
let a = mem::take(args[0]).cast::<A>();
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let c = mem::take(args[2]).cast::<C>();
|
let c = mem::take(args[2]).cast::<C>();
|
||||||
|
|
||||||
func(a, b, c)
|
func(a, b, c).map(Dynamic::from)
|
||||||
.map(Dynamic::from)
|
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), Pure, DEF_ACCESS, &arg_types, Box::new(f))
|
||||||
@ -520,14 +505,12 @@ impl Module {
|
|||||||
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B, C) -> FuncReturn<T> + 'static,
|
#[cfg(not(feature = "sync"))] func: impl Fn(&mut A, B, C) -> FuncReturn<T> + 'static,
|
||||||
#[cfg(feature = "sync")] func: impl Fn(&mut A, B, C) -> FuncReturn<T> + Send + Sync + 'static,
|
#[cfg(feature = "sync")] func: impl Fn(&mut A, B, C) -> FuncReturn<T> + Send + Sync + 'static,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let f = move |args: &mut FnCallArgs, pos| {
|
let f = move |args: &mut FnCallArgs| {
|
||||||
let b = mem::take(args[1]).cast::<B>();
|
let b = mem::take(args[1]).cast::<B>();
|
||||||
let c = mem::take(args[2]).cast::<C>();
|
let c = mem::take(args[2]).cast::<C>();
|
||||||
let a = args[0].downcast_mut::<A>().unwrap();
|
let a = args[0].downcast_mut::<A>().unwrap();
|
||||||
|
|
||||||
func(a, b, c)
|
func(a, b, c).map(Dynamic::from)
|
||||||
.map(Dynamic::from)
|
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
};
|
};
|
||||||
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
let arg_types = [TypeId::of::<A>(), TypeId::of::<B>(), TypeId::of::<C>()];
|
||||||
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
self.set_fn(name.into(), Method, DEF_ACCESS, &arg_types, Box::new(f))
|
||||||
@ -559,12 +542,16 @@ impl Module {
|
|||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
hash_fn_native: u64,
|
hash_fn_native: u64,
|
||||||
pos: Position,
|
|
||||||
) -> Result<&Box<dyn NativeCallable>, Box<EvalAltResult>> {
|
) -> Result<&Box<dyn NativeCallable>, Box<EvalAltResult>> {
|
||||||
self.all_functions
|
self.all_functions
|
||||||
.get(&hash_fn_native)
|
.get(&hash_fn_native)
|
||||||
.map(|f| f.as_ref())
|
.map(|f| f.as_ref())
|
||||||
.ok_or_else(|| Box::new(EvalAltResult::ErrorFunctionNotFound(name.to_string(), pos)))
|
.ok_or_else(|| {
|
||||||
|
Box::new(EvalAltResult::ErrorFunctionNotFound(
|
||||||
|
name.to_string(),
|
||||||
|
Position::none(),
|
||||||
|
))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a modules-qualified script-defined functions.
|
/// Get a modules-qualified script-defined functions.
|
||||||
@ -950,10 +937,9 @@ mod file {
|
|||||||
// Compile it
|
// Compile it
|
||||||
let ast = engine
|
let ast = engine
|
||||||
.compile_file(file_path)
|
.compile_file(file_path)
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))?;
|
.map_err(|err| err.new_position(pos))?;
|
||||||
|
|
||||||
Module::eval_ast_as_new(scope, &ast, engine)
|
Module::eval_ast_as_new(scope, &ast, engine).map_err(|err| err.new_position(pos))
|
||||||
.map_err(|err| EvalAltResult::set_position(err, pos))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,8 +124,9 @@ fn call_fn(
|
|||||||
global_module
|
global_module
|
||||||
.get_fn(hash)
|
.get_fn(hash)
|
||||||
.or_else(|| packages.get_fn(hash))
|
.or_else(|| packages.get_fn(hash))
|
||||||
.map(|func| func.call(args, pos))
|
.map(|func| func.call(args))
|
||||||
.transpose()
|
.transpose()
|
||||||
|
.map_err(|err| err.new_position(pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optimize a statement.
|
/// Optimize a statement.
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::def_package;
|
use crate::def_package;
|
||||||
use crate::module::FuncReturn;
|
|
||||||
use crate::parser::INT;
|
use crate::parser::INT;
|
||||||
use crate::result::EvalAltResult;
|
use crate::result::EvalAltResult;
|
||||||
use crate::token::Position;
|
use crate::token::Position;
|
||||||
|
@ -516,7 +516,7 @@ impl Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the `Position` of the expression.
|
/// Override the `Position` of the expression.
|
||||||
pub(crate) fn set_position(mut self, new_pos: Position) -> Self {
|
pub(crate) fn set_position(mut self, new_pos: Position) -> Self {
|
||||||
match &mut self {
|
match &mut self {
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
@ -33,6 +33,9 @@ pub enum EvalAltResult {
|
|||||||
|
|
||||||
/// 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),
|
||||||
|
/// An error has occurred inside a called function.
|
||||||
|
/// Wrapped values re the name of the function and the interior error.
|
||||||
|
ErrorInFunctionCall(String, Box<EvalAltResult>, Position),
|
||||||
/// Function call has incorrect number of arguments.
|
/// Function call has incorrect number of arguments.
|
||||||
/// Wrapped values are the name of the function, the number of parameters required
|
/// Wrapped values are the name of the function, the number of parameters required
|
||||||
/// and the actual number of arguments passed.
|
/// and the actual number of arguments passed.
|
||||||
@ -97,6 +100,7 @@ impl EvalAltResult {
|
|||||||
Self::ErrorReadingScriptFile(_, _, _) => "Cannot read from script file",
|
Self::ErrorReadingScriptFile(_, _, _) => "Cannot read from script file",
|
||||||
|
|
||||||
Self::ErrorParsing(p) => p.desc(),
|
Self::ErrorParsing(p) => p.desc(),
|
||||||
|
Self::ErrorInFunctionCall(_, _, _) => "Error in called function",
|
||||||
Self::ErrorFunctionNotFound(_, _) => "Function not found",
|
Self::ErrorFunctionNotFound(_, _) => "Function not found",
|
||||||
Self::ErrorFunctionArgsMismatch(_, _, _, _) => {
|
Self::ErrorFunctionArgsMismatch(_, _, _, _) => {
|
||||||
"Function call with wrong number of arguments"
|
"Function call with wrong number of arguments"
|
||||||
@ -160,6 +164,10 @@ impl fmt::Display for EvalAltResult {
|
|||||||
|
|
||||||
Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p),
|
Self::ErrorParsing(p) => write!(f, "Syntax error: {}", p),
|
||||||
|
|
||||||
|
Self::ErrorInFunctionCall(s, err, pos) => {
|
||||||
|
write!(f, "Error in call to function '{}' ({}): {}", s, pos, err)
|
||||||
|
}
|
||||||
|
|
||||||
Self::ErrorFunctionNotFound(s, pos)
|
Self::ErrorFunctionNotFound(s, pos)
|
||||||
| Self::ErrorVariableNotFound(s, pos)
|
| Self::ErrorVariableNotFound(s, pos)
|
||||||
| Self::ErrorModuleNotFound(s, pos) => write!(f, "{}: '{}' ({})", desc, s, pos),
|
| Self::ErrorModuleNotFound(s, pos) => write!(f, "{}: '{}' ({})", desc, s, pos),
|
||||||
@ -262,6 +270,7 @@ impl<T: AsRef<str>> From<T> for Box<EvalAltResult> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EvalAltResult {
|
impl EvalAltResult {
|
||||||
|
/// Get the `Position` of this error.
|
||||||
pub fn position(&self) -> Position {
|
pub fn position(&self) -> Position {
|
||||||
match self {
|
match self {
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
@ -270,6 +279,7 @@ impl EvalAltResult {
|
|||||||
Self::ErrorParsing(err) => err.position(),
|
Self::ErrorParsing(err) => err.position(),
|
||||||
|
|
||||||
Self::ErrorFunctionNotFound(_, pos)
|
Self::ErrorFunctionNotFound(_, pos)
|
||||||
|
| Self::ErrorInFunctionCall(_, _, pos)
|
||||||
| Self::ErrorFunctionArgsMismatch(_, _, _, pos)
|
| Self::ErrorFunctionArgsMismatch(_, _, _, pos)
|
||||||
| Self::ErrorBooleanArgMismatch(_, pos)
|
| Self::ErrorBooleanArgMismatch(_, pos)
|
||||||
| Self::ErrorCharMismatch(pos)
|
| Self::ErrorCharMismatch(pos)
|
||||||
@ -296,16 +306,16 @@ impl EvalAltResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume the current `EvalAltResult` and return a new one
|
/// Override the `Position` of this error.
|
||||||
/// with the specified `Position`.
|
pub fn set_position(&mut self, new_position: Position) {
|
||||||
pub(crate) fn set_position(mut err: Box<Self>, new_position: Position) -> Box<Self> {
|
match self {
|
||||||
match err.as_mut() {
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
Self::ErrorReadingScriptFile(_, pos, _) => *pos = new_position,
|
Self::ErrorReadingScriptFile(_, pos, _) => *pos = new_position,
|
||||||
|
|
||||||
Self::ErrorParsing(err) => err.1 = new_position,
|
Self::ErrorParsing(err) => err.1 = new_position,
|
||||||
|
|
||||||
Self::ErrorFunctionNotFound(_, pos)
|
Self::ErrorFunctionNotFound(_, pos)
|
||||||
|
| Self::ErrorInFunctionCall(_, _, pos)
|
||||||
| Self::ErrorFunctionArgsMismatch(_, _, _, pos)
|
| Self::ErrorFunctionArgsMismatch(_, _, _, pos)
|
||||||
| Self::ErrorBooleanArgMismatch(_, pos)
|
| Self::ErrorBooleanArgMismatch(_, pos)
|
||||||
| Self::ErrorCharMismatch(pos)
|
| Self::ErrorCharMismatch(pos)
|
||||||
@ -330,7 +340,12 @@ impl EvalAltResult {
|
|||||||
| Self::ErrorLoopBreak(_, pos)
|
| Self::ErrorLoopBreak(_, pos)
|
||||||
| Self::Return(_, pos) => *pos = new_position,
|
| Self::Return(_, pos) => *pos = new_position,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err
|
/// Consume the current `EvalAltResult` and return a new one
|
||||||
|
/// with the specified `Position`.
|
||||||
|
pub(crate) fn new_position(mut self: Box<Self>, new_position: Position) -> Box<Self> {
|
||||||
|
self.set_position(new_position);
|
||||||
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#![cfg(not(feature = "no_function"))]
|
#![cfg(not(feature = "no_function"))]
|
||||||
use rhai::{Engine, EvalAltResult, Func, ParseErrorType, Scope, INT};
|
use rhai::{Engine, EvalAltResult, INT};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_functions() -> Result<(), Box<EvalAltResult>> {
|
fn test_functions() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
@ -41,7 +41,7 @@ fn test_method_call() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_method_call_style() -> Result<(), Box<EvalAltResult>> {
|
fn test_method_call_style() -> Result<(), Box<EvalAltResult>> {
|
||||||
let mut engine = Engine::new();
|
let engine = Engine::new();
|
||||||
|
|
||||||
assert_eq!(engine.eval::<INT>("let x = -123; x.abs(); x")?, -123);
|
assert_eq!(engine.eval::<INT>("let x = -123; x.abs(); x")?, -123);
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ fn test_stack_overflow() -> Result<(), Box<EvalAltResult>> {
|
|||||||
) {
|
) {
|
||||||
Ok(_) => panic!("should be stack overflow"),
|
Ok(_) => panic!("should be stack overflow"),
|
||||||
Err(err) => match *err {
|
Err(err) => match *err {
|
||||||
EvalAltResult::ErrorStackOverflow(_) => (),
|
EvalAltResult::ErrorInFunctionCall(name, _, _)
|
||||||
|
if name.starts_with("foo > foo > foo") => {}
|
||||||
_ => panic!("should be stack overflow"),
|
_ => panic!("should be stack overflow"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user