From 8aae3ac46ccd18fad3971275005a802c0e903986 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 21 Jan 2021 21:49:25 +0800 Subject: [PATCH] Add function name to NativeCallContext. --- RELEASES.md | 4 +++- src/engine.rs | 10 +++++++--- src/fn_call.rs | 20 ++++++++++++-------- src/fn_native.rs | 42 ++++++++++++++++++++++++++---------------- tests/closures.rs | 3 ++- 5 files changed, 50 insertions(+), 29 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 4eb31b70..2fec4b9e 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -11,7 +11,8 @@ Rust compiler minimum version is raised to 1.49. Breaking changes ---------------- -Rust compiler requirement raised to 1.49. +* Rust compiler requirement raised to 1.49. +* `NativeCallContext::new` taker an additional parameter containing the name of the function called. Bug fixes --------- @@ -28,6 +29,7 @@ Enhancements * `ahash` is used to hash function call parameters. This should yield speed improvements. * `Dynamic` and `ImmutableString` now implement `serde::Serialize` and `serde::Deserialize`. +* `NativeCallContext` has a new field containing the name of the function called, useful when the same Rust function is registered under multiple names in Rhai. Version 0.19.10 diff --git a/src/engine.rs b/src/engine.rs index c6dce576..150a8eb5 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1971,12 +1971,16 @@ impl Engine { let args = &mut [lhs_ptr_inner, &mut rhs_val]; // Overriding exact implementation - let source = source.or_else(|| state.source.as_ref()); + let source = + source.or_else(|| state.source.as_ref()).map(|s| s.as_str()); if func.is_plugin_fn() { func.get_plugin_fn() - .call((self, source, &*mods, lib).into(), args)?; + .call((self, op.as_ref(), source, &*mods, lib).into(), args)?; } else { - func.get_native_fn()((self, source, &*mods, lib).into(), args)?; + func.get_native_fn()( + (self, op.as_ref(), source, &*mods, lib).into(), + args, + )?; } } // Built-in op-assignment function diff --git a/src/fn_call.rs b/src/fn_call.rs index 5ee9387f..929eb825 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -211,12 +211,13 @@ impl Engine { state.source.as_ref() } else { source.as_ref() - }; + } + .map(|s| s.as_str()); let result = if func.is_plugin_fn() { func.get_plugin_fn() - .call((self, source, mods, lib).into(), args) + .call((self, fn_name, source, mods, lib).into(), args) } else { - func.get_native_fn()((self, source, mods, lib).into(), args) + func.get_native_fn()((self, fn_name, source, mods, lib).into(), args) }; // Restore the original reference @@ -1236,10 +1237,10 @@ impl Engine { result } - Some(f) if f.is_plugin_fn() => f - .get_plugin_fn() - .clone() - .call((self, module.id_raw(), &*mods, lib).into(), args.as_mut()), + Some(f) if f.is_plugin_fn() => f.get_plugin_fn().clone().call( + (self, fn_name, module.id(), &*mods, lib).into(), + args.as_mut(), + ), Some(f) if f.is_native() => { if !f.is_method() { // Clone first argument @@ -1250,7 +1251,10 @@ impl Engine { } } - f.get_native_fn()((self, module.id_raw(), &*mods, lib).into(), args.as_mut()) + f.get_native_fn()( + (self, fn_name, module.id(), &*mods, lib).into(), + args.as_mut(), + ) } Some(f) => unreachable!("unknown function type: {:?}", f), None if def_val.is_some() => Ok(def_val.unwrap().clone()), diff --git a/src/fn_native.rs b/src/fn_native.rs index 6144ac5e..6372c3c7 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -55,48 +55,52 @@ pub type Locked = crate::stdlib::sync::RwLock; /// Context of a native Rust function call. #[derive(Debug, Copy, Clone)] -pub struct NativeCallContext<'e, 's, 'a, 'm, 'pm: 'm> { +pub struct NativeCallContext<'e, 'n, 's, 'a, 'm, 'pm: 'm> { engine: &'e Engine, + fn_name: &'n str, source: Option<&'s str>, pub(crate) mods: Option<&'a Imports>, pub(crate) lib: &'m [&'pm Module], } -impl<'e, 's, 'a, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized> - From<(&'e Engine, Option<&'s ImmutableString>, &'a Imports, &'m M)> - for NativeCallContext<'e, 's, 'a, 'm, 'pm> +impl<'e, 'n, 's, 'a, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized> + From<(&'e Engine, &'n str, Option<&'s str>, &'a Imports, &'m M)> + for NativeCallContext<'e, 'n, 's, 'a, 'm, 'pm> { #[inline(always)] - fn from(value: (&'e Engine, Option<&'s ImmutableString>, &'a Imports, &'m M)) -> Self { + fn from(value: (&'e Engine, &'n str, Option<&'s str>, &'a Imports, &'m M)) -> Self { Self { engine: value.0, - source: value.1.map(|s| s.as_str()), - mods: Some(value.2), - lib: value.3.as_ref(), + fn_name: value.1, + source: value.2, + mods: Some(value.3), + lib: value.4.as_ref(), } } } -impl<'e, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized> From<(&'e Engine, &'m M)> - for NativeCallContext<'e, '_, '_, 'm, 'pm> +impl<'e, 'n, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized> From<(&'e Engine, &'n str, &'m M)> + for NativeCallContext<'e, 'n, '_, '_, 'm, 'pm> { #[inline(always)] - fn from(value: (&'e Engine, &'m M)) -> Self { + fn from(value: (&'e Engine, &'n str, &'m M)) -> Self { Self { engine: value.0, + fn_name: value.1, source: None, mods: None, - lib: value.1.as_ref(), + lib: value.2.as_ref(), } } } -impl<'e, 's, 'a, 'm, 'pm> NativeCallContext<'e, 's, 'a, 'm, 'pm> { +impl<'e, 'n, 's, 'a, 'm, 'pm> NativeCallContext<'e, 'n, 's, 'a, 'm, 'pm> { /// Create a new [`NativeCallContext`]. #[inline(always)] - pub fn new(engine: &'e Engine, lib: &'m impl AsRef<[&'pm Module]>) -> Self { + pub fn new(engine: &'e Engine, fn_name: &'n str, lib: &'m impl AsRef<[&'pm Module]>) -> Self { Self { engine, + fn_name, source: None, mods: None, lib: lib.as_ref(), @@ -109,13 +113,14 @@ impl<'e, 's, 'a, 'm, 'pm> NativeCallContext<'e, 's, 'a, 'm, 'pm> { #[inline(always)] pub fn new_with_all_fields( engine: &'e Engine, - source: &'s Option, + fn_name: &'n str, + source: &'s Option<&str>, imports: &'a mut Imports, lib: &'m impl AsRef<[&'pm Module]>, ) -> Self { Self { engine, - source: source.as_ref().map(|s| s.as_str()), + source: source.clone(), mods: Some(imports), lib: lib.as_ref(), } @@ -125,6 +130,11 @@ impl<'e, 's, 'a, 'm, 'pm> NativeCallContext<'e, 's, 'a, 'm, 'pm> { pub fn engine(&self) -> &Engine { self.engine } + /// Name of the function called. + #[inline(always)] + pub fn fn_name(&self) -> &str { + self.fn_name + } /// The current source. #[inline(always)] pub fn source(&self) -> Option<&str> { diff --git a/tests/closures.rs b/tests/closures.rs index 4a0cd74b..3f9fcfa2 100644 --- a/tests/closures.rs +++ b/tests/closures.rs @@ -286,7 +286,8 @@ fn test_closures_external() -> Result<(), Box> { let lib = [ast.as_ref()]; // Create native call context - let context = NativeCallContext::new(&engine, &lib); + let fn_name = fn_ptr.fn_name().to_string(); + 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()]);