Add function name to NativeCallContext.

This commit is contained in:
Stephen Chung 2021-01-21 21:49:25 +08:00
parent f6553c1426
commit 8aae3ac46c
5 changed files with 50 additions and 29 deletions

View File

@ -11,7 +11,8 @@ Rust compiler minimum version is raised to 1.49.
Breaking changes 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 Bug fixes
--------- ---------
@ -28,6 +29,7 @@ Enhancements
* `ahash` is used to hash function call parameters. This should yield speed improvements. * `ahash` is used to hash function call parameters. This should yield speed improvements.
* `Dynamic` and `ImmutableString` now implement `serde::Serialize` and `serde::Deserialize`. * `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 Version 0.19.10

View File

@ -1971,12 +1971,16 @@ impl Engine {
let args = &mut [lhs_ptr_inner, &mut rhs_val]; let args = &mut [lhs_ptr_inner, &mut rhs_val];
// Overriding exact implementation // 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() { if func.is_plugin_fn() {
func.get_plugin_fn() func.get_plugin_fn()
.call((self, source, &*mods, lib).into(), args)?; .call((self, op.as_ref(), source, &*mods, lib).into(), args)?;
} else { } 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 // Built-in op-assignment function

View File

@ -211,12 +211,13 @@ impl Engine {
state.source.as_ref() state.source.as_ref()
} else { } else {
source.as_ref() source.as_ref()
}; }
.map(|s| s.as_str());
let result = if func.is_plugin_fn() { let result = if func.is_plugin_fn() {
func.get_plugin_fn() func.get_plugin_fn()
.call((self, source, mods, lib).into(), args) .call((self, fn_name, source, mods, lib).into(), args)
} else { } 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 // Restore the original reference
@ -1236,10 +1237,10 @@ impl Engine {
result result
} }
Some(f) if f.is_plugin_fn() => f Some(f) if f.is_plugin_fn() => f.get_plugin_fn().clone().call(
.get_plugin_fn() (self, fn_name, module.id(), &*mods, lib).into(),
.clone() args.as_mut(),
.call((self, module.id_raw(), &*mods, lib).into(), args.as_mut()), ),
Some(f) if f.is_native() => { Some(f) if f.is_native() => {
if !f.is_method() { if !f.is_method() {
// Clone first argument // 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), Some(f) => unreachable!("unknown function type: {:?}", f),
None if def_val.is_some() => Ok(def_val.unwrap().clone()), None if def_val.is_some() => Ok(def_val.unwrap().clone()),

View File

@ -55,48 +55,52 @@ pub type Locked<T> = crate::stdlib::sync::RwLock<T>;
/// Context of a native Rust function call. /// Context of a native Rust function call.
#[derive(Debug, Copy, Clone)] #[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, engine: &'e Engine,
fn_name: &'n str,
source: Option<&'s str>, source: Option<&'s str>,
pub(crate) mods: Option<&'a Imports>, pub(crate) mods: Option<&'a Imports>,
pub(crate) lib: &'m [&'pm Module], pub(crate) lib: &'m [&'pm Module],
} }
impl<'e, 's, 'a, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized> impl<'e, 'n, 's, 'a, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized>
From<(&'e Engine, Option<&'s ImmutableString>, &'a Imports, &'m M)> From<(&'e Engine, &'n str, Option<&'s str>, &'a Imports, &'m M)>
for NativeCallContext<'e, 's, 'a, 'm, 'pm> for NativeCallContext<'e, 'n, 's, 'a, 'm, 'pm>
{ {
#[inline(always)] #[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 { Self {
engine: value.0, engine: value.0,
source: value.1.map(|s| s.as_str()), fn_name: value.1,
mods: Some(value.2), source: value.2,
lib: value.3.as_ref(), mods: Some(value.3),
lib: value.4.as_ref(),
} }
} }
} }
impl<'e, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized> From<(&'e Engine, &'m M)> impl<'e, 'n, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized> From<(&'e Engine, &'n str, &'m M)>
for NativeCallContext<'e, '_, '_, 'm, 'pm> for NativeCallContext<'e, 'n, '_, '_, 'm, 'pm>
{ {
#[inline(always)] #[inline(always)]
fn from(value: (&'e Engine, &'m M)) -> Self { fn from(value: (&'e Engine, &'n str, &'m M)) -> Self {
Self { Self {
engine: value.0, engine: value.0,
fn_name: value.1,
source: None, source: None,
mods: 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`]. /// Create a new [`NativeCallContext`].
#[inline(always)] #[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 { Self {
engine, engine,
fn_name,
source: None, source: None,
mods: None, mods: None,
lib: lib.as_ref(), lib: lib.as_ref(),
@ -109,13 +113,14 @@ impl<'e, 's, 'a, 'm, 'pm> NativeCallContext<'e, 's, 'a, 'm, 'pm> {
#[inline(always)] #[inline(always)]
pub fn new_with_all_fields( pub fn new_with_all_fields(
engine: &'e Engine, engine: &'e Engine,
source: &'s Option<ImmutableString>, fn_name: &'n str,
source: &'s Option<&str>,
imports: &'a mut Imports, imports: &'a mut Imports,
lib: &'m impl AsRef<[&'pm Module]>, lib: &'m impl AsRef<[&'pm Module]>,
) -> Self { ) -> Self {
Self { Self {
engine, engine,
source: source.as_ref().map(|s| s.as_str()), source: source.clone(),
mods: Some(imports), mods: Some(imports),
lib: lib.as_ref(), 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 { pub fn engine(&self) -> &Engine {
self.engine self.engine
} }
/// Name of the function called.
#[inline(always)]
pub fn fn_name(&self) -> &str {
self.fn_name
}
/// The current source. /// The current source.
#[inline(always)] #[inline(always)]
pub fn source(&self) -> Option<&str> { pub fn source(&self) -> Option<&str> {

View File

@ -286,7 +286,8 @@ fn test_closures_external() -> Result<(), Box<EvalAltResult>> {
let lib = [ast.as_ref()]; let lib = [ast.as_ref()];
// Create native call context // 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 // 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()]);