Add for statement and range function; New register_box_fn for functions returning Box<dyn Any> (which should not be boxed again); Register standard utility functions in library (e.g. print, string concat).
This commit is contained in:
@@ -6,6 +6,9 @@ use crate::engine::{Engine, EvalAltResult};
|
||||
pub trait RegisterFn<FN, ARGS, RET> {
|
||||
fn register_fn(&mut self, name: &str, f: FN);
|
||||
}
|
||||
pub trait RegisterBoxFn<FN, ARGS> {
|
||||
fn register_box_fn(&mut self, name: &str, f: FN);
|
||||
}
|
||||
|
||||
pub struct Ref<A>(A);
|
||||
pub struct Mut<A>(A);
|
||||
@@ -44,7 +47,37 @@ macro_rules! def_register {
|
||||
|
||||
// Call the user-supplied function using ($clone) to
|
||||
// potentially clone the value, otherwise pass the reference.
|
||||
Ok(Box::new(f($(($clone)($par)),*)) as Box<dyn Any>)
|
||||
let r = f($(($clone)($par)),*);
|
||||
Ok(Box::new(r) as Box<dyn Any>)
|
||||
};
|
||||
self.register_fn_raw(name.to_owned(), Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($par,)* FN> RegisterBoxFn<FN, ($($mark,)*)> for Engine
|
||||
where
|
||||
$($par: Any + Clone,)*
|
||||
FN: Fn($($param),*) -> Box<dyn Any> + 'static
|
||||
{
|
||||
fn register_box_fn(&mut self, name: &str, f: FN) {
|
||||
let fun = move |mut args: Vec<&mut dyn Any>| {
|
||||
// Check for length at the beginning to avoid
|
||||
// per-element bound checks.
|
||||
if args.len() != count_args!($($par)*) {
|
||||
return Err(EvalAltResult::ErrorFunctionArgMismatch);
|
||||
}
|
||||
|
||||
#[allow(unused_variables, unused_mut)]
|
||||
let mut drain = args.drain(..);
|
||||
$(
|
||||
// Downcast every element, return in case of a type mismatch
|
||||
let $par = ((*drain.next().unwrap()).downcast_mut() as Option<&mut $par>)
|
||||
.ok_or(EvalAltResult::ErrorFunctionArgMismatch)?;
|
||||
)*
|
||||
|
||||
// Call the user-supplied function using ($clone) to
|
||||
// potentially clone the value, otherwise pass the reference.
|
||||
Ok(f($(($clone)($par)),*))
|
||||
};
|
||||
self.register_fn_raw(name.to_owned(), Some(vec![$(TypeId::of::<$par>()),*]), Box::new(fun));
|
||||
}
|
||||
|
Reference in New Issue
Block a user