From bb827c55cede7e1ed0fbbb36e11891557ecc0140 Mon Sep 17 00:00:00 2001 From: Ophir LOJKINE Date: Mon, 15 Apr 2019 00:07:07 +0200 Subject: [PATCH] Add a macro for easy context definition --- src/context/mod.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/context/mod.rs b/src/context/mod.rs index d58199b..d86d73a 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -93,3 +93,45 @@ impl Context for HashMapContext { Ok(()) } } + +/// This macro provides a convenient syntax for creating a static context +/// +/// ```rust +/// use evalexpr::*; +/// +/// let ctx = evalexpr::context_map! { +/// "x" => 8, +/// "f" => Function::new(None, Box::new(|_| Ok(42.into()) )) +/// }.unwrap(); +/// +/// assert_eq!(eval_with_context("x + f()", &ctx), Ok(50.into())); +/// ``` +#[macro_export] +macro_rules! context_map { + // Termination (allow missing comma at the end of the argument list) + ( ($ctx:expr) $k:expr => Function::new($($v:tt)*) ) => + { $crate::context_map!(($ctx) $k => Function::new($($v)*),) }; + ( ($ctx:expr) $k:expr => $v:expr ) => + { $crate::context_map!(($ctx) $k => $v,) }; + // Termination + ( ($ctx:expr) ) => { Ok(()) }; + + // The user has to specify a literal 'Function::new' in order to create a function + ( ($ctx:expr) $k:expr => Function::new($($v:tt)*) , $($tt:tt)*) => {{ + $ctx.set_function($k.into(), $crate::Function::new($($v)*)) + .and($crate::context_map!(($ctx) $($tt)*)) + }}; + // add a value, and chain the eventual error with the ones in the next values + ( ($ctx:expr) $k:expr => $v:expr , $($tt:tt)*) => {{ + $ctx.set_value($k.into(), $v.into()) + .and($crate::context_map!(($ctx) $($tt)*)) + }}; + + // Create a context, then recurse to add the values in it + ( $($tt:tt)* ) => {{ + use $crate::Context; + let mut context = $crate::HashMapContext::new(); + $crate::context_map!((context) $($tt)*) + .map(|_| context) + }}; +}