From d0922adb5b75b97b5a9ee0ea8c00ed537386293b Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 15 Mar 2021 11:36:30 +0800 Subject: [PATCH] Deprecate RegisterFn and RegisterResultFn. --- CHANGELOG.md | 6 + benches/engine.rs | 2 +- benches/eval_type.rs | 2 +- codegen/src/lib.rs | 4 +- codegen/tests/test_functions.rs | 2 +- codegen/tests/test_modules.rs | 2 +- codegen/tests/test_nested.rs | 2 +- examples/arrays_and_structs.rs | 2 +- examples/custom_types_and_methods.rs | 2 +- examples/simple_fn.rs | 2 +- examples/strings.rs | 2 +- examples/threading.rs | 2 +- src/engine_api.rs | 112 +++++++++++---- src/engine_settings.rs | 2 +- src/fn_native.rs | 4 +- src/fn_register.rs | 195 +++++++++++---------------- src/lib.rs | 4 +- src/packages/array_basic.rs | 50 +++---- src/plugin.rs | 2 +- tests/arrays.rs | 2 +- tests/call_fn.rs | 4 +- tests/closures.rs | 10 +- tests/constants.rs | 2 +- tests/float.rs | 2 +- tests/fn_ptr.rs | 2 +- tests/functions.rs | 2 +- tests/get_set.rs | 2 +- tests/method_call.rs | 2 +- tests/mismatched_op.rs | 2 +- tests/optimizer.rs | 2 +- tests/print.rs | 2 +- tests/side_effects.rs | 2 +- tests/string.rs | 2 +- tests/tokens.rs | 2 +- tests/types.rs | 2 +- 35 files changed, 235 insertions(+), 206 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b705550f..2a841377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ Rhai Release Notes Version 0.19.15 =============== +Breaking changes +---------------- + +* The traits `RegisterFn` and `RegisterResultFn` are removed. `Engine::register_fn` and `Engine::register_result_fn` are now implemented directly on `Engine`. +* `FnPtr::call_dynamic` now takes `&NativeCallContext` instead of consuming it. + Version 0.19.14 =============== diff --git a/benches/engine.rs b/benches/engine.rs index 0cfc2972..70643a08 100644 --- a/benches/engine.rs +++ b/benches/engine.rs @@ -3,7 +3,7 @@ ///! Test evaluating expressions extern crate test; -use rhai::{Array, Engine, Map, RegisterFn, INT}; +use rhai::{Array, Engine, Map, INT}; use test::Bencher; #[bench] diff --git a/benches/eval_type.rs b/benches/eval_type.rs index 1e5a70c8..469e6332 100644 --- a/benches/eval_type.rs +++ b/benches/eval_type.rs @@ -3,7 +3,7 @@ ///! Test evaluating expressions extern crate test; -use rhai::{Engine, OptimizationLevel, RegisterFn, Scope, INT}; +use rhai::{Engine, OptimizationLevel, Scope, INT}; use test::Bencher; #[derive(Debug, Clone)] diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 13396a8b..7ba9e874 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -35,7 +35,7 @@ //! # Register a Rust Function with a Rhai `Module` //! //! ``` -//! use rhai::{EvalAltResult, FLOAT, Module, RegisterFn}; +//! use rhai::{EvalAltResult, FLOAT, Module}; //! use rhai::plugin::*; //! use rhai::module_resolvers::*; //! @@ -65,7 +65,7 @@ //! # Register a Plugin Function with an `Engine` //! //! ``` -//! use rhai::{EvalAltResult, FLOAT, Module, RegisterFn}; +//! use rhai::{EvalAltResult, FLOAT, Module}; //! use rhai::plugin::*; //! use rhai::module_resolvers::*; //! diff --git a/codegen/tests/test_functions.rs b/codegen/tests/test_functions.rs index 303076e2..86def42e 100644 --- a/codegen/tests/test_functions.rs +++ b/codegen/tests/test_functions.rs @@ -1,6 +1,6 @@ use rhai::module_resolvers::*; use rhai::plugin::*; -use rhai::{Engine, EvalAltResult, Module, RegisterFn, FLOAT}; +use rhai::{Engine, EvalAltResult, Module, FLOAT}; pub mod raw_fn { use rhai::plugin::*; diff --git a/codegen/tests/test_modules.rs b/codegen/tests/test_modules.rs index 4993c5c3..0e63dad7 100644 --- a/codegen/tests/test_modules.rs +++ b/codegen/tests/test_modules.rs @@ -1,5 +1,5 @@ use rhai::module_resolvers::*; -use rhai::{Array, Engine, EvalAltResult, RegisterFn, FLOAT, INT}; +use rhai::{Array, Engine, EvalAltResult, FLOAT, INT}; pub mod empty_module { use rhai::plugin::*; diff --git a/codegen/tests/test_nested.rs b/codegen/tests/test_nested.rs index 8e3497de..62428282 100644 --- a/codegen/tests/test_nested.rs +++ b/codegen/tests/test_nested.rs @@ -1,5 +1,5 @@ use rhai::module_resolvers::*; -use rhai::{Array, Engine, EvalAltResult, RegisterFn, FLOAT, INT}; +use rhai::{Array, Engine, EvalAltResult, FLOAT, INT}; pub mod one_fn_module_nested_attr { use rhai::plugin::*; diff --git a/examples/arrays_and_structs.rs b/examples/arrays_and_structs.rs index aac28801..374fc834 100644 --- a/examples/arrays_and_structs.rs +++ b/examples/arrays_and_structs.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, INT}; #[derive(Debug, Clone)] struct TestStruct { diff --git a/examples/custom_types_and_methods.rs b/examples/custom_types_and_methods.rs index 5d494fd3..4e06312c 100644 --- a/examples/custom_types_and_methods.rs +++ b/examples/custom_types_and_methods.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, INT}; #[derive(Debug, Clone)] struct TestStruct { diff --git a/examples/simple_fn.rs b/examples/simple_fn.rs index c0c59bad..9b9b000f 100644 --- a/examples/simple_fn.rs +++ b/examples/simple_fn.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, INT}; fn add(x: INT, y: INT) -> INT { x + y diff --git a/examples/strings.rs b/examples/strings.rs index 2ea97511..f10fac94 100644 --- a/examples/strings.rs +++ b/examples/strings.rs @@ -1,6 +1,6 @@ ///! This example registers a variety of functions that operate on strings. ///! Remember to use `ImmutableString` or `&str` instead of `String` as parameters. -use rhai::{Engine, EvalAltResult, ImmutableString, RegisterFn, Scope, INT}; +use rhai::{Engine, EvalAltResult, ImmutableString, Scope, INT}; use std::io::{stdin, stdout, Write}; /// Trim whitespace from a string. The original string argument is changed. diff --git a/examples/threading.rs b/examples/threading.rs index f28da439..2e0aa9d3 100644 --- a/examples/threading.rs +++ b/examples/threading.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, RegisterFn, INT}; +use rhai::{Engine, INT}; #[cfg(feature = "sync")] use std::sync::Mutex; diff --git a/src/engine_api.rs b/src/engine_api.rs index 7218582d..159e822c 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -3,6 +3,7 @@ use crate::dynamic::Variant; use crate::engine::{EvalContext, Imports, State}; use crate::fn_native::{FnCallArgs, SendSync}; +use crate::fn_register::RegisterNativeFunction; use crate::optimize::OptimizationLevel; use crate::stdlib::{ any::{type_name, TypeId}, @@ -24,6 +25,68 @@ use crate::Map; /// Engine public API impl Engine { + /// Register a custom function with the [`Engine`]. + /// + /// # Example + /// + /// ``` + /// # fn main() -> Result<(), Box> { + /// use rhai::Engine; + /// + /// // Normal function + /// fn add(x: i64, y: i64) -> i64 { + /// x + y + /// } + /// + /// let mut engine = Engine::new(); + /// + /// engine.register_fn("add", add); + /// + /// assert_eq!(engine.eval::("add(40, 2)")?, 42); + /// + /// // You can also register a closure. + /// engine.register_fn("sub", |x: i64, y: i64| x - y ); + /// + /// assert_eq!(engine.eval::("sub(44, 2)")?, 42); + /// # Ok(()) + /// # } + /// ``` + pub fn register_fn(&mut self, name: &str, func: impl RegisterNativeFunction) -> &mut Self { + func.register_into(self, name); + self + } + /// Register a custom fallible function with the [`Engine`]. + /// + /// # Example + /// + /// ``` + /// use rhai::{Engine, Dynamic, EvalAltResult}; + /// + /// // Normal function + /// fn div(x: i64, y: i64) -> Result> { + /// if y == 0 { + /// // '.into()' automatically converts to 'Box' + /// Err("division by zero!".into()) + /// } else { + /// Ok((x / y).into()) + /// } + /// } + /// + /// let mut engine = Engine::new(); + /// + /// engine.register_result_fn("div", div); + /// + /// engine.eval::("div(42, 0)") + /// .expect_err("expecting division by zero error!"); + /// ``` + pub fn register_result_fn( + &mut self, + name: &str, + func: impl RegisterNativeFunction, + ) -> &mut Self { + func.register_into(self, name); + self + } /// Register a function of the [`Engine`]. /// /// # WARNING - Low Level API @@ -76,7 +139,7 @@ impl Engine { /// } /// /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// @@ -115,7 +178,7 @@ impl Engine { /// } /// /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// @@ -177,7 +240,7 @@ impl Engine { /// } /// /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// @@ -199,7 +262,7 @@ impl Engine { name: &str, get_fn: impl Fn(&mut T) -> U + SendSync + 'static, ) -> &mut Self { - use crate::{engine::make_getter, RegisterFn}; + use crate::engine::make_getter; self.register_fn(&make_getter(name), get_fn) } /// Register a getter function for a member of a registered type with the [`Engine`]. @@ -209,7 +272,7 @@ impl Engine { /// # Example /// /// ``` - /// use rhai::{Engine, Dynamic, EvalAltResult, RegisterFn}; + /// use rhai::{Engine, Dynamic, EvalAltResult}; /// /// #[derive(Clone)] /// struct TestStruct { @@ -246,7 +309,7 @@ impl Engine { name: &str, get_fn: impl Fn(&mut T) -> RhaiResult + SendSync + 'static, ) -> &mut Self { - use crate::{engine::make_getter, RegisterResultFn}; + use crate::engine::make_getter; self.register_result_fn(&make_getter(name), get_fn) } /// Register a setter function for a member of a registered type with the [`Engine`]. @@ -266,7 +329,7 @@ impl Engine { /// } /// /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// @@ -292,7 +355,7 @@ impl Engine { name: &str, set_fn: impl Fn(&mut T, U) + SendSync + 'static, ) -> &mut Self { - use crate::{engine::make_setter, RegisterFn}; + use crate::engine::make_setter; self.register_fn(&make_setter(name), set_fn) } /// Register a setter function for a member of a registered type with the [`Engine`]. @@ -300,7 +363,7 @@ impl Engine { /// # Example /// /// ``` - /// use rhai::{Engine, Dynamic, EvalAltResult, RegisterFn}; + /// use rhai::{Engine, Dynamic, EvalAltResult}; /// /// #[derive(Debug, Clone, Eq, PartialEq)] /// struct TestStruct { @@ -341,7 +404,7 @@ impl Engine { name: &str, set_fn: impl Fn(&mut T, U) -> Result<(), Box> + SendSync + 'static, ) -> &mut Self { - use crate::{engine::make_setter, RegisterResultFn}; + use crate::engine::make_setter; self.register_result_fn(&make_setter(name), move |obj: &mut T, value: U| { set_fn(obj, value).map(Into::into) }) @@ -369,7 +432,7 @@ impl Engine { /// } /// /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// @@ -420,7 +483,7 @@ impl Engine { /// } /// /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// @@ -457,8 +520,7 @@ impl Engine { panic!("Cannot register indexer for strings."); } - use crate::{engine::FN_IDX_GET, RegisterFn}; - self.register_fn(FN_IDX_GET, get_fn) + self.register_fn(crate::engine::FN_IDX_GET, get_fn) } /// Register an index getter for a custom type with the [`Engine`]. /// @@ -472,7 +534,7 @@ impl Engine { /// # Example /// /// ``` - /// use rhai::{Engine, Dynamic, EvalAltResult, RegisterFn}; + /// use rhai::{Engine, Dynamic, EvalAltResult}; /// /// #[derive(Clone)] /// struct TestStruct { @@ -524,8 +586,7 @@ impl Engine { panic!("Cannot register indexer for strings."); } - use crate::{engine::FN_IDX_GET, RegisterResultFn}; - self.register_result_fn(FN_IDX_GET, get_fn) + self.register_result_fn(crate::engine::FN_IDX_GET, get_fn) } /// Register an index setter for a custom type with the [`Engine`]. /// @@ -549,7 +610,7 @@ impl Engine { /// } /// /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// @@ -589,8 +650,7 @@ impl Engine { panic!("Cannot register indexer for strings."); } - use crate::{engine::FN_IDX_SET, RegisterFn}; - self.register_fn(FN_IDX_SET, set_fn) + self.register_fn(crate::engine::FN_IDX_SET, set_fn) } /// Register an index setter for a custom type with the [`Engine`]. /// @@ -602,7 +662,7 @@ impl Engine { /// # Example /// /// ``` - /// use rhai::{Engine, Dynamic, EvalAltResult, RegisterFn}; + /// use rhai::{Engine, Dynamic, EvalAltResult}; /// /// #[derive(Clone)] /// struct TestStruct { @@ -661,10 +721,10 @@ impl Engine { panic!("Cannot register indexer for strings."); } - use crate::{engine::FN_IDX_SET, RegisterResultFn}; - self.register_result_fn(FN_IDX_SET, move |obj: &mut T, index: X, value: U| { - set_fn(obj, index, value).map(Into::into) - }) + self.register_result_fn( + crate::engine::FN_IDX_SET, + move |obj: &mut T, index: X, value: U| set_fn(obj, index, value).map(Into::into), + ) } /// Short-hand for register both index getter and setter functions for a custom type with the [`Engine`]. /// @@ -691,7 +751,7 @@ impl Engine { /// } /// /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// diff --git a/src/engine_settings.rs b/src/engine_settings.rs index 7ba0f2cc..1bf32f1a 100644 --- a/src/engine_settings.rs +++ b/src/engine_settings.rs @@ -250,7 +250,7 @@ impl Engine { /// /// ```rust /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; + /// use rhai::Engine; /// /// let mut engine = Engine::new(); /// diff --git a/src/fn_native.rs b/src/fn_native.rs index fdb4ba9b..f4d41ae4 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -49,7 +49,7 @@ pub use crate::stdlib::cell::RefCell as Locked; pub use crate::stdlib::sync::RwLock as Locked; /// Context of a native Rust function call. -#[derive(Debug, Copy, Clone)] +#[derive(Debug)] pub struct NativeCallContext<'a> { engine: &'a Engine, fn_name: &'a str, @@ -320,7 +320,7 @@ impl FnPtr { #[inline(always)] pub fn call_dynamic( &self, - ctx: NativeCallContext, + ctx: &NativeCallContext, this_ptr: Option<&mut Dynamic>, mut arg_values: impl AsMut<[Dynamic]>, ) -> RhaiResult { diff --git a/src/fn_register.rs b/src/fn_register.rs index 38f2d272..3d43cc3a 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -4,72 +4,10 @@ use crate::dynamic::{DynamicWriteLock, Variant}; use crate::fn_native::{CallableFunction, FnAny, FnCallArgs, SendSync}; -use crate::r#unsafe::unsafe_cast_box; +use crate::r#unsafe::unsafe_try_cast; use crate::stdlib::{any::TypeId, boxed::Box, mem, string::String}; use crate::{Dynamic, Engine, FnAccess, FnNamespace, NativeCallContext, RhaiResult}; -/// Trait to register custom functions with the [`Engine`]. -pub trait RegisterFn { - /// Register a custom function with the [`Engine`]. - /// - /// # Example - /// - /// ``` - /// # fn main() -> Result<(), Box> { - /// use rhai::{Engine, RegisterFn}; - /// - /// // Normal function - /// fn add(x: i64, y: i64) -> i64 { - /// x + y - /// } - /// - /// let mut engine = Engine::new(); - /// - /// // You must use the trait rhai::RegisterFn to get this method. - /// engine.register_fn("add", add); - /// - /// assert_eq!(engine.eval::("add(40, 2)")?, 42); - /// - /// // You can also register a closure. - /// engine.register_fn("sub", |x: i64, y: i64| x - y ); - /// - /// assert_eq!(engine.eval::("sub(44, 2)")?, 42); - /// # Ok(()) - /// # } - /// ``` - fn register_fn(&mut self, name: &str, f: FN) -> &mut Self; -} - -/// Trait to register fallible custom functions returning [`Result`]`<`[`Dynamic`]`, `[`Box`]`<`[`EvalAltResult`][crate::EvalAltResult]`>>` with the [`Engine`]. -pub trait RegisterResultFn { - /// Register a custom fallible function with the [`Engine`]. - /// - /// # Example - /// - /// ``` - /// use rhai::{Engine, Dynamic, RegisterResultFn, EvalAltResult}; - /// - /// // Normal function - /// fn div(x: i64, y: i64) -> Result> { - /// if y == 0 { - /// // '.into()' automatically converts to 'Box' - /// Err("division by zero!".into()) - /// } else { - /// Ok((x / y).into()) - /// } - /// } - /// - /// let mut engine = Engine::new(); - /// - /// // You must use the trait rhai::RegisterResultFn to get this method. - /// engine.register_result_fn("div", div); - /// - /// engine.eval::("div(42, 0)") - /// .expect_err("expecting division by zero error!"); - /// ``` - fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self; -} - // 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. // That is because stable Rust currently does not allow distinguishing implementations @@ -77,7 +15,7 @@ pub trait RegisterResultFn { // // For example: // -// `RegisterFn, B, Ref), R>` +// `NativeFunction<(Mut, B, Ref), R>` // // will have the function prototype constraint to: // @@ -107,7 +45,7 @@ pub fn by_value(data: &mut Dynamic) -> T { ref_t.clone() } else if TypeId::of::() == TypeId::of::() { // If T is `String`, data must be `ImmutableString`, so map directly to it - *unsafe_cast_box(Box::new(mem::take(data).take_string().unwrap())).unwrap() + unsafe_try_cast(mem::take(data).take_string().unwrap()).unwrap() } else { // We consume the argument and then replace it with () - the argument is not supposed to be used again. // This way, we avoid having to clone the argument again, because it is already a clone when passed here. @@ -115,41 +53,10 @@ pub fn by_value(data: &mut Dynamic) -> T { } } -/// This macro creates a closure wrapping a registered function. -macro_rules! make_func { - ($fn:ident : $map:expr ; $($par:ident => $let:stmt => $convert:expr => $arg:expr),*) => { -// ^ function pointer -// ^ result mapping function -// ^ function parameter generic type name (A, B, C etc.) -// ^ argument let statement(e.g. let mut A ...) -// ^ dereferencing function -// ^ argument reference expression(like A, *B, &mut C etc) - - Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| { - // The arguments are assumed to be of the correct number and types! - - let mut _drain = args.iter_mut(); - $($let $par = ($convert)(_drain.next().unwrap()); )* - - // Call the function with each argument value - let r = $fn($($arg),*); - - // Map the result - $map(r) - }) as Box - }; -} - -/// To Dynamic mapping function. -#[inline(always)] -pub fn map_dynamic(data: impl Variant + Clone) -> RhaiResult { - Ok(data.into_dynamic()) -} - -/// To Dynamic mapping function. -#[inline(always)] -pub fn map_result(data: RhaiResult) -> RhaiResult { - data +/// Trait to register custom functions with an [`Engine`]. +pub trait RegisterNativeFunction { + /// Register the function with an [`Engine`]. + fn register_into(self, engine: &mut Engine, name: &str); } macro_rules! def_register { @@ -160,37 +67,95 @@ macro_rules! def_register { // ^ function ABI type // ^ function parameter generic type name (A, B, C etc.) // ^ call argument(like A, *B, &mut C etc) - // ^ function parameter marker type (T, Ref or Mut) + // ^ function parameter marker type (T, Ref or Mut) // ^ function parameter actual type (T, &T or &mut T) // ^ argument let statement + impl< - $($par: Variant + Clone,)* FN: Fn($($param),*) -> RET + SendSync + 'static, + $($par: Variant + Clone,)* RET: Variant + Clone - > RegisterFn for Engine - { + > RegisterNativeFunction<($($mark,)*), ()> for FN { #[inline(always)] - fn register_fn(&mut self, name: &str, f: FN) -> &mut Self { - self.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None, + fn register_into(self, engine: &mut Engine, name: &str) { + engine.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None, &[$(TypeId::of::<$par>()),*], - CallableFunction::$abi(make_func!(f : map_dynamic ; $($par => $let => $clone => $arg),*)) + CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| { + // The arguments are assumed to be of the correct number and types! + let mut _drain = args.iter_mut(); + $($let $par = ($clone)(_drain.next().unwrap()); )* + + // Call the function with each argument value + let r = self($($arg),*); + + // Map the result + Ok(r.into_dynamic()) + }) as Box) ); - self } } impl< + FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RET + SendSync + 'static, $($par: Variant + Clone,)* - FN: Fn($($param),*) -> RhaiResult + SendSync + 'static, - > RegisterResultFn for Engine - { + RET: Variant + Clone + > RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), ()> for FN { #[inline(always)] - fn register_result_fn(&mut self, name: &str, f: FN) -> &mut Self { - self.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None, + fn register_into(self, engine: &mut Engine, name: &str) { + engine.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None, &[$(TypeId::of::<$par>()),*], - CallableFunction::$abi(make_func!(f : map_result ; $($par => $let => $clone => $arg),*)) + CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { + // The arguments are assumed to be of the correct number and types! + let mut _drain = args.iter_mut(); + $($let $par = ($clone)(_drain.next().unwrap()); )* + + // Call the function with each argument value + let r = self(ctx, $($arg),*); + + // Map the result + Ok(r.into_dynamic()) + }) as Box) + ); + } + } + + impl< + FN: Fn($($param),*) -> RhaiResult + SendSync + 'static, + $($par: Variant + Clone,)* + > RegisterNativeFunction<($($mark,)*), RhaiResult> for FN { + #[inline(always)] + fn register_into(self, engine: &mut Engine, name: &str) { + engine.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None, + &[$(TypeId::of::<$par>()),*], + CallableFunction::$abi(Box::new(move |_: NativeCallContext, args: &mut FnCallArgs| { + // The arguments are assumed to be of the correct number and types! + let mut _drain = args.iter_mut(); + $($let $par = ($clone)(_drain.next().unwrap()); )* + + // Call the function with each argument value + self($($arg),*) + }) as Box) + ); + } + } + + impl< + FN: for<'a> Fn(NativeCallContext<'a>, $($param),*) -> RhaiResult + SendSync + 'static, + $($par: Variant + Clone,)* + > RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), RhaiResult> for FN { + #[inline(always)] + fn register_into(self, engine: &mut Engine, name: &str) { + engine.global_namespace.set_fn(name, FnNamespace::Global, FnAccess::Public, None, + &[$(TypeId::of::<$par>()),*], + CallableFunction::$abi(Box::new(move |ctx: NativeCallContext, args: &mut FnCallArgs| { + // The arguments are assumed to be of the correct number and types! + let mut _drain = args.iter_mut(); + $($let $par = ($clone)(_drain.next().unwrap()); )* + + // Call the function with each argument value + self(ctx, $($arg),*) + }) as Box) ); - self } } diff --git a/src/lib.rs b/src/lib.rs index 503890d5..215db356 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ //! ## The Rust part //! //! ```,no_run -//! use rhai::{Engine, EvalAltResult, RegisterFn}; +//! use rhai::{Engine, EvalAltResult}; //! //! fn main() -> Result<(), Box> //! { @@ -126,7 +126,7 @@ pub use ast::{FnAccess, AST}; pub use dynamic::Dynamic; pub use engine::{Engine, EvalContext, OP_CONTAINS, OP_EQUALS}; pub use fn_native::{FnPtr, NativeCallContext}; -pub use fn_register::{RegisterFn, RegisterResultFn}; +pub use fn_register::RegisterNativeFunction; pub use module::{FnNamespace, Module}; pub use parse_error::{LexError, ParseError, ParseErrorType}; pub use result::EvalAltResult; diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index 7e3012f9..5244c46d 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -175,12 +175,12 @@ mod array_functions { for (i, item) in array.iter().enumerate() { ar.push( mapper - .call_dynamic(ctx, None, [item.clone()]) + .call_dynamic(&ctx, None, [item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(mapper.fn_name()) => { - mapper.call_dynamic(ctx, None, [item.clone(), (i as INT).into()]) + mapper.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -207,12 +207,12 @@ mod array_functions { for (i, item) in array.iter().enumerate() { if filter - .call_dynamic(ctx, None, [item.clone()]) + .call_dynamic(&ctx, None, [item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(filter.fn_name()) => { - filter.call_dynamic(ctx, None, [item.clone(), (i as INT).into()]) + filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -303,12 +303,12 @@ mod array_functions { ) -> Result> { for (i, item) in array.iter().enumerate() { if filter - .call_dynamic(ctx, None, [item.clone()]) + .call_dynamic(&ctx, None, [item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(filter.fn_name()) => { - filter.call_dynamic(ctx, None, [item.clone(), (i as INT).into()]) + filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -337,12 +337,12 @@ mod array_functions { ) -> Result> { for (i, item) in array.iter().enumerate() { if filter - .call_dynamic(ctx, None, [item.clone()]) + .call_dynamic(&ctx, None, [item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(filter.fn_name()) => { - filter.call_dynamic(ctx, None, [item.clone(), (i as INT).into()]) + filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -371,12 +371,12 @@ mod array_functions { ) -> Result> { for (i, item) in array.iter().enumerate() { if !filter - .call_dynamic(ctx, None, [item.clone()]) + .call_dynamic(&ctx, None, [item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(filter.fn_name()) => { - filter.call_dynamic(ctx, None, [item.clone(), (i as INT).into()]) + filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -407,12 +407,12 @@ mod array_functions { for (i, item) in array.iter().enumerate() { result = reducer - .call_dynamic(ctx, None, [result.clone(), item.clone()]) + .call_dynamic(&ctx, None, [result.clone(), item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(reducer.fn_name()) => { - reducer.call_dynamic(ctx, None, [result, item.clone(), (i as INT).into()]) + reducer.call_dynamic(&ctx, None, [result, item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -435,7 +435,7 @@ mod array_functions { reducer: FnPtr, initial: FnPtr, ) -> Result> { - let mut result = initial.call_dynamic(ctx, None, []).map_err(|err| { + let mut result = initial.call_dynamic(&ctx, None, []).map_err(|err| { Box::new(EvalAltResult::ErrorInFunctionCall( "reduce".to_string(), ctx.source().unwrap_or("").to_string(), @@ -446,12 +446,12 @@ mod array_functions { for (i, item) in array.iter().enumerate() { result = reducer - .call_dynamic(ctx, None, [result.clone(), item.clone()]) + .call_dynamic(&ctx, None, [result.clone(), item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(reducer.fn_name()) => { - reducer.call_dynamic(ctx, None, [result, item.clone(), (i as INT).into()]) + reducer.call_dynamic(&ctx, None, [result, item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -477,12 +477,12 @@ mod array_functions { for (i, item) in array.iter().enumerate().rev() { result = reducer - .call_dynamic(ctx, None, [result.clone(), item.clone()]) + .call_dynamic(&ctx, None, [result.clone(), item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(reducer.fn_name()) => { - reducer.call_dynamic(ctx, None, [result, item.clone(), (i as INT).into()]) + reducer.call_dynamic(&ctx, None, [result, item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -505,7 +505,7 @@ mod array_functions { reducer: FnPtr, initial: FnPtr, ) -> Result> { - let mut result = initial.call_dynamic(ctx, None, []).map_err(|err| { + let mut result = initial.call_dynamic(&ctx, None, []).map_err(|err| { Box::new(EvalAltResult::ErrorInFunctionCall( "reduce_rev".to_string(), ctx.source().unwrap_or("").to_string(), @@ -516,12 +516,12 @@ mod array_functions { for (i, item) in array.iter().enumerate().rev() { result = reducer - .call_dynamic(ctx, None, [result.clone(), item.clone()]) + .call_dynamic(&ctx, None, [result.clone(), item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(reducer.fn_name()) => { - reducer.call_dynamic(ctx, None, [result, item.clone(), (i as INT).into()]) + reducer.call_dynamic(&ctx, None, [result, item.clone(), (i as INT).into()]) } _ => Err(err), }) @@ -545,7 +545,7 @@ mod array_functions { ) -> Result> { array.sort_by(|x, y| { comparer - .call_dynamic(ctx, None, [x.clone(), y.clone()]) + .call_dynamic(&ctx, None, [x.clone(), y.clone()]) .ok() .and_then(|v| v.as_int().ok()) .map(|v| { @@ -587,12 +587,12 @@ mod array_functions { i -= 1; if filter - .call_dynamic(ctx, None, [array[i].clone()]) + .call_dynamic(&ctx, None, [array[i].clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(filter.fn_name()) => { - filter.call_dynamic(ctx, None, [array[i].clone(), (i as INT).into()]) + filter.call_dynamic(&ctx, None, [array[i].clone(), (i as INT).into()]) } _ => Err(err), }) @@ -647,12 +647,12 @@ mod array_functions { i -= 1; if !filter - .call_dynamic(ctx, None, [array[i].clone()]) + .call_dynamic(&ctx, None, [array[i].clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.starts_with(filter.fn_name()) => { - filter.call_dynamic(ctx, None, [array[i].clone(), (i as INT).into()]) + filter.call_dynamic(&ctx, None, [array[i].clone(), (i as INT).into()]) } _ => Err(err), }) diff --git a/src/plugin.rs b/src/plugin.rs index 8aa2d8e1..d7013ef7 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -5,7 +5,7 @@ pub use crate::stdlib::{any::TypeId, boxed::Box, format, mem, string::ToString, use crate::RhaiResult; pub use crate::{ Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, Module, - NativeCallContext, Position, RegisterFn, RegisterResultFn, + NativeCallContext, Position, }; #[cfg(not(features = "no_module"))] diff --git a/tests/arrays.rs b/tests/arrays.rs index 78cf30b6..1be7f8cb 100644 --- a/tests/arrays.rs +++ b/tests/arrays.rs @@ -1,5 +1,5 @@ #![cfg(not(feature = "no_index"))] -use rhai::{Array, Engine, EvalAltResult, RegisterFn, INT}; +use rhai::{Array, Engine, EvalAltResult, INT}; #[test] fn test_arrays() -> Result<(), Box> { diff --git a/tests/call_fn.rs b/tests/call_fn.rs index f7e4fa67..dbe3ece0 100644 --- a/tests/call_fn.rs +++ b/tests/call_fn.rs @@ -1,5 +1,5 @@ #![cfg(not(feature = "no_function"))] -use rhai::{Dynamic, Engine, EvalAltResult, FnPtr, Func, FuncArgs, RegisterFn, Scope, INT}; +use rhai::{Dynamic, Engine, EvalAltResult, FnPtr, Func, FuncArgs, Scope, INT}; use std::{any::TypeId, iter::once}; #[test] @@ -131,7 +131,7 @@ fn test_fn_ptr_raw() -> Result<(), Box> { let value = args[2].clone(); let this_ptr = args.get_mut(0).unwrap(); - fp.call_dynamic(context, Some(this_ptr), [value]) + fp.call_dynamic(&context, Some(this_ptr), [value]) }, ); diff --git a/tests/closures.rs b/tests/closures.rs index 25f81c8a..ff4cc431 100644 --- a/tests/closures.rs +++ b/tests/closures.rs @@ -1,7 +1,5 @@ #![cfg(not(feature = "no_function"))] -use rhai::{ - Engine, EvalAltResult, FnPtr, NativeCallContext, ParseErrorType, RegisterFn, Scope, INT, -}; +use rhai::{Engine, EvalAltResult, FnPtr, NativeCallContext, ParseErrorType, Scope, INT}; use std::any::TypeId; use std::cell::RefCell; use std::mem::take; @@ -20,7 +18,7 @@ fn test_fn_ptr_curry_call() -> Result<(), Box> { &[TypeId::of::(), TypeId::of::()], |context, args| { let fn_ptr = std::mem::take(args[0]).cast::(); - fn_ptr.call_dynamic(context, None, [std::mem::take(args[1])]) + fn_ptr.call_dynamic(&context, None, [std::mem::take(args[1])]) }, ); @@ -159,7 +157,7 @@ fn test_closures() -> Result<(), Box> { |context, args| { let func = take(args[1]).cast::(); - func.call_dynamic(context, None, []) + func.call_dynamic(&context, None, []) }, ); @@ -343,7 +341,7 @@ fn test_closures_external() -> Result<(), Box> { let context = NativeCallContext::new(&engine, &fn_name, &lib); // Closure 'f' captures: the engine, the AST, and the curried function pointer - let f = move |x: INT| fn_ptr.call_dynamic(context, None, [x.into()]); + let f = move |x: INT| fn_ptr.call_dynamic(&context, None, [x.into()]); assert_eq!(f(42)?.take_string(), Ok("hello42".to_string())); diff --git a/tests/constants.rs b/tests/constants.rs index 05ec5ea2..b3432449 100644 --- a/tests/constants.rs +++ b/tests/constants.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, ParseErrorType, RegisterFn, Scope, INT}; +use rhai::{Engine, EvalAltResult, ParseErrorType, Scope, INT}; #[test] fn test_constant() -> Result<(), Box> { diff --git a/tests/float.rs b/tests/float.rs index 5cb23e5f..a1c05186 100644 --- a/tests/float.rs +++ b/tests/float.rs @@ -1,5 +1,5 @@ #![cfg(not(feature = "no_float"))] -use rhai::{Engine, EvalAltResult, RegisterFn, FLOAT}; +use rhai::{Engine, EvalAltResult, FLOAT}; const EPSILON: FLOAT = 0.000_000_000_1; diff --git a/tests/fn_ptr.rs b/tests/fn_ptr.rs index 9f175bd2..04d89b29 100644 --- a/tests/fn_ptr.rs +++ b/tests/fn_ptr.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, INT}; #[test] fn test_fn_ptr() -> Result<(), Box> { diff --git a/tests/functions.rs b/tests/functions.rs index f5624fbf..7f8fe26c 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -1,5 +1,5 @@ #![cfg(not(feature = "no_function"))] -use rhai::{Engine, EvalAltResult, FnNamespace, Module, ParseErrorType, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, FnNamespace, Module, ParseErrorType, INT}; #[test] fn test_functions() -> Result<(), Box> { diff --git a/tests/get_set.rs b/tests/get_set.rs index b654348c..79acc67d 100644 --- a/tests/get_set.rs +++ b/tests/get_set.rs @@ -1,6 +1,6 @@ #![cfg(not(feature = "no_object"))] -use rhai::{Engine, EvalAltResult, ImmutableString, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, ImmutableString, INT}; #[test] fn test_get_set() -> Result<(), Box> { diff --git a/tests/method_call.rs b/tests/method_call.rs index e7b863e6..a65b511a 100644 --- a/tests/method_call.rs +++ b/tests/method_call.rs @@ -1,6 +1,6 @@ #![cfg(not(feature = "no_object"))] -use rhai::{Engine, EvalAltResult, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, INT}; #[test] fn test_method_call() -> Result<(), Box> { diff --git a/tests/mismatched_op.rs b/tests/mismatched_op.rs index eea4f693..1f259484 100644 --- a/tests/mismatched_op.rs +++ b/tests/mismatched_op.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, INT}; #[test] fn test_mismatched_op() { diff --git a/tests/optimizer.rs b/tests/optimizer.rs index 7f9d2bd5..caa98dcc 100644 --- a/tests/optimizer.rs +++ b/tests/optimizer.rs @@ -1,6 +1,6 @@ #![cfg(not(feature = "no_optimize"))] -use rhai::{Engine, EvalAltResult, OptimizationLevel, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, OptimizationLevel, INT}; #[test] fn test_optimizer_run() -> Result<(), Box> { diff --git a/tests/print.rs b/tests/print.rs index d2679073..d574d5fe 100644 --- a/tests/print.rs +++ b/tests/print.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, RegisterFn, Scope, INT}; +use rhai::{Engine, EvalAltResult, Scope, INT}; use std::sync::{Arc, RwLock}; #[cfg(not(feature = "only_i32"))] diff --git a/tests/side_effects.rs b/tests/side_effects.rs index b7ba49f6..52caabd2 100644 --- a/tests/side_effects.rs +++ b/tests/side_effects.rs @@ -1,5 +1,5 @@ ///! This test simulates an external command object that is driven by a script. -use rhai::{Engine, EvalAltResult, RegisterFn, Scope, INT}; +use rhai::{Engine, EvalAltResult, Scope, INT}; use std::sync::{Arc, Mutex, RwLock}; /// Simulate a command object. diff --git a/tests/string.rs b/tests/string.rs index 2078b90c..ff787116 100644 --- a/tests/string.rs +++ b/tests/string.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, ImmutableString, RegisterFn, Scope, INT}; +use rhai::{Engine, EvalAltResult, ImmutableString, Scope, INT}; #[test] fn test_string() -> Result<(), Box> { diff --git a/tests/tokens.rs b/tests/tokens.rs index 71158313..b8343a69 100644 --- a/tests/tokens.rs +++ b/tests/tokens.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, LexError, ParseErrorType, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, LexError, ParseErrorType, INT}; #[test] fn test_tokens_disabled() { diff --git a/tests/types.rs b/tests/types.rs index 2ee51a68..87e93d51 100644 --- a/tests/types.rs +++ b/tests/types.rs @@ -1,4 +1,4 @@ -use rhai::{Engine, EvalAltResult, RegisterFn, INT}; +use rhai::{Engine, EvalAltResult, INT}; #[test] fn test_type_of() -> Result<(), Box> {