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
----------------
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

View File

@ -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

View File

@ -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()),

View File

@ -55,48 +55,52 @@ pub type Locked<T> = crate::stdlib::sync::RwLock<T>;
/// 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<ImmutableString>,
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> {

View File

@ -286,7 +286,8 @@ fn test_closures_external() -> Result<(), Box<EvalAltResult>> {
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()]);