diff --git a/src/fn_native.rs b/src/fn_native.rs index 303c6278..5c3b86a4 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -1,11 +1,12 @@ //! Module containing interfaces with native-Rust functions. use crate::any::Dynamic; use crate::engine::Engine; -use crate::module::Module; +use crate::module::{Module, FuncReturn}; use crate::parser::ScriptFnDef; use crate::result::EvalAltResult; use crate::token::{is_valid_identifier, Position}; use crate::utils::ImmutableString; +use crate::Scope; use crate::stdlib::{boxed::Box, convert::TryFrom, fmt, rc::Rc, string::String, sync::Arc}; @@ -74,6 +75,31 @@ impl FnPtr { pub(crate) fn curry(&self) -> &[Dynamic] { &self.1 } + + /// A shortcut of `Engine::call_fn_dynamic` function that takes into + /// consideration curry-ed and passed arguments both. + pub fn call_dynamic( + &self, + engine: &Engine, + lib: impl AsRef, + mut this_ptr: Option<&mut Dynamic>, + mut arg_values: impl AsMut<[Dynamic]> + ) -> FuncReturn { + let mut args: Vec = self + .1 + .iter() + .chain(arg_values.as_mut().iter()) + .cloned() + .collect(); + + engine.call_fn_dynamic( + &mut Scope::new(), + lib, + &self.0.as_ref(), + this_ptr, + args + ) + } } impl fmt::Display for FnPtr { diff --git a/tests/call_fn.rs b/tests/call_fn.rs index 97767df7..105789b3 100644 --- a/tests/call_fn.rs +++ b/tests/call_fn.rs @@ -2,6 +2,8 @@ use rhai::{ Dynamic, Engine, EvalAltResult, FnPtr, Func, Module, ParseError, ParseErrorType, Scope, INT, }; +use std::any::TypeId; +use std::rc::Rc; #[test] fn test_fn() -> Result<(), Box> { @@ -157,3 +159,35 @@ fn test_fn_ptr_raw() -> Result<(), Box> { Ok(()) } + +#[test] +fn test_currying_with_registered_fn() -> Result<(), Box> { + let mut module = Module::new(); + + module.set_raw_fn( + "call_with_arg", + &[TypeId::of::(), TypeId::of::()], + |engine: &Engine, module: &Module, args: &mut [&mut Dynamic]| { + std::mem::take(args[0]) + .cast::() + .call_dynamic(engine, module, None, [std::mem::take(args[1])]) + }, + ); + + let mut engine = Engine::new(); + engine.load_package(Rc::new(module)); + + assert_eq!( + engine.eval::( + r#" + let addition = |x, y| { x + y }; + let curryed = addition.curry(100); + + call_with_arg(curryed, 5) + "# + )?, + 105 + ); + + Ok(()) +}