From 0a69caaf6d25984e16ad72823857e4c94220eed7 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Fri, 1 Jan 2021 17:05:06 +0800 Subject: [PATCH] Refine API for contexts. --- doc/src/engine/custom-syntax.md | 26 ++++++++++++++------------ doc/src/engine/var.md | 26 ++++++++++++++------------ doc/src/language/fn-ptr.md | 14 ++++++++------ doc/src/plugins/function.md | 14 ++++++++------ doc/src/plugins/module.md | 14 ++++++++------ doc/src/rust/register-raw.md | 20 +++++++++++--------- src/engine.rs | 29 ++++++++++++++++++++--------- src/fn_native.rs | 21 +++++++++++++++++---- 8 files changed, 100 insertions(+), 64 deletions(-) diff --git a/doc/src/engine/custom-syntax.md b/doc/src/engine/custom-syntax.md index 97747072..5c27142a 100644 --- a/doc/src/engine/custom-syntax.md +++ b/doc/src/engine/custom-syntax.md @@ -116,18 +116,20 @@ The function signature of an implementation is: where: -| Parameter | Type | Description | -| -------------------------- | :-----------------------------: | ------------------------------------------------------------------------------------- | -| `context` | `&mut EvalContext` | mutable reference to the current evaluation _context_ | -| • `scope()` | `&Scope` | reference to the current [`Scope`] | -| • `scope_mut()` | `&mut Scope` | mutable reference to the current [`Scope`]; variables can be added to/removed from it | -| • `engine()` | `&Engine` | reference to the current [`Engine`] | -| • `source()` | `Option<&str>` | reference to the current source, if any | -| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements | -| • `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | -| • `this_ptr()` | `Option<&Dynamic>` | reference to the current bound [`this`] pointer, if any | -| • `call_level()` | `usize` | the current nesting level of function calls | -| `inputs` | `&[Expression]` | a list of input expression trees | +| Parameter | Type | Description | +| -------------------------- | :-------------------------------------: | ---------------------------------------------------------------------------------------------------------------------- | +| `context` | `&mut EvalContext` | mutable reference to the current evaluation _context_ | +| • `scope()` | `&Scope` | reference to the current [`Scope`] | +| • `scope_mut()` | `&mut &mut Scope` | mutable reference to the current [`Scope`]; variables can be added to/removed from it | +| • `engine()` | `&Engine` | reference to the current [`Engine`] | +| • `source()` | `Option<&str>` | reference to the current source, if any | +| • `iter_imports()` | `impl Iterator` | iterator of the current stack of [modules] imported via `import` statements | +| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature | +| • `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| • `namespaces()` | `&[&Module]` | reference to the namespaces (as [modules]) containing all script-defined functions; requires the [`internals`] feature | +| • `this_ptr()` | `Option<&Dynamic>` | reference to the current bound [`this`] pointer, if any | +| • `call_level()` | `usize` | the current nesting level of function calls | +| `inputs` | `&[Expression]` | a list of input expression trees | ### Return Value diff --git a/doc/src/engine/var.md b/doc/src/engine/var.md index 5fe79881..c0fb5579 100644 --- a/doc/src/engine/var.md +++ b/doc/src/engine/var.md @@ -67,18 +67,20 @@ The function signature passed to `Engine::on_var` takes the following form: where: -| Parameter | Type | Description | -| -------------------------- | :-----------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `name` | `&str` | variable name | -| `index` | `usize` | an offset from the bottom of the current [`Scope`] that the variable is supposed to reside.
Offsets start from 1, with 1 meaning the last variable in the current [`Scope`]. Essentially the correct variable is at position `scope.len() - index`.
If `index` is zero, then there is no pre-calculated offset position and a search through the current [`Scope`] must be performed. | -| `context` | `&EvalContext` | reference to the current evaluation _context_ | -| • `scope()` | `&Scope` | reference to the current [`Scope`] | -| • `engine()` | `&Engine` | reference to the current [`Engine`] | -| • `source()` | `Option<&str>` | reference to the current source, if any | -| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements | -| • `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | -| • `this_ptr()` | `Option<&Dynamic>` | reference to the current bound [`this`] pointer, if any | -| • `call_level()` | `usize` | the current nesting level of function calls | +| Parameter | Type | Description | +| -------------------------- | :-------------------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | `&str` | variable name | +| `index` | `usize` | an offset from the bottom of the current [`Scope`] that the variable is supposed to reside.
Offsets start from 1, with 1 meaning the last variable in the current [`Scope`]. Essentially the correct variable is at position `scope.len() - index`.
If `index` is zero, then there is no pre-calculated offset position and a search through the current [`Scope`] must be performed. | +| `context` | `&EvalContext` | reference to the current evaluation _context_ | +| • `scope()` | `&Scope` | reference to the current [`Scope`] | +| • `engine()` | `&Engine` | reference to the current [`Engine`] | +| • `source()` | `Option<&str>` | reference to the current source, if any | +| • `iter_imports()` | `impl Iterator` | iterator of the current stack of [modules] imported via `import` statements | +| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature | +| • `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| • `namespaces()` | `&[&Module]` | reference to the namespaces (as [modules]) containing all script-defined functions; requires the [`internals`] feature | +| • `this_ptr()` | `Option<&Dynamic>` | reference to the current bound [`this`] pointer, if any | +| • `call_level()` | `usize` | the current nesting level of function calls | ### Return Value diff --git a/doc/src/language/fn-ptr.md b/doc/src/language/fn-ptr.md index 16c37e08..4717504a 100644 --- a/doc/src/language/fn-ptr.md +++ b/doc/src/language/fn-ptr.md @@ -225,12 +225,14 @@ engine.register_raw_fn("super_call", `FnPtr::call_dynamic` takes a parameter of type `NativeCallContext` which holds the _native call context_ of the particular call to a registered Rust function. It is a type that exposes the following: -| Field | Type | Description | -| ------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. | -| `source()` | `Option<&str>` | reference to the current source, if any | -| `imports()` | `Option<&Imports>` | reference to the current stack of [modules] imported via `import` statements (if any) | -| `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| Field | Type | Description | +| ------------------- | :-------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. | +| `source()` | `Option<&str>` | reference to the current source, if any | +| `iter_imports()` | `impl Iterator` | iterator of the current stack of [modules] imported via `import` statements | +| `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature | +| `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| `namespaces()` | `&[&Module]` | reference to the namespaces (as [modules]) containing all script-defined functions; requires the [`internals`] feature | This type is normally provided by the [`Engine`] (e.g. when using [`Engine::register_fn_raw`](../rust/register-raw.md)). diff --git a/doc/src/plugins/function.md b/doc/src/plugins/function.md index fad53a03..8f7b3f46 100644 --- a/doc/src/plugins/function.md +++ b/doc/src/plugins/function.md @@ -86,12 +86,14 @@ specially by the plugins system. `NativeCallContext` is a type that encapsulates the current _native call context_ and exposes the following: -| Field | Type | Description | -| ------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. | -| `source()` | `Option<&str>` | reference to the current source, if any | -| `imports()` | `Option<&Imports>` | reference to the current stack of [modules] imported via `import` statements (if any) | -| `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| Field | Type | Description | +| ------------------- | :-------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. | +| `source()` | `Option<&str>` | reference to the current source, if any | +| `iter_imports()` | `impl Iterator` | iterator of the current stack of [modules] imported via `import` statements | +| `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature | +| `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| `namespaces()` | `&[&Module]` | reference to the namespaces (as [modules]) containing all script-defined functions; requires the [`internals`] feature | This first parameter, if exists, will be stripped before all other processing. It is _virtual_. Most importantly, it does _not_ count as a parameter to the function and there is no need to provide diff --git a/doc/src/plugins/module.md b/doc/src/plugins/module.md index d8ebbd41..c147809f 100644 --- a/doc/src/plugins/module.md +++ b/doc/src/plugins/module.md @@ -399,12 +399,14 @@ specially by the plugins system. `NativeCallContext` is a type that encapsulates the current _native call context_ and exposes the following: -| Field | Type | Description | -| ------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. | -| `source()` | `Option<&str>` | reference to the current source, if any | -| `imports()` | `Option<&Imports>` | reference to the current stack of [modules] imported via `import` statements (if any) | -| `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| Field | Type | Description | +| ------------------- | :-------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. | +| `source()` | `Option<&str>` | reference to the current source, if any | +| `iter_imports()` | `impl Iterator` | iterator of the current stack of [modules] imported via `import` statements | +| `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature | +| `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| `namespaces()` | `&[&Module]` | reference to the namespaces (as [modules]) containing all script-defined functions; requires the [`internals`] feature | This first parameter, if exists, will be stripped before all other processing. It is _virtual_. Most importantly, it does _not_ count as a parameter to the function and there is no need to provide diff --git a/doc/src/rust/register-raw.md b/doc/src/rust/register-raw.md index c2b094e7..7b7566f7 100644 --- a/doc/src/rust/register-raw.md +++ b/doc/src/rust/register-raw.md @@ -65,15 +65,17 @@ The function signature passed to `Engine::register_raw_fn` takes the following f where: -| Parameter | Type | Description | -| -------------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `T` | `impl Clone` | return type of the function | -| `context` | `NativeCallContext` | the current _native call context_ | -| • `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. | -| • `source()` | `Option<&str>` | reference to the current source, if any | -| • `imports()` | `Option<&Imports>` | reference to the current stack of [modules] imported via `import` statements (if any) | -| • `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | -| `args` | `&mut [&mut Dynamic]` | a slice containing `&mut` references to [`Dynamic`] values.
The slice is guaranteed to contain enough arguments _of the correct types_. | +| Parameter | Type | Description | +| -------------------------- | :-------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `T` | `impl Clone` | return type of the function | +| `context` | `NativeCallContext` | the current _native call context_ | +| • `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer]. | +| • `source()` | `Option<&str>` | reference to the current source, if any | +| • `iter_imports()` | `impl Iterator` | iterator of the current stack of [modules] imported via `import` statements | +| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature | +| • `iter_namespaces()` | `impl Iterator` | iterator of the namespaces (as [modules]) containing all script-defined functions | +| • `namespaces()` | `&[&Module]` | reference to the namespaces (as [modules]) containing all script-defined functions; requires the [`internals`] feature | +| `args` | `&mut [&mut Dynamic]` | a slice containing `&mut` references to [`Dynamic`] values.
The slice is guaranteed to contain enough arguments _of the correct types_. | ### Return value diff --git a/src/engine.rs b/src/engine.rs index 073b4daf..8795c706 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -96,7 +96,7 @@ impl Imports { /// Get an iterator to this stack of imported [modules][Module] in reverse order. #[allow(dead_code)] #[inline(always)] - pub fn iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn iter(&self) -> impl Iterator { self.0 .iter() .rev() @@ -105,9 +105,7 @@ impl Imports { /// Get an iterator to this stack of imported [modules][Module] in reverse order. #[allow(dead_code)] #[inline(always)] - pub(crate) fn iter_raw<'a>( - &'a self, - ) -> impl Iterator)> + 'a { + pub(crate) fn iter_raw(&self) -> impl Iterator)> { self.0.iter().rev().map(|(n, m)| (n, m)) } /// Get a consuming iterator to this stack of imported [modules][Module] in reverse order. @@ -575,17 +573,17 @@ pub struct EvalContext<'e, 'x, 'px: 'x, 'a, 's, 'm, 'pm: 'm, 't, 'pt: 't> { impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> { /// The current [`Engine`]. #[inline(always)] - pub fn engine(&self) -> &'e Engine { + pub fn engine(&self) -> &Engine { self.engine } /// The current source. #[inline(always)] - pub fn source<'z: 's>(&'z self) -> Option<&'s str> { + pub fn source(&self) -> Option<&str> { self.state.source.as_ref().map(|s| s.as_str()) } /// The current [`Scope`]. #[inline(always)] - pub fn scope(&self) -> &Scope<'px> { + pub fn scope(&self) -> &Scope { self.scope } /// Mutable reference to the current [`Scope`]. @@ -593,19 +591,32 @@ impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, pub fn scope_mut(&mut self) -> &mut &'x mut Scope<'px> { &mut self.scope } + /// Get an iterator over the current set of modules imported via `import` statements. + #[cfg(not(feature = "no_module"))] + #[inline(always)] + pub fn iter_imports(&self) -> impl Iterator { + self.mods.iter() + } /// _(INTERNALS)_ The current set of modules imported via `import` statements. /// Available under the `internals` feature only. #[cfg(feature = "internals")] #[cfg(not(feature = "no_module"))] #[inline(always)] - pub fn imports(&'a self) -> &'a Imports { + pub fn imports(&self) -> &Imports { self.mods } /// Get an iterator over the namespaces containing definition of all script-defined functions. #[inline(always)] - pub fn iter_namespaces(&self) -> impl Iterator + 'm { + pub fn iter_namespaces(&self) -> impl Iterator { self.lib.iter().cloned() } + /// _(INTERNALS)_ The current set of namespaces containing definitions of all script-defined functions. + /// Available under the `internals` feature only. + #[cfg(feature = "internals")] + #[inline(always)] + pub fn namespaces(&self) -> &[&Module] { + self.lib + } /// The current bound `this` pointer, if any. #[inline(always)] pub fn this_ptr(&self) -> Option<&Dynamic> { diff --git a/src/fn_native.rs b/src/fn_native.rs index 6ca51e43..949b1071 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -121,14 +121,20 @@ impl<'e, 's, 'a, 'm, 'pm> NativeCallContext<'e, 's, 'a, 'm, 'pm> { } /// The current [`Engine`]. #[inline(always)] - pub fn engine(&self) -> &'e Engine { + pub fn engine(&self) -> &Engine { self.engine } /// The current source. #[inline(always)] - pub fn source<'z: 's>(&'z self) -> Option<&'s str> { + pub fn source(&self) -> Option<&str> { self.source } + /// Get an iterator over the current set of modules imported via `import` statements. + #[cfg(not(feature = "no_module"))] + #[inline(always)] + pub fn iter_imports(&self) -> impl Iterator { + self.mods.iter().flat_map(|m| m.iter()) + } /// _(INTERNALS)_ The current set of modules imported via `import` statements. /// Available under the `internals` feature only. #[cfg(feature = "internals")] @@ -137,11 +143,18 @@ impl<'e, 's, 'a, 'm, 'pm> NativeCallContext<'e, 's, 'a, 'm, 'pm> { pub fn imports(&self) -> Option<&Imports> { self.mods } - /// Get an iterator over the namespaces containing definition of all script-defined functions. + /// Get an iterator over the namespaces containing definitions of all script-defined functions. #[inline(always)] - pub fn iter_namespaces(&self) -> impl Iterator + 'm { + pub fn iter_namespaces(&self) -> impl Iterator { self.lib.iter().cloned() } + /// _(INTERNALS)_ The current set of namespaces containing definitions of all script-defined functions. + /// Available under the `internals` feature only. + #[cfg(feature = "internals")] + #[inline(always)] + pub fn namespaces(&self) -> &[&Module] { + self.lib + } /// Call a function inside the call context. /// /// ## WARNING