diff --git a/src/call.rs b/src/call.rs index ddd5f927..5ecbf66d 100644 --- a/src/call.rs +++ b/src/call.rs @@ -11,11 +11,15 @@ use crate::engine::Array; use crate::stdlib::{string::String, vec, vec::Vec}; /// Trait that represent arguments to a function call. +/// Any data type that can be converted into a `Vec` of `Dynamic` values can be used +/// as arguments to a function call. pub trait FuncArgs { /// Convert to a `Vec` of `Dynamic` arguments. fn into_vec(self) -> Vec; } +/// Macro to implement `FuncArgs` for a single standard type that can be converted +/// into `Dynamic`. macro_rules! impl_std_args { ($($p:ty),*) => { $( @@ -43,6 +47,8 @@ impl_std_args!(INT); #[cfg(not(feature = "no_float"))] impl_std_args!(f32, f64); +/// Macro to implement `FuncArgs` for tuples of standard types (each can be +/// converted into `Dynamic`). macro_rules! impl_args { ($($p:ident),*) => { impl<$($p: Any + Clone),*> FuncArgs for ($($p,)*) diff --git a/src/fn_register.rs b/src/fn_register.rs index 79ca5735..a9da5cdf 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -80,7 +80,8 @@ pub trait RegisterResultFn { /// // Normal function /// fn div(x: i64, y: i64) -> Result { /// if y == 0 { - /// Err("division by zero!".into()) // '.into()' automatically converts to 'EvalAltResult::ErrorRuntime' + /// // '.into()' automatically converts to 'EvalAltResult::ErrorRuntime' + /// Err("division by zero!".into()) /// } else { /// Ok(x / y) /// } @@ -97,14 +98,28 @@ pub trait RegisterResultFn { fn register_result_fn(&mut self, name: &str, f: FN); } +// These types are used to build a unique _marker_ tuple type for each combination +// of function parameter types in order to make each trait implementation unique. +// +// For example: +// +// `RegisterFn, B, Ref), R>` +// +// will have the function prototype constraint to: +// +// `FN: (&mut A, B, &C) -> R` +// +// These types are not actually used anywhere. pub struct Ref(A); pub struct Mut(A); +/// Identity dereferencing function. #[inline] fn identity(data: T) -> T { data } +/// This macro counts the number of arguments via recursion. macro_rules! count_args { () => { 0_usize }; ( $head:ident $($tail:ident)* ) => { 1_usize + count_args!($($tail)*) }; @@ -115,6 +130,10 @@ macro_rules! def_register { def_register!(imp); }; (imp $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => { + // ^ function parameter generic type name + // ^ function parameter marker type (A, Ref or Mut) + // ^ function parameter actual type + // ^ dereferencing function impl< $($par: Any + Clone,)* FN: Fn($($param),*) -> RET + 'static, @@ -220,6 +239,8 @@ macro_rules! def_register { def_register!(imp $p0 => $p0 => $p0 => Clone::clone $(, $p => $p => $p => Clone::clone)*); def_register!(imp $p0 => Ref<$p0> => &$p0 => identity $(, $p => $p => $p => Clone::clone)*); def_register!(imp $p0 => Mut<$p0> => &mut $p0 => identity $(, $p => $p => $p => Clone::clone)*); + // handle the first parameter ^ first parameter passed through + // others passed by value (cloned) ^ def_register!($($p),*); };