Document macros.

This commit is contained in:
Stephen Chung 2020-03-25 11:24:06 +08:00
parent 928f044553
commit 180c4dee08
2 changed files with 28 additions and 1 deletions

View File

@ -11,11 +11,15 @@ use crate::engine::Array;
use crate::stdlib::{string::String, vec, vec::Vec}; use crate::stdlib::{string::String, vec, vec::Vec};
/// Trait that represent arguments to a function call. /// 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 { pub trait FuncArgs {
/// Convert to a `Vec` of `Dynamic` arguments. /// Convert to a `Vec` of `Dynamic` arguments.
fn into_vec(self) -> Vec<Dynamic>; fn into_vec(self) -> Vec<Dynamic>;
} }
/// Macro to implement `FuncArgs` for a single standard type that can be converted
/// into `Dynamic`.
macro_rules! impl_std_args { macro_rules! impl_std_args {
($($p:ty),*) => { ($($p:ty),*) => {
$( $(
@ -43,6 +47,8 @@ impl_std_args!(INT);
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
impl_std_args!(f32, f64); impl_std_args!(f32, f64);
/// Macro to implement `FuncArgs` for tuples of standard types (each can be
/// converted into `Dynamic`).
macro_rules! impl_args { macro_rules! impl_args {
($($p:ident),*) => { ($($p:ident),*) => {
impl<$($p: Any + Clone),*> FuncArgs for ($($p,)*) impl<$($p: Any + Clone),*> FuncArgs for ($($p,)*)

View File

@ -80,7 +80,8 @@ pub trait RegisterResultFn<FN, ARGS, RET> {
/// // Normal function /// // Normal function
/// fn div(x: i64, y: i64) -> Result<i64, EvalAltResult> { /// fn div(x: i64, y: i64) -> Result<i64, EvalAltResult> {
/// if y == 0 { /// 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 { /// } else {
/// Ok(x / y) /// Ok(x / y)
/// } /// }
@ -97,14 +98,28 @@ pub trait RegisterResultFn<FN, ARGS, RET> {
fn register_result_fn(&mut self, name: &str, f: FN); 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<FN, (Mut<A>, B, Ref<C>), 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>(A); pub struct Ref<A>(A);
pub struct Mut<A>(A); pub struct Mut<A>(A);
/// Identity dereferencing function.
#[inline] #[inline]
fn identity<T>(data: T) -> T { fn identity<T>(data: T) -> T {
data data
} }
/// This macro counts the number of arguments via recursion.
macro_rules! count_args { macro_rules! count_args {
() => { 0_usize }; () => { 0_usize };
( $head:ident $($tail:ident)* ) => { 1_usize + count_args!($($tail)*) }; ( $head:ident $($tail:ident)* ) => { 1_usize + count_args!($($tail)*) };
@ -115,6 +130,10 @@ macro_rules! def_register {
def_register!(imp); def_register!(imp);
}; };
(imp $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => { (imp $($par:ident => $mark:ty => $param:ty => $clone:expr),*) => {
// ^ function parameter generic type name
// ^ function parameter marker type (A, Ref<A> or Mut<A>)
// ^ function parameter actual type
// ^ dereferencing function
impl< impl<
$($par: Any + Clone,)* $($par: Any + Clone,)*
FN: Fn($($param),*) -> RET + 'static, 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 => $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 => Ref<$p0> => &$p0 => identity $(, $p => $p => $p => Clone::clone)*);
def_register!(imp $p0 => Mut<$p0> => &mut $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),*); def_register!($($p),*);
}; };