From 976f3a7f6d60f9835614d1ec5679e8c11ee48eab Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 20 Apr 2020 12:43:34 +0800 Subject: [PATCH] Avoid an allocation in each function registration. --- src/api.rs | 6 ------ src/fn_register.rs | 23 +++++++++++++++-------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/api.rs b/src/api.rs index 4bc12510..750b6447 100644 --- a/src/api.rs +++ b/src/api.rs @@ -60,12 +60,6 @@ impl Box> + 'static> IteratorCal /// Engine public API impl Engine { - /// Register a custom function. - pub(crate) fn register_fn_raw(&mut self, fn_name: &str, args: Vec, f: Box) { - self.functions - .insert(calc_fn_spec(fn_name, args.into_iter()), f); - } - /// Register a custom type for use with the `Engine`. /// The type must implement `Clone`. /// diff --git a/src/fn_register.rs b/src/fn_register.rs index b68e483a..269faedd 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -3,11 +3,11 @@ #![allow(non_snake_case)] use crate::any::{Dynamic, Variant}; -use crate::engine::{Engine, FnCallArgs}; +use crate::engine::{calc_fn_spec, Engine, FnCallArgs}; use crate::result::EvalAltResult; use crate::token::Position; -use crate::stdlib::{any::TypeId, boxed::Box, string::ToString, vec}; +use crate::stdlib::{any::TypeId, boxed::Box, string::ToString}; /// A trait to register custom functions with the `Engine`. pub trait RegisterFn { @@ -128,6 +128,7 @@ macro_rules! count_args { } /// This macro creates a closure wrapping a registered function. +#[macro_export] macro_rules! make_func { ($fn_name:ident : $fn:ident : $map:expr ; $($par:ident => $clone:expr),*) => { // ^ function name @@ -161,19 +162,22 @@ macro_rules! make_func { /// To Dynamic mapping function. #[inline] -fn map_dynamic(data: T, _pos: Position) -> Result> { +pub fn map_dynamic( + data: T, + _pos: Position, +) -> Result> { Ok(data.into_dynamic()) } /// To Dynamic mapping function. #[inline] -fn map_identity(data: Dynamic, _pos: Position) -> Result> { +pub fn map_identity(data: Dynamic, _pos: Position) -> Result> { Ok(data) } /// To Result mapping function. #[inline] -fn map_result( +pub fn map_result( data: Result, pos: Position, ) -> Result> { @@ -205,7 +209,8 @@ macro_rules! def_register { fn register_fn(&mut self, name: &str, f: FN) { let fn_name = name.to_string(); let func = make_func!(fn_name : f : map_dynamic ; $($par => $clone),*); - self.register_fn_raw(name, vec![$(TypeId::of::<$par>()),*], Box::new(func)); + let hash = calc_fn_spec(name, [$(TypeId::of::<$par>()),*].iter().cloned()); + self.functions.insert(hash, Box::new(func)); } } @@ -222,7 +227,8 @@ macro_rules! def_register { fn register_dynamic_fn(&mut self, name: &str, f: FN) { let fn_name = name.to_string(); let func = make_func!(fn_name : f : map_identity ; $($par => $clone),*); - self.register_fn_raw(name, vec![$(TypeId::of::<$par>()),*], Box::new(func)); + let hash = calc_fn_spec(name, [$(TypeId::of::<$par>()),*].iter().cloned()); + self.functions.insert(hash, Box::new(func)); } } @@ -240,7 +246,8 @@ macro_rules! def_register { fn register_result_fn(&mut self, name: &str, f: FN) { let fn_name = name.to_string(); let func = make_func!(fn_name : f : map_result ; $($par => $clone),*); - self.register_fn_raw(name, vec![$(TypeId::of::<$par>()),*], Box::new(func)); + let hash = calc_fn_spec(name, [$(TypeId::of::<$par>()),*].iter().cloned()); + self.functions.insert(hash, Box::new(func)); } }