commit
1642232350
@ -6,7 +6,7 @@ members = [
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "rhai"
|
name = "rhai"
|
||||||
version = "0.19.9"
|
version = "0.19.10"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"]
|
authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"]
|
||||||
description = "Embedded scripting for Rust"
|
description = "Embedded scripting for Rust"
|
||||||
|
15
RELEASES.md
15
RELEASES.md
@ -1,6 +1,21 @@
|
|||||||
Rhai Release Notes
|
Rhai Release Notes
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
Version 0.19.10
|
||||||
|
===============
|
||||||
|
|
||||||
|
Breaking changes
|
||||||
|
----------------
|
||||||
|
|
||||||
|
* The error variant `EvalAltResult::ErrorInFunctionCall` has a new parameter holding the _source_ of the function.
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Source information is provided when there is an error within a call to a function defined in another module.
|
||||||
|
* Source information is provided to the `NativeCallContext` for native Rust functions.
|
||||||
|
|
||||||
|
|
||||||
Version 0.19.9
|
Version 0.19.9
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "0.19.9",
|
"version": "0.19.10",
|
||||||
"repoHome": "https://github.com/jonathandturner/rhai/blob/master",
|
"repoHome": "https://github.com/jonathandturner/rhai/blob/master",
|
||||||
"repoTree": "https://github.com/jonathandturner/rhai/tree/master",
|
"repoTree": "https://github.com/jonathandturner/rhai/tree/master",
|
||||||
"rootUrl": "",
|
"rootUrl": "",
|
||||||
|
@ -116,18 +116,20 @@ The function signature of an implementation is:
|
|||||||
|
|
||||||
where:
|
where:
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| -------------------------- | :-----------------------------: | ------------------------------------------------------------------------------------- |
|
| -------------------------- | :-------------------------------------: | ---------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `context` | `&mut EvalContext` | mutable reference to the current evaluation _context_ |
|
| `context` | `&mut EvalContext` | mutable reference to the current evaluation _context_ |
|
||||||
| • `scope()` | `&Scope` | reference to the current [`Scope`] |
|
| • `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 |
|
| • `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`] |
|
| • `engine()` | `&Engine` | reference to the current [`Engine`] |
|
||||||
| • `source()` | `Option<&str>` | reference to the current source, if any |
|
| • `source()` | `Option<&str>` | reference to the current source, if any |
|
||||||
| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements |
|
| • `iter_imports()` | `impl Iterator<Item = (&str, &Module)>` | iterator of the current stack of [modules] imported via `import` statements |
|
||||||
| • `iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature |
|
||||||
| • `this_ptr()` | `Option<&Dynamic>` | reference to the current bound [`this`] pointer, if any |
|
| • `iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
||||||
| • `call_level()` | `usize` | the current nesting level of function calls |
|
| • `namespaces()` | `&[&Module]` | reference to the namespaces (as [modules]) containing all script-defined functions; requires the [`internals`] feature |
|
||||||
| `inputs` | `&[Expression]` | a list of input expression trees |
|
| • `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
|
### Return Value
|
||||||
|
|
||||||
|
@ -67,18 +67,20 @@ The function signature passed to `Engine::on_var` takes the following form:
|
|||||||
|
|
||||||
where:
|
where:
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| -------------------------- | :-----------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| -------------------------- | :-------------------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `name` | `&str` | variable name |
|
| `name` | `&str` | variable name |
|
||||||
| `index` | `usize` | an offset from the bottom of the current [`Scope`] that the variable is supposed to reside.<br/>Offsets start from 1, with 1 meaning the last variable in the current [`Scope`]. Essentially the correct variable is at position `scope.len() - index`.<br/>If `index` is zero, then there is no pre-calculated offset position and a search through the current [`Scope`] must be performed. |
|
| `index` | `usize` | an offset from the bottom of the current [`Scope`] that the variable is supposed to reside.<br/>Offsets start from 1, with 1 meaning the last variable in the current [`Scope`]. Essentially the correct variable is at position `scope.len() - index`.<br/>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_ |
|
| `context` | `&EvalContext` | reference to the current evaluation _context_ |
|
||||||
| • `scope()` | `&Scope` | reference to the current [`Scope`] |
|
| • `scope()` | `&Scope` | reference to the current [`Scope`] |
|
||||||
| • `engine()` | `&Engine` | reference to the current [`Engine`] |
|
| • `engine()` | `&Engine` | reference to the current [`Engine`] |
|
||||||
| • `source()` | `Option<&str>` | reference to the current source, if any |
|
| • `source()` | `Option<&str>` | reference to the current source, if any |
|
||||||
| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements |
|
| • `iter_imports()` | `impl Iterator<Item = (&str, &Module)>` | iterator of the current stack of [modules] imported via `import` statements |
|
||||||
| • `iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature |
|
||||||
| • `this_ptr()` | `Option<&Dynamic>` | reference to the current bound [`this`] pointer, if any |
|
| • `iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
||||||
| • `call_level()` | `usize` | the current nesting level of function calls |
|
| • `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
|
### Return Value
|
||||||
|
|
||||||
|
@ -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_
|
`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:
|
of the particular call to a registered Rust function. It is a type that exposes the following:
|
||||||
|
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
| ------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| ------------------- | :-------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>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]. |
|
| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>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 |
|
| `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_imports()` | `impl Iterator<Item = (&str, &Module)>` | iterator of the current stack of [modules] imported via `import` statements |
|
||||||
| `iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
| `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature |
|
||||||
|
| `iter_namespaces()` | `impl Iterator<Item = &Module>` | 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)).
|
This type is normally provided by the [`Engine`] (e.g. when using [`Engine::register_fn_raw`](../rust/register-raw.md)).
|
||||||
|
@ -149,14 +149,18 @@ change(); // <- error: `this` is unbound
|
|||||||
`is_def_fn`
|
`is_def_fn`
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
Use `is_def_fn` to detect if a Rhai function is defined (and therefore callable), based on its name
|
Use `is_def_fn` to detect if a Rhai function is defined (and therefore callable),
|
||||||
and the number of parameters.
|
based on its name and the number of parameters.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn foo(x) { x + 1 }
|
fn foo(x) { x + 1 }
|
||||||
|
|
||||||
is_def_fn("foo", 1) == true;
|
is_def_fn("foo", 1) == true;
|
||||||
|
|
||||||
|
is_def_fn("foo", 0) == false;
|
||||||
|
|
||||||
|
is_def_fn("foo", 2) == false;
|
||||||
|
|
||||||
is_def_fn("bar", 1) == false;
|
is_def_fn("bar", 1) == false;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -86,12 +86,14 @@ specially by the plugins system.
|
|||||||
|
|
||||||
`NativeCallContext` is a type that encapsulates the current _native call context_ and exposes the following:
|
`NativeCallContext` is a type that encapsulates the current _native call context_ and exposes the following:
|
||||||
|
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
| ------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| ------------------- | :-------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>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]. |
|
| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>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 |
|
| `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_imports()` | `impl Iterator<Item = (&str, &Module)>` | iterator of the current stack of [modules] imported via `import` statements |
|
||||||
| `iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
| `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature |
|
||||||
|
| `iter_namespaces()` | `impl Iterator<Item = &Module>` | 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_.
|
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
|
Most importantly, it does _not_ count as a parameter to the function and there is no need to provide
|
||||||
|
@ -399,12 +399,14 @@ specially by the plugins system.
|
|||||||
|
|
||||||
`NativeCallContext` is a type that encapsulates the current _native call context_ and exposes the following:
|
`NativeCallContext` is a type that encapsulates the current _native call context_ and exposes the following:
|
||||||
|
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
| ------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| ------------------- | :-------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>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]. |
|
| `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>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 |
|
| `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_imports()` | `impl Iterator<Item = (&str, &Module)>` | iterator of the current stack of [modules] imported via `import` statements |
|
||||||
| `iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
| `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature |
|
||||||
|
| `iter_namespaces()` | `impl Iterator<Item = &Module>` | 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_.
|
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
|
Most importantly, it does _not_ count as a parameter to the function and there is no need to provide
|
||||||
|
@ -65,15 +65,17 @@ The function signature passed to `Engine::register_raw_fn` takes the following f
|
|||||||
|
|
||||||
where:
|
where:
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| -------------------------- | :-----------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| -------------------------- | :-------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `T` | `impl Clone` | return type of the function |
|
| `T` | `impl Clone` | return type of the function |
|
||||||
| `context` | `NativeCallContext` | the current _native call context_ |
|
| `context` | `NativeCallContext` | the current _native call context_ |
|
||||||
| • `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>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]. |
|
| • `engine()` | `&Engine` | the current [`Engine`], with all configurations and settings.<br/>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 |
|
| • `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_imports()` | `impl Iterator<Item = (&str, &Module)>` | iterator of the current stack of [modules] imported via `import` statements |
|
||||||
| • `iter_namespaces()` | `impl Iterator<Item = &Module>` | iterator of the namespaces (as [modules]) containing all script-defined functions |
|
| • `imports()` | `&Imports` | reference to the current stack of [modules] imported via `import` statements; requires the [`internals`] feature |
|
||||||
| `args` | `&mut [&mut Dynamic]` | a slice containing `&mut` references to [`Dynamic`] values.<br/>The slice is guaranteed to contain enough arguments _of the correct types_. |
|
| • `iter_namespaces()` | `impl Iterator<Item = &Module>` | 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.<br/>The slice is guaranteed to contain enough arguments _of the correct types_. |
|
||||||
|
|
||||||
### Return value
|
### Return value
|
||||||
|
|
||||||
|
@ -10,8 +10,43 @@ A number of Rhai-driven utility programs can be found in the `src/bin` directory
|
|||||||
| [`rhai-repl`]({{repoTree}}/examples/rhai-repl.rs) | a simple REPL, interactively evaluate statements from stdin |
|
| [`rhai-repl`]({{repoTree}}/examples/rhai-repl.rs) | a simple REPL, interactively evaluate statements from stdin |
|
||||||
| [`rhai-run`]({{repoTree}}/examples/rhai-run.rs) | runs each filename passed to it as a Rhai script |
|
| [`rhai-run`]({{repoTree}}/examples/rhai-run.rs) | runs each filename passed to it as a Rhai script |
|
||||||
|
|
||||||
`rhai-repl` is particularly useful – it allows one to interactively try out Rhai's
|
|
||||||
language features in a standard REPL (**R**ead-**E**val-**P**rint **L**oop).
|
`rhai-repl` – The Rhai REPL Tool
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
`rhai-repl` is a particularly useful utility program – it allows one to interactively
|
||||||
|
try out Rhai's language features in a standard REPL (**R**ead-**E**val-**P**rint **L**oop).
|
||||||
|
|
||||||
|
Filenames passed to it as command line arguments are run and loaded before the REPL starts.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
The following command first runs three scripts – `init1.rhai`, `init2.rhai` and
|
||||||
|
`init3.rhai` – loading the functions defined in each script into the _global_
|
||||||
|
namespace.
|
||||||
|
|
||||||
|
Then it enters an REPL, which can call the above functions freely.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rhai-repl init1.rhai init2.rhai init3.rhai
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
`rhai-run` – The Rhai Runner
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Use `rhai-run` to run Rhai scripts.
|
||||||
|
|
||||||
|
Filenames passed to it as command line arguments are run in sequence.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
The following command runs the scripts `script1.rhai`, `script2.rhai` and `script3.rhai`
|
||||||
|
in order.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rhai-run script1.rhai script2.rhai script3.rhai
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Running a Utility Program
|
Running a Utility Program
|
||||||
|
@ -12,7 +12,7 @@ homepage = "https://github.com/jonathandturner/rhai/tree/no_std/no_std_test"
|
|||||||
repository = "https://github.com/jonathandturner/rhai"
|
repository = "https://github.com/jonathandturner/rhai"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rhai = { path = "../../", features = [ "no_std", "unchecked", "only_i32", "f32_float", "no_module" ], default_features = false }
|
rhai = { path = "../../", features = [ "no_std" ], default_features = false }
|
||||||
wee_alloc = { version = "0.4.5", default_features = false }
|
wee_alloc = { version = "0.4.5", default_features = false }
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
35
src/ast.rs
35
src/ast.rs
@ -62,7 +62,7 @@ impl FnAccess {
|
|||||||
/// _(INTERNALS)_ A type containing information on a scripted function.
|
/// _(INTERNALS)_ A type containing information on a scripted function.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -224,7 +224,11 @@ impl AST {
|
|||||||
/// Set the source.
|
/// Set the source.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_source<S: Into<ImmutableString>>(&mut self, source: Option<S>) {
|
pub fn set_source<S: Into<ImmutableString>>(&mut self, source: Option<S>) {
|
||||||
self.source = source.map(|s| s.into())
|
self.source = source.map(|s| s.into());
|
||||||
|
|
||||||
|
if let Some(module) = Shared::get_mut(&mut self.functions) {
|
||||||
|
module.set_id(self.source.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Get the statements.
|
/// Get the statements.
|
||||||
#[cfg(not(feature = "internals"))]
|
#[cfg(not(feature = "internals"))]
|
||||||
@ -271,6 +275,8 @@ impl AST {
|
|||||||
/// No statements are cloned.
|
/// No statements are cloned.
|
||||||
///
|
///
|
||||||
/// This operation is cheap because functions are shared.
|
/// This operation is cheap because functions are shared.
|
||||||
|
///
|
||||||
|
/// Not available under [`no_function`].
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clone_functions_only(&self) -> Self {
|
pub fn clone_functions_only(&self) -> Self {
|
||||||
@ -280,6 +286,8 @@ impl AST {
|
|||||||
/// No statements are cloned.
|
/// No statements are cloned.
|
||||||
///
|
///
|
||||||
/// This operation is cheap because functions are shared.
|
/// This operation is cheap because functions are shared.
|
||||||
|
///
|
||||||
|
/// Not available under [`no_function`].
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clone_functions_only_filtered(
|
pub fn clone_functions_only_filtered(
|
||||||
@ -564,6 +572,8 @@ impl AST {
|
|||||||
}
|
}
|
||||||
/// Filter out the functions, retaining only some based on a filter predicate.
|
/// Filter out the functions, retaining only some based on a filter predicate.
|
||||||
///
|
///
|
||||||
|
/// Not available under [`no_function`].
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -597,6 +607,8 @@ impl AST {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Iterate through all function definitions.
|
/// Iterate through all function definitions.
|
||||||
|
///
|
||||||
|
/// Not available under [`no_function`].
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_functions<'a>(&'a self) -> impl Iterator<Item = ScriptFnMetadata> + 'a {
|
pub fn iter_functions<'a>(&'a self) -> impl Iterator<Item = ScriptFnMetadata> + 'a {
|
||||||
@ -605,6 +617,8 @@ impl AST {
|
|||||||
.map(|(_, _, _, _, fn_def)| fn_def.into())
|
.map(|(_, _, _, _, fn_def)| fn_def.into())
|
||||||
}
|
}
|
||||||
/// Clear all function definitions in the [`AST`].
|
/// Clear all function definitions in the [`AST`].
|
||||||
|
///
|
||||||
|
/// Not available under [`no_function`].
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear_functions(&mut self) {
|
pub fn clear_functions(&mut self) {
|
||||||
@ -650,7 +664,7 @@ impl AsRef<Module> for AST {
|
|||||||
/// _(INTERNALS)_ An identifier containing an [immutable string][ImmutableString] name and a [position][Position].
|
/// _(INTERNALS)_ An identifier containing an [immutable string][ImmutableString] name and a [position][Position].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
@ -671,7 +685,7 @@ impl fmt::Debug for Ident {
|
|||||||
/// _(INTERNALS)_ A type encapsulating the mode of a `return`/`throw` statement.
|
/// _(INTERNALS)_ A type encapsulating the mode of a `return`/`throw` statement.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
||||||
@ -685,7 +699,7 @@ pub enum ReturnType {
|
|||||||
/// _(INTERNALS)_ A statement.
|
/// _(INTERNALS)_ A statement.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -882,7 +896,7 @@ impl Stmt {
|
|||||||
/// _(INTERNALS)_ A custom syntax definition.
|
/// _(INTERNALS)_ A custom syntax definition.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -909,7 +923,7 @@ impl fmt::Debug for CustomExpr {
|
|||||||
/// _(INTERNALS)_ A binary expression.
|
/// _(INTERNALS)_ A binary expression.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -923,7 +937,7 @@ pub struct BinaryExpr {
|
|||||||
/// _(INTERNALS)_ A function call.
|
/// _(INTERNALS)_ A function call.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
@ -948,7 +962,7 @@ pub struct FnCallExpr {
|
|||||||
/// _(INTERNALS)_ An expression sub-tree.
|
/// _(INTERNALS)_ An expression sub-tree.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -1028,7 +1042,7 @@ impl Expr {
|
|||||||
AccessMode::ReadOnly,
|
AccessMode::ReadOnly,
|
||||||
)),
|
)),
|
||||||
Self::BoolConstant(x, _) => (*x).into(),
|
Self::BoolConstant(x, _) => (*x).into(),
|
||||||
Self::Unit(_) => ().into(),
|
Self::Unit(_) => Dynamic::UNIT,
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Self::Array(x, _) if self.is_constant() => {
|
Self::Array(x, _) if self.is_constant() => {
|
||||||
@ -1245,6 +1259,7 @@ mod tests {
|
|||||||
assert_eq!(size_of::<Option<crate::ast::Expr>>(), 16);
|
assert_eq!(size_of::<Option<crate::ast::Expr>>(), 16);
|
||||||
assert_eq!(size_of::<crate::ast::Stmt>(), 32);
|
assert_eq!(size_of::<crate::ast::Stmt>(), 32);
|
||||||
assert_eq!(size_of::<Option<crate::ast::Stmt>>(), 32);
|
assert_eq!(size_of::<Option<crate::ast::Stmt>>(), 32);
|
||||||
|
assert_eq!(size_of::<crate::FnPtr>(), 32);
|
||||||
assert_eq!(size_of::<crate::Scope>(), 48);
|
assert_eq!(size_of::<crate::Scope>(), 48);
|
||||||
assert_eq!(size_of::<crate::LexError>(), 56);
|
assert_eq!(size_of::<crate::LexError>(), 56);
|
||||||
assert_eq!(size_of::<crate::ParseError>(), 16);
|
assert_eq!(size_of::<crate::ParseError>(), 16);
|
||||||
|
@ -92,8 +92,10 @@ fn main() {
|
|||||||
let module = match engine
|
let module = match engine
|
||||||
.compile(&contents)
|
.compile(&contents)
|
||||||
.map_err(|err| err.into())
|
.map_err(|err| err.into())
|
||||||
.and_then(|ast| Module::eval_ast_as_new(Default::default(), &ast, &engine))
|
.and_then(|mut ast| {
|
||||||
{
|
ast.set_source(Some(&filename));
|
||||||
|
Module::eval_ast_as_new(Default::default(), &ast, &engine)
|
||||||
|
}) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{:=<1$}", "", filename.len());
|
eprintln!("{:=<1$}", "", filename.len());
|
||||||
eprintln!("{}", filename);
|
eprintln!("{}", filename);
|
||||||
|
@ -9,7 +9,7 @@ use crate::stdlib::{
|
|||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
mem,
|
mem,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
string::{String, ToString},
|
string::String,
|
||||||
};
|
};
|
||||||
use crate::{FnPtr, ImmutableString, INT};
|
use crate::{FnPtr, ImmutableString, INT};
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ pub enum AccessMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AccessMode {
|
impl AccessMode {
|
||||||
/// Is the access type [`ReadOnly`]?
|
/// Is the access type `ReadOnly`?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_read_only(self) -> bool {
|
pub fn is_read_only(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
@ -183,7 +183,7 @@ enum DynamicReadLockInner<'d, T: Variant + Clone> {
|
|||||||
/// A simple reference to a non-shared value.
|
/// A simple reference to a non-shared value.
|
||||||
Reference(&'d T),
|
Reference(&'d T),
|
||||||
|
|
||||||
/// A read guard to a shared `RefCell`.
|
/// A read guard to a shared [`RefCell`][std::cell::RefCell].
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
Guard(crate::stdlib::cell::Ref<'d, Dynamic>),
|
Guard(crate::stdlib::cell::Ref<'d, Dynamic>),
|
||||||
@ -220,7 +220,7 @@ enum DynamicWriteLockInner<'d, T: Variant + Clone> {
|
|||||||
/// A simple mutable reference to a non-shared value.
|
/// A simple mutable reference to a non-shared value.
|
||||||
Reference(&'d mut T),
|
Reference(&'d mut T),
|
||||||
|
|
||||||
/// A write guard to a shared `RefCell`.
|
/// A write guard to a shared [`RefCell`][std::cell::RefCell].
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
Guard(crate::stdlib::cell::RefMut<'d, Dynamic>),
|
Guard(crate::stdlib::cell::RefMut<'d, Dynamic>),
|
||||||
@ -258,7 +258,7 @@ impl<'d, T: Variant + Clone> DerefMut for DynamicWriteLock<'d, T> {
|
|||||||
|
|
||||||
impl Dynamic {
|
impl Dynamic {
|
||||||
/// Does this [`Dynamic`] hold a variant data type
|
/// Does this [`Dynamic`] hold a variant data type
|
||||||
/// instead of one of the support system primitive types?
|
/// instead of one of the supported system primitive types?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_variant(&self) -> bool {
|
pub fn is_variant(&self) -> bool {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
@ -266,8 +266,7 @@ impl Dynamic {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Does this [`Dynamic`] hold a shared data type
|
/// Is the value held by this [`Dynamic`] shared?
|
||||||
/// instead of one of the supported system primitive types?
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_shared(&self) -> bool {
|
pub fn is_shared(&self) -> bool {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
@ -279,7 +278,7 @@ impl Dynamic {
|
|||||||
/// Is the value held by this [`Dynamic`] a particular type?
|
/// Is the value held by this [`Dynamic`] a particular type?
|
||||||
///
|
///
|
||||||
/// If the [`Dynamic`] is a shared variant checking is performed on
|
/// If the [`Dynamic`] is a shared variant checking is performed on
|
||||||
/// top of it's internal value.
|
/// top of its internal value.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is<T: Variant + Clone>(&self) -> bool {
|
pub fn is<T: Variant + Clone>(&self) -> bool {
|
||||||
let mut target_type_id = TypeId::of::<T>();
|
let mut target_type_id = TypeId::of::<T>();
|
||||||
@ -508,7 +507,7 @@ impl fmt::Debug for Dynamic {
|
|||||||
impl Clone for Dynamic {
|
impl Clone for Dynamic {
|
||||||
/// Clone the [`Dynamic`] value.
|
/// Clone the [`Dynamic`] value.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// The cloned copy is marked read-write even if the original is read-only.
|
/// The cloned copy is marked read-write even if the original is read-only.
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
@ -618,7 +617,7 @@ impl Dynamic {
|
|||||||
///
|
///
|
||||||
/// Constant [`Dynamic`] values are read-only. If a [`&mut Dynamic`][Dynamic] to such a constant
|
/// Constant [`Dynamic`] values are read-only. If a [`&mut Dynamic`][Dynamic] to such a constant
|
||||||
/// is passed to a Rust function, the function can use this information to return an error of
|
/// is passed to a Rust function, the function can use this information to return an error of
|
||||||
/// [`EvalAltResult::ErrorAssignmentToConstant`][crate::EvalAltResult::ErrorAssignmentToConstant]
|
/// [`ErrorAssignmentToConstant`][crate::EvalAltResult::ErrorAssignmentToConstant]
|
||||||
/// if its value is going to be modified. This safe-guards constant values from being modified
|
/// if its value is going to be modified. This safe-guards constant values from being modified
|
||||||
/// from within Rust functions.
|
/// from within Rust functions.
|
||||||
pub fn is_read_only(&self) -> bool {
|
pub fn is_read_only(&self) -> bool {
|
||||||
@ -707,7 +706,7 @@ impl Dynamic {
|
|||||||
if TypeId::of::<T>() == TypeId::of::<&str>() {
|
if TypeId::of::<T>() == TypeId::of::<&str>() {
|
||||||
return <dyn Any>::downcast_ref::<&str>(&value)
|
return <dyn Any>::downcast_ref::<&str>(&value)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string()
|
.deref()
|
||||||
.into();
|
.into();
|
||||||
}
|
}
|
||||||
if TypeId::of::<T>() == TypeId::of::<()>() {
|
if TypeId::of::<T>() == TypeId::of::<()>() {
|
||||||
|
150
src/engine.rs
150
src/engine.rs
@ -45,13 +45,13 @@ pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical
|
|||||||
/// _(INTERNALS)_ A stack of imported [modules][Module].
|
/// _(INTERNALS)_ A stack of imported [modules][Module].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
//
|
//
|
||||||
// # Implementation Notes
|
// # Implementation Notes
|
||||||
//
|
//
|
||||||
// We cannot use &str or Cow<str> here because `eval` may load a [module][Module] and
|
// We cannot use Cow<str> here because `eval` may load a [module][Module] and
|
||||||
// the module name will live beyond the AST of the eval script text.
|
// the module name will live beyond the AST of the eval script text.
|
||||||
// The best we can do is a shared reference.
|
// The best we can do is a shared reference.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
@ -96,7 +96,7 @@ impl Imports {
|
|||||||
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
|
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a str, &'a Module)> + 'a {
|
pub fn iter(&self) -> impl Iterator<Item = (&str, &Module)> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
@ -105,9 +105,7 @@ impl Imports {
|
|||||||
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
|
/// Get an iterator to this stack of imported [modules][Module] in reverse order.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn iter_raw<'a>(
|
pub(crate) fn iter_raw(&self) -> impl Iterator<Item = (&ImmutableString, &Shared<Module>)> {
|
||||||
&'a self,
|
|
||||||
) -> impl Iterator<Item = (&'a ImmutableString, &'a Shared<Module>)> + 'a {
|
|
||||||
self.0.iter().rev().map(|(n, m)| (n, m))
|
self.0.iter().rev().map(|(n, m)| (n, m))
|
||||||
}
|
}
|
||||||
/// Get a consuming iterator to this stack of imported [modules][Module] in reverse order.
|
/// Get a consuming iterator to this stack of imported [modules][Module] in reverse order.
|
||||||
@ -128,11 +126,14 @@ impl Imports {
|
|||||||
}
|
}
|
||||||
/// Get specified function via its hash key.
|
/// Get specified function via its hash key.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_fn(&self, hash: NonZeroU64) -> Option<&CallableFunction> {
|
pub fn get_fn(
|
||||||
|
&self,
|
||||||
|
hash: NonZeroU64,
|
||||||
|
) -> Option<(&CallableFunction, Option<&ImmutableString>)> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.find_map(|(_, m)| m.get_qualified_fn(hash))
|
.find_map(|(_, m)| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
|
||||||
}
|
}
|
||||||
/// Does the specified [`TypeId`][std::any::TypeId] iterator exist in this stack of imported [modules][Module]?
|
/// Does the specified [`TypeId`][std::any::TypeId] iterator exist in this stack of imported [modules][Module]?
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -216,55 +217,62 @@ pub const FN_ANONYMOUS: &str = "anon$";
|
|||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
pub const OP_EQUALS: &str = "==";
|
pub const OP_EQUALS: &str = "==";
|
||||||
|
|
||||||
/// A type specifying the method of chaining.
|
/// Method of chaining.
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum ChainType {
|
pub enum ChainType {
|
||||||
None,
|
/// Not a chaining type.
|
||||||
|
NonChaining,
|
||||||
|
/// Indexing.
|
||||||
Index,
|
Index,
|
||||||
|
/// Dotting.
|
||||||
Dot,
|
Dot,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Value of a chaining argument.
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
pub enum IndexChainValue {
|
pub enum ChainArgument {
|
||||||
None,
|
/// Dot-property access.
|
||||||
|
Property,
|
||||||
|
/// Arguments to a dot-function call.
|
||||||
FnCallArgs(StaticVec<Dynamic>),
|
FnCallArgs(StaticVec<Dynamic>),
|
||||||
Value(Dynamic),
|
/// Index value.
|
||||||
|
IndexValue(Dynamic),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
impl IndexChainValue {
|
impl ChainArgument {
|
||||||
/// Return the `Dynamic` value.
|
/// Return the `Dynamic` value.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if not `IndexChainValue::Value`.
|
/// Panics if not `ChainArgument::IndexValue`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
pub fn as_value(self) -> Dynamic {
|
pub fn as_index_value(self) -> Dynamic {
|
||||||
match self {
|
match self {
|
||||||
Self::None | Self::FnCallArgs(_) => panic!("expecting IndexChainValue::Value"),
|
Self::Property | Self::FnCallArgs(_) => panic!("expecting ChainArgument::IndexValue"),
|
||||||
Self::Value(value) => value,
|
Self::IndexValue(value) => value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Return the `StaticVec<Dynamic>` value.
|
/// Return the `StaticVec<Dynamic>` value.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if not `IndexChainValue::FnCallArgs`.
|
/// Panics if not `ChainArgument::FnCallArgs`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub fn as_fn_call_args(self) -> StaticVec<Dynamic> {
|
pub fn as_fn_call_args(self) -> StaticVec<Dynamic> {
|
||||||
match self {
|
match self {
|
||||||
Self::None | Self::Value(_) => panic!("expecting IndexChainValue::FnCallArgs"),
|
Self::Property | Self::IndexValue(_) => panic!("expecting ChainArgument::FnCallArgs"),
|
||||||
Self::FnCallArgs(value) => value,
|
Self::FnCallArgs(value) => value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
impl From<StaticVec<Dynamic>> for IndexChainValue {
|
impl From<StaticVec<Dynamic>> for ChainArgument {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: StaticVec<Dynamic>) -> Self {
|
fn from(value: StaticVec<Dynamic>) -> Self {
|
||||||
Self::FnCallArgs(value)
|
Self::FnCallArgs(value)
|
||||||
@ -272,10 +280,10 @@ impl From<StaticVec<Dynamic>> for IndexChainValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
impl From<Dynamic> for IndexChainValue {
|
impl From<Dynamic> for ChainArgument {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: Dynamic) -> Self {
|
fn from(value: Dynamic) -> Self {
|
||||||
Self::Value(value)
|
Self::IndexValue(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +497,7 @@ impl<T: Into<Dynamic>> From<T> for Target<'_> {
|
|||||||
/// _(INTERNALS)_ A type that holds all the current states of the [`Engine`].
|
/// _(INTERNALS)_ A type that holds all the current states of the [`Engine`].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
@ -508,7 +516,11 @@ pub struct State {
|
|||||||
/// Number of modules loaded.
|
/// Number of modules loaded.
|
||||||
pub modules: usize,
|
pub modules: usize,
|
||||||
/// Cached lookup values for function hashes.
|
/// Cached lookup values for function hashes.
|
||||||
pub functions_cache: HashMap<NonZeroU64, Option<CallableFunction>, StraightHasherBuilder>,
|
pub functions_cache: HashMap<
|
||||||
|
NonZeroU64,
|
||||||
|
Option<(CallableFunction, Option<ImmutableString>)>,
|
||||||
|
StraightHasherBuilder,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
@ -522,7 +534,7 @@ impl State {
|
|||||||
/// _(INTERNALS)_ A type containing all the limits imposed by the [`Engine`].
|
/// _(INTERNALS)_ A type containing all the limits imposed by the [`Engine`].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
@ -571,17 +583,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> {
|
impl<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> EvalContext<'e, 'x, 'px, 'a, 's, 'm, 'pm, 't, 'pt> {
|
||||||
/// The current [`Engine`].
|
/// The current [`Engine`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn engine(&self) -> &'e Engine {
|
pub fn engine(&self) -> &Engine {
|
||||||
self.engine
|
self.engine
|
||||||
}
|
}
|
||||||
/// The current source.
|
/// The current source.
|
||||||
#[inline(always)]
|
#[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())
|
self.state.source.as_ref().map(|s| s.as_str())
|
||||||
}
|
}
|
||||||
/// The current [`Scope`].
|
/// The current [`Scope`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn scope(&self) -> &Scope<'px> {
|
pub fn scope(&self) -> &Scope {
|
||||||
self.scope
|
self.scope
|
||||||
}
|
}
|
||||||
/// Mutable reference to the current [`Scope`].
|
/// Mutable reference to the current [`Scope`].
|
||||||
@ -589,19 +601,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> {
|
pub fn scope_mut(&mut self) -> &mut &'x mut Scope<'px> {
|
||||||
&mut self.scope
|
&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<Item = (&str, &Module)> {
|
||||||
|
self.mods.iter()
|
||||||
|
}
|
||||||
/// _(INTERNALS)_ The current set of modules imported via `import` statements.
|
/// _(INTERNALS)_ The current set of modules imported via `import` statements.
|
||||||
/// Available under the `internals` feature only.
|
/// Available under the `internals` feature only.
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn imports(&'a self) -> &'a Imports {
|
pub fn imports(&self) -> &Imports {
|
||||||
self.mods
|
self.mods
|
||||||
}
|
}
|
||||||
/// Get an iterator over the namespaces containing definition of all script-defined functions.
|
/// Get an iterator over the namespaces containing definition of all script-defined functions.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_namespaces(&self) -> impl Iterator<Item = &'pm Module> + 'm {
|
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
|
||||||
self.lib.iter().cloned()
|
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.
|
/// The current bound `this` pointer, if any.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn this_ptr(&self) -> Option<&Dynamic> {
|
pub fn this_ptr(&self) -> Option<&Dynamic> {
|
||||||
@ -835,7 +860,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new [`Engine`] with minimal built-in functions.
|
/// Create a new [`Engine`] with minimal built-in functions.
|
||||||
/// Use the [`register_global_module`][Engine::register_global_module] method to load additional packages of functions.
|
///
|
||||||
|
/// Use [`register_global_module`][Engine::register_global_module] to add packages of functions.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_raw() -> Self {
|
pub fn new_raw() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -1006,13 +1032,13 @@ impl Engine {
|
|||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
target: &mut Target,
|
target: &mut Target,
|
||||||
rhs: &Expr,
|
rhs: &Expr,
|
||||||
idx_values: &mut StaticVec<IndexChainValue>,
|
idx_values: &mut StaticVec<ChainArgument>,
|
||||||
chain_type: ChainType,
|
chain_type: ChainType,
|
||||||
level: usize,
|
level: usize,
|
||||||
new_val: Option<(Dynamic, Position)>,
|
new_val: Option<(Dynamic, Position)>,
|
||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
if chain_type == ChainType::None {
|
if chain_type == ChainType::NonChaining {
|
||||||
unreachable!("should not be ChainType::None");
|
unreachable!("should not be ChainType::NonChaining");
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_ref = target.is_ref();
|
let is_ref = target.is_ref();
|
||||||
@ -1020,7 +1046,7 @@ impl Engine {
|
|||||||
let next_chain = match rhs {
|
let next_chain = match rhs {
|
||||||
Expr::Index(_, _) => ChainType::Index,
|
Expr::Index(_, _) => ChainType::Index,
|
||||||
Expr::Dot(_, _) => ChainType::Dot,
|
Expr::Dot(_, _) => ChainType::Dot,
|
||||||
_ => ChainType::None,
|
_ => ChainType::NonChaining,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pop the last index value
|
// Pop the last index value
|
||||||
@ -1037,7 +1063,7 @@ impl Engine {
|
|||||||
// xxx[idx].expr... | xxx[idx][expr]...
|
// xxx[idx].expr... | xxx[idx][expr]...
|
||||||
Expr::Dot(x, x_pos) | Expr::Index(x, x_pos) => {
|
Expr::Dot(x, x_pos) | Expr::Index(x, x_pos) => {
|
||||||
let idx_pos = x.lhs.position();
|
let idx_pos = x.lhs.position();
|
||||||
let idx_val = idx_val.as_value();
|
let idx_val = idx_val.as_index_value();
|
||||||
let obj_ptr = &mut self.get_indexed_mut(
|
let obj_ptr = &mut self.get_indexed_mut(
|
||||||
mods, state, lib, target_val, idx_val, idx_pos, false, is_ref, true,
|
mods, state, lib, target_val, idx_val, idx_pos, false, is_ref, true,
|
||||||
level,
|
level,
|
||||||
@ -1051,7 +1077,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// xxx[rhs] = new_val
|
// xxx[rhs] = new_val
|
||||||
_ if new_val.is_some() => {
|
_ if new_val.is_some() => {
|
||||||
let idx_val = idx_val.as_value();
|
let idx_val = idx_val.as_index_value();
|
||||||
let mut idx_val2 = idx_val.clone();
|
let mut idx_val2 = idx_val.clone();
|
||||||
|
|
||||||
// `call_setter` is introduced to bypass double mutable borrowing of target
|
// `call_setter` is introduced to bypass double mutable borrowing of target
|
||||||
@ -1099,7 +1125,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
// xxx[rhs]
|
// xxx[rhs]
|
||||||
_ => {
|
_ => {
|
||||||
let idx_val = idx_val.as_value();
|
let idx_val = idx_val.as_index_value();
|
||||||
self.get_indexed_mut(
|
self.get_indexed_mut(
|
||||||
mods, state, lib, target_val, idx_val, pos, false, is_ref, true, level,
|
mods, state, lib, target_val, idx_val, pos, false, is_ref, true, level,
|
||||||
)
|
)
|
||||||
@ -1167,7 +1193,6 @@ impl Engine {
|
|||||||
None, None, level,
|
None, None, level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| (v, true))
|
.map(|(v, _)| (v, true))
|
||||||
.map_err(|err| err.fill_position(*pos))
|
|
||||||
}
|
}
|
||||||
// xxx.id
|
// xxx.id
|
||||||
Expr::Property(x) => {
|
Expr::Property(x) => {
|
||||||
@ -1178,7 +1203,6 @@ impl Engine {
|
|||||||
None, None, level,
|
None, None, level,
|
||||||
)
|
)
|
||||||
.map(|(v, _)| (v, false))
|
.map(|(v, _)| (v, false))
|
||||||
.map_err(|err| err.fill_position(*pos))
|
|
||||||
}
|
}
|
||||||
// {xxx:map}.sub_lhs[expr] | {xxx:map}.sub_lhs.expr
|
// {xxx:map}.sub_lhs[expr] | {xxx:map}.sub_lhs.expr
|
||||||
Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) if target_val.is::<Map>() => {
|
Expr::Index(x, x_pos) | Expr::Dot(x, x_pos) if target_val.is::<Map>() => {
|
||||||
@ -1229,12 +1253,10 @@ impl Engine {
|
|||||||
let (getter, setter, Ident { pos, .. }) = p.as_ref();
|
let (getter, setter, Ident { pos, .. }) = p.as_ref();
|
||||||
let arg_values = &mut [target_val, &mut Default::default()];
|
let arg_values = &mut [target_val, &mut Default::default()];
|
||||||
let args = &mut arg_values[..1];
|
let args = &mut arg_values[..1];
|
||||||
let (mut val, updated) = self
|
let (mut val, updated) = self.exec_fn_call(
|
||||||
.exec_fn_call(
|
mods, state, lib, getter, None, args, is_ref, true, false,
|
||||||
mods, state, lib, getter, None, args, is_ref, true, false,
|
*pos, None, None, level,
|
||||||
*pos, None, None, level,
|
)?;
|
||||||
)
|
|
||||||
.map_err(|err| err.fill_position(*pos))?;
|
|
||||||
|
|
||||||
let val = &mut val;
|
let val = &mut val;
|
||||||
|
|
||||||
@ -1267,7 +1289,7 @@ impl Engine {
|
|||||||
EvalAltResult::ErrorDotExpr(_, _) => {
|
EvalAltResult::ErrorDotExpr(_, _) => {
|
||||||
Ok((Dynamic::UNIT, false))
|
Ok((Dynamic::UNIT, false))
|
||||||
}
|
}
|
||||||
_ => Err(err.fill_position(*x_pos)),
|
_ => Err(err),
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
@ -1394,7 +1416,7 @@ impl Engine {
|
|||||||
this_ptr: &mut Option<&mut Dynamic>,
|
this_ptr: &mut Option<&mut Dynamic>,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
parent_chain_type: ChainType,
|
parent_chain_type: ChainType,
|
||||||
idx_values: &mut StaticVec<IndexChainValue>,
|
idx_values: &mut StaticVec<ChainArgument>,
|
||||||
size: usize,
|
size: usize,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> Result<(), Box<EvalAltResult>> {
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
@ -1417,7 +1439,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Expr::Property(_) if parent_chain_type == ChainType::Dot => {
|
Expr::Property(_) if parent_chain_type == ChainType::Dot => {
|
||||||
idx_values.push(IndexChainValue::None)
|
idx_values.push(ChainArgument::Property)
|
||||||
}
|
}
|
||||||
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
|
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
|
||||||
|
|
||||||
@ -1427,7 +1449,7 @@ impl Engine {
|
|||||||
// Evaluate in left-to-right order
|
// Evaluate in left-to-right order
|
||||||
let lhs_val = match lhs {
|
let lhs_val = match lhs {
|
||||||
Expr::Property(_) if parent_chain_type == ChainType::Dot => {
|
Expr::Property(_) if parent_chain_type == ChainType::Dot => {
|
||||||
IndexChainValue::None
|
ChainArgument::Property
|
||||||
}
|
}
|
||||||
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
|
Expr::Property(_) => unreachable!("unexpected Expr::Property for indexing"),
|
||||||
Expr::FnCall(x, _)
|
Expr::FnCall(x, _)
|
||||||
@ -2027,15 +2049,16 @@ impl Engine {
|
|||||||
match self
|
match self
|
||||||
.global_namespace
|
.global_namespace
|
||||||
.get_fn(hash_fn, false)
|
.get_fn(hash_fn, false)
|
||||||
|
.map(|f| (f, None))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.global_modules
|
self.global_modules
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|m| m.get_fn(hash_fn, false))
|
.find_map(|m| m.get_fn(hash_fn, false).map(|f| (f, m.id_raw())))
|
||||||
})
|
})
|
||||||
.or_else(|| mods.get_fn(hash_fn))
|
.or_else(|| mods.get_fn(hash_fn))
|
||||||
{
|
{
|
||||||
// op= function registered as method
|
// op= function registered as method
|
||||||
Some(func) if func.is_method() => {
|
Some((func, source)) if func.is_method() => {
|
||||||
let mut lock_guard;
|
let mut lock_guard;
|
||||||
let lhs_ptr_inner;
|
let lhs_ptr_inner;
|
||||||
|
|
||||||
@ -2049,14 +2072,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 = if source.is_none() {
|
||||||
|
state.source.as_ref()
|
||||||
|
} else {
|
||||||
|
source
|
||||||
|
};
|
||||||
if func.is_plugin_fn() {
|
if func.is_plugin_fn() {
|
||||||
func.get_plugin_fn()
|
func.get_plugin_fn()
|
||||||
.call((self, &state.source, &*mods, lib).into(), args)?;
|
.call((self, source, &*mods, lib).into(), args)?;
|
||||||
} else {
|
} else {
|
||||||
func.get_native_fn()(
|
func.get_native_fn()((self, source, &*mods, lib).into(), args)?;
|
||||||
(self, &state.source, &*mods, lib).into(),
|
|
||||||
args,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Built-in op-assignment function
|
// Built-in op-assignment function
|
||||||
@ -2301,7 +2326,7 @@ impl Engine {
|
|||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.eval_stmt(scope, mods, state, lib, this_ptr, try_body, level)
|
.eval_stmt(scope, mods, state, lib, this_ptr, try_body, level)
|
||||||
.map(|_| ().into());
|
.map(|_| Dynamic::UNIT);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => result,
|
Ok(_) => result,
|
||||||
@ -2363,7 +2388,7 @@ impl Engine {
|
|||||||
|
|
||||||
// Empty throw
|
// Empty throw
|
||||||
Stmt::Return((ReturnType::Exception, pos), None, _) => {
|
Stmt::Return((ReturnType::Exception, pos), None, _) => {
|
||||||
EvalAltResult::ErrorRuntime(().into(), *pos).into()
|
EvalAltResult::ErrorRuntime(Dynamic::UNIT, *pos).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let/const statement
|
// Let/const statement
|
||||||
@ -2378,7 +2403,7 @@ impl Engine {
|
|||||||
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
||||||
.flatten()
|
.flatten()
|
||||||
} else {
|
} else {
|
||||||
().into()
|
Dynamic::UNIT
|
||||||
};
|
};
|
||||||
let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() {
|
let (var_name, _alias): (Cow<'_, str>, _) = if state.is_global() {
|
||||||
(
|
(
|
||||||
@ -2596,6 +2621,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the number of operations stay within limit.
|
/// Check if the number of operations stay within limit.
|
||||||
|
#[inline]
|
||||||
pub(crate) fn inc_operations(
|
pub(crate) fn inc_operations(
|
||||||
&self,
|
&self,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
|
@ -35,7 +35,7 @@ fn calc_hash_for_scripts<'a>(scripts: impl IntoIterator<Item = &'a &'a str>) ->
|
|||||||
impl Engine {
|
impl Engine {
|
||||||
/// Register a function of the [`Engine`].
|
/// Register a function of the [`Engine`].
|
||||||
///
|
///
|
||||||
/// ## WARNING - Low Level API
|
/// # WARNING - Low Level API
|
||||||
///
|
///
|
||||||
/// This function is very low level. It takes a list of [`TypeId`][std::any::TypeId]'s indicating the actual types of the parameters.
|
/// This function is very low level. It takes a list of [`TypeId`][std::any::TypeId]'s indicating the actual types of the parameters.
|
||||||
///
|
///
|
||||||
@ -88,13 +88,12 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine
|
||||||
///
|
/// .register_type::<TestStruct>()
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
///
|
/// // Use `register_fn` to register methods on the type.
|
||||||
/// // Use `register_fn` to register methods on the type.
|
/// .register_fn("update", TestStruct::update);
|
||||||
/// engine.register_fn("update", TestStruct::update);
|
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// engine.eval::<TestStruct>("let x = new_ts(); x.update(41); x")?,
|
/// engine.eval::<TestStruct>("let x = new_ts(); x.update(41); x")?,
|
||||||
@ -128,22 +127,19 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine
|
||||||
///
|
/// .register_type::<TestStruct>()
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// .register_fn("new_ts", TestStruct::new);
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// engine.eval::<String>("let x = new_ts(); type_of(x)")?,
|
/// engine.eval::<String>("let x = new_ts(); type_of(x)")?,
|
||||||
/// "rust_out::TestStruct"
|
/// "rust_out::TestStruct"
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// // Register the custom type with a name.
|
/// // Re-register the custom type with a name.
|
||||||
/// engine.register_type_with_name::<TestStruct>("Hello");
|
/// engine.register_type_with_name::<TestStruct>("Hello");
|
||||||
///
|
///
|
||||||
/// // Register methods on the type.
|
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
|
||||||
///
|
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// engine.eval::<String>("let x = new_ts(); type_of(x)")?,
|
/// engine.eval::<String>("let x = new_ts(); type_of(x)")?,
|
||||||
/// "Hello"
|
/// "Hello"
|
||||||
@ -192,13 +188,12 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine
|
||||||
///
|
/// .register_type::<TestStruct>()
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
///
|
/// // Register a getter on a property (notice it doesn't have to be the same name).
|
||||||
/// // Register a getter on a property (notice it doesn't have to be the same name).
|
/// .register_get("xyz", TestStruct::get_field);
|
||||||
/// engine.register_get("xyz", TestStruct::get_field);
|
|
||||||
///
|
///
|
||||||
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz")?, 1);
|
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz")?, 1);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
@ -239,13 +234,12 @@ impl Engine {
|
|||||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine
|
||||||
///
|
/// .register_type::<TestStruct>()
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
///
|
/// // Register a getter on a property (notice it doesn't have to be the same name).
|
||||||
/// // Register a getter on a property (notice it doesn't have to be the same name).
|
/// .register_get_result("xyz", TestStruct::get_field);
|
||||||
/// engine.register_get_result("xyz", TestStruct::get_field);
|
|
||||||
///
|
///
|
||||||
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz")?, 1);
|
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz")?, 1);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
@ -281,13 +275,12 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine
|
||||||
///
|
/// .register_type::<TestStruct>()
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
///
|
/// // Register a setter on a property (notice it doesn't have to be the same name)
|
||||||
/// // Register a setter on a property (notice it doesn't have to be the same name)
|
/// .register_set("xyz", TestStruct::set_field);
|
||||||
/// engine.register_set("xyz", TestStruct::set_field);
|
|
||||||
///
|
///
|
||||||
/// // Notice that, with a getter, there is no way to get the property value
|
/// // Notice that, with a getter, there is no way to get the property value
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
@ -330,13 +323,12 @@ impl Engine {
|
|||||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine
|
||||||
///
|
/// .register_type::<TestStruct>()
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
///
|
/// // Register a setter on a property (notice it doesn't have to be the same name)
|
||||||
/// // Register a setter on a property (notice it doesn't have to be the same name)
|
/// .register_set_result("xyz", TestStruct::set_field);
|
||||||
/// engine.register_set_result("xyz", TestStruct::set_field);
|
|
||||||
///
|
///
|
||||||
/// // Notice that, with a getter, there is no way to get the property value
|
/// // Notice that, with a getter, there is no way to get the property value
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
@ -383,14 +375,13 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine
|
||||||
///
|
/// .register_type::<TestStruct>()
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
///
|
/// // Register both a getter and a setter on a property
|
||||||
/// // Register a getter and a setter on a property
|
/// // (notice it doesn't have to be the same name)
|
||||||
/// // (notice it doesn't have to be the same name)
|
/// .register_get_set("xyz", TestStruct::get_field, TestStruct::set_field);
|
||||||
/// engine.register_get_set("xyz", TestStruct::get_field, TestStruct::set_field);
|
|
||||||
///
|
///
|
||||||
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz = 42; a.xyz")?, 42);
|
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz = 42; a.xyz")?, 42);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
@ -434,14 +425,14 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// # #[cfg(not(feature = "no_object"))]
|
/// # #[cfg(not(feature = "no_object"))]
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine.register_type::<TestStruct>();
|
||||||
///
|
///
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// engine
|
||||||
///
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
/// // Register an indexer.
|
/// // Register an indexer.
|
||||||
/// engine.register_indexer_get(TestStruct::get_field);
|
/// .register_indexer_get(TestStruct::get_field);
|
||||||
///
|
///
|
||||||
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2]")?, 3);
|
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2]")?, 3);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
@ -500,14 +491,14 @@ impl Engine {
|
|||||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// # #[cfg(not(feature = "no_object"))]
|
/// # #[cfg(not(feature = "no_object"))]
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine.register_type::<TestStruct>();
|
||||||
///
|
///
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// engine
|
||||||
///
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
/// // Register an indexer.
|
/// // Register an indexer.
|
||||||
/// engine.register_indexer_get_result(TestStruct::get_field);
|
/// .register_indexer_get_result(TestStruct::get_field);
|
||||||
///
|
///
|
||||||
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2]")?, 3);
|
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2]")?, 3);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
@ -561,14 +552,14 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// # #[cfg(not(feature = "no_object"))]
|
/// # #[cfg(not(feature = "no_object"))]
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine.register_type::<TestStruct>();
|
||||||
///
|
///
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// engine
|
||||||
///
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
/// // Register an indexer.
|
/// // Register an indexer.
|
||||||
/// engine.register_indexer_set(TestStruct::set_field);
|
/// .register_indexer_set(TestStruct::set_field);
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// engine.eval::<TestStruct>("let a = new_ts(); a[2] = 42; a")?.fields[2],
|
/// engine.eval::<TestStruct>("let a = new_ts(); a[2] = 42; a")?.fields[2],
|
||||||
@ -628,14 +619,14 @@ impl Engine {
|
|||||||
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// # #[cfg(not(feature = "no_object"))]
|
/// # #[cfg(not(feature = "no_object"))]
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine.register_type::<TestStruct>();
|
||||||
///
|
///
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// engine
|
||||||
///
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
/// // Register an indexer.
|
/// // Register an indexer.
|
||||||
/// engine.register_indexer_set_result(TestStruct::set_field);
|
/// .register_indexer_set_result(TestStruct::set_field);
|
||||||
///
|
///
|
||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// engine.eval::<TestStruct>("let a = new_ts(); a[2] = 42; a")?.fields[2],
|
/// engine.eval::<TestStruct>("let a = new_ts(); a[2] = 42; a")?.fields[2],
|
||||||
@ -700,14 +691,14 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let mut engine = Engine::new();
|
/// let mut engine = Engine::new();
|
||||||
///
|
///
|
||||||
/// // Register the custom type.
|
/// // Register API for the custom type.
|
||||||
/// # #[cfg(not(feature = "no_object"))]
|
/// # #[cfg(not(feature = "no_object"))]
|
||||||
/// engine.register_type::<TestStruct>();
|
/// engine.register_type::<TestStruct>();
|
||||||
///
|
///
|
||||||
/// engine.register_fn("new_ts", TestStruct::new);
|
/// engine
|
||||||
///
|
/// .register_fn("new_ts", TestStruct::new)
|
||||||
/// // Register an indexer.
|
/// // Register an indexer.
|
||||||
/// engine.register_indexer_get_set(TestStruct::get_field, TestStruct::set_field);
|
/// .register_indexer_get_set(TestStruct::get_field, TestStruct::set_field);
|
||||||
///
|
///
|
||||||
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2] = 42; a[2]")?, 42);
|
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2] = 42; a[2]")?, 42);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
@ -740,9 +731,9 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Register a shared [`Module`] into the global namespace of [`Engine`].
|
/// Register a shared [`Module`] into the global namespace of [`Engine`].
|
||||||
///
|
///
|
||||||
/// ## Deprecated
|
/// # Deprecated
|
||||||
///
|
///
|
||||||
/// Use `register_global_module` instead.
|
/// Use [`register_global_module`][Engine::register_global_module] instead.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[deprecated = "use `register_global_module` instead"]
|
#[deprecated = "use `register_global_module` instead"]
|
||||||
pub fn load_package(&mut self, module: impl Into<Shared<Module>>) -> &mut Self {
|
pub fn load_package(&mut self, module: impl Into<Shared<Module>>) -> &mut Self {
|
||||||
@ -768,13 +759,12 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// let module: Shared<Module> = module.into();
|
/// let module: Shared<Module> = module.into();
|
||||||
///
|
///
|
||||||
/// // Register the module as a fixed sub-module
|
/// engine
|
||||||
/// engine.register_static_module("foo::bar::baz", module.clone());
|
/// // Register the module as a fixed sub-module
|
||||||
///
|
/// .register_static_module("foo::bar::baz", module.clone())
|
||||||
/// // Multiple registrations to the same partial path is also OK!
|
/// // Multiple registrations to the same partial path is also OK!
|
||||||
/// engine.register_static_module("foo::bar::hello", module.clone());
|
/// .register_static_module("foo::bar::hello", module.clone())
|
||||||
///
|
/// .register_static_module("CalcService", module);
|
||||||
/// engine.register_static_module("CalcService", module);
|
|
||||||
///
|
///
|
||||||
/// assert_eq!(engine.eval::<i64>("foo::bar::baz::calc(41)")?, 42);
|
/// assert_eq!(engine.eval::<i64>("foo::bar::baz::calc(41)")?, 42);
|
||||||
/// assert_eq!(engine.eval::<i64>("foo::bar::hello::calc(41)")?, 42);
|
/// assert_eq!(engine.eval::<i64>("foo::bar::hello::calc(41)")?, 42);
|
||||||
@ -830,9 +820,9 @@ impl Engine {
|
|||||||
|
|
||||||
/// Register a shared [`Module`] as a static module namespace with the [`Engine`].
|
/// Register a shared [`Module`] as a static module namespace with the [`Engine`].
|
||||||
///
|
///
|
||||||
/// ## Deprecated
|
/// # Deprecated
|
||||||
///
|
///
|
||||||
/// Use `register_static_module` instead.
|
/// Use [`register_static_module`][Engine::register_static_module] instead.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[deprecated = "use `register_static_module` instead"]
|
#[deprecated = "use `register_static_module` instead"]
|
||||||
@ -1001,6 +991,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Compile a script file into an [`AST`], which can be used later for evaluation.
|
/// Compile a script file into an [`AST`], which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
|
/// Not available under `no_std` or `WASM`.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
@ -1030,6 +1022,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Compile a script file into an [`AST`] using own scope, which can be used later for evaluation.
|
/// Compile a script file into an [`AST`] using own scope, which can be used later for evaluation.
|
||||||
///
|
///
|
||||||
|
/// Not available under `no_std` or `WASM`.
|
||||||
|
///
|
||||||
/// The scope is useful for passing constants into the script for optimization
|
/// The scope is useful for passing constants into the script for optimization
|
||||||
/// when using [`OptimizationLevel::Full`].
|
/// when using [`OptimizationLevel::Full`].
|
||||||
///
|
///
|
||||||
@ -1069,12 +1063,13 @@ impl Engine {
|
|||||||
) -> Result<AST, Box<EvalAltResult>> {
|
) -> Result<AST, Box<EvalAltResult>> {
|
||||||
Self::read_file(path).and_then(|contents| Ok(self.compile_with_scope(scope, &contents)?))
|
Self::read_file(path).and_then(|contents| Ok(self.compile_with_scope(scope, &contents)?))
|
||||||
}
|
}
|
||||||
/// Parse a JSON string into a map.
|
/// Parse a JSON string into an [object map][`Map`].
|
||||||
|
/// This is a light-weight alternative to using, say, [`serde_json`][https://crates.io/crates/serde_json] to deserialize the JSON.
|
||||||
///
|
///
|
||||||
/// The JSON string must be an object hash. It cannot be a simple JavaScript primitive.
|
/// The JSON string must be an object hash. It cannot be a simple scalar value.
|
||||||
///
|
///
|
||||||
/// Set `has_null` to `true` in order to map `null` values to `()`.
|
/// Set `has_null` to `true` in order to map `null` values to `()`.
|
||||||
/// Setting it to `false` will cause a _variable not found_ error during parsing.
|
/// Setting it to `false` will cause an [`ErrorVariableNotFound`][EvalAltResult::ErrorVariableNotFound] error during parsing.
|
||||||
///
|
///
|
||||||
/// # JSON With Sub-Objects
|
/// # JSON With Sub-Objects
|
||||||
///
|
///
|
||||||
@ -1083,7 +1078,7 @@ impl Engine {
|
|||||||
/// Parsing a JSON string with sub-objects will cause a syntax error.
|
/// Parsing a JSON string with sub-objects will cause a syntax error.
|
||||||
///
|
///
|
||||||
/// If it is certain that the character `{` never appears in any text string within the JSON object,
|
/// If it is certain that the character `{` never appears in any text string within the JSON object,
|
||||||
/// then globally replace `{` with `#{` before calling this method.
|
/// which is a valid assumption for many use cases, then globally replace `{` with `#{` before calling this method.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -1235,6 +1230,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Evaluate a script file.
|
/// Evaluate a script file.
|
||||||
///
|
///
|
||||||
|
/// Not available under `no_std` or `WASM`.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
@ -1259,6 +1256,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Evaluate a script file with own scope.
|
/// Evaluate a script file with own scope.
|
||||||
///
|
///
|
||||||
|
/// Not available under `no_std` or `WASM`.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
@ -1483,6 +1482,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Evaluate a file, but throw away the result and only return error (if any).
|
/// Evaluate a file, but throw away the result and only return error (if any).
|
||||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||||
|
///
|
||||||
|
/// Not available under `no_std` or `WASM`.
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -1494,6 +1495,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Evaluate a file with own scope, but throw away the result and only return error (if any).
|
/// Evaluate a file with own scope, but throw away the result and only return error (if any).
|
||||||
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
/// Useful for when you don't need the result, but still need to keep track of possible errors.
|
||||||
|
///
|
||||||
|
/// Not available under `no_std` or `WASM`.
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -1611,7 +1614,7 @@ impl Engine {
|
|||||||
/// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments
|
/// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments
|
||||||
/// and optionally a value for binding to the `this` pointer.
|
/// and optionally a value for binding to the `this` pointer.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
||||||
/// This is to avoid unnecessarily cloning the arguments.
|
/// This is to avoid unnecessarily cloning the arguments.
|
||||||
@ -1673,7 +1676,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments.
|
/// Call a script function defined in an [`AST`] with multiple [`Dynamic`] arguments.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
||||||
/// This is to avoid unnecessarily cloning the arguments.
|
/// This is to avoid unnecessarily cloning the arguments.
|
||||||
@ -1776,12 +1779,12 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Provide a callback that will be invoked before each variable access.
|
/// Provide a callback that will be invoked before each variable access.
|
||||||
///
|
///
|
||||||
/// ## Return Value of Callback
|
/// # Return Value of Callback
|
||||||
///
|
///
|
||||||
/// Return `Ok(None)` to continue with normal variable access.
|
/// Return `Ok(None)` to continue with normal variable access.
|
||||||
/// Return `Ok(Some(Dynamic))` as the variable's value.
|
/// Return `Ok(Some(Dynamic))` as the variable's value.
|
||||||
///
|
///
|
||||||
/// ## Errors in Callback
|
/// # Errors in Callback
|
||||||
///
|
///
|
||||||
/// Return `Err(...)` if there is an error.
|
/// Return `Err(...)` if there is an error.
|
||||||
///
|
///
|
||||||
|
@ -10,7 +10,7 @@ use crate::stdlib::boxed::Box;
|
|||||||
impl Engine {
|
impl Engine {
|
||||||
/// Control whether and how the [`Engine`] will optimize an [`AST`][crate::AST] after compilation.
|
/// Control whether and how the [`Engine`] will optimize an [`AST`][crate::AST] after compilation.
|
||||||
///
|
///
|
||||||
/// Not available under the `no_optimize` feature.
|
/// Not available under `no_optimize`.
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_optimization_level(
|
pub fn set_optimization_level(
|
||||||
@ -23,7 +23,7 @@ impl Engine {
|
|||||||
/// The current optimization level.
|
/// The current optimization level.
|
||||||
/// It controls whether and how the [`Engine`] will optimize an [`AST`][crate::AST] after compilation.
|
/// It controls whether and how the [`Engine`] will optimize an [`AST`][crate::AST] after compilation.
|
||||||
///
|
///
|
||||||
/// Not available under the `no_optimize` feature.
|
/// Not available under `no_optimize`.
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn optimization_level(&self) -> crate::OptimizationLevel {
|
pub fn optimization_level(&self) -> crate::OptimizationLevel {
|
||||||
@ -37,6 +37,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Set the maximum levels of function calls allowed for a script in order to avoid
|
/// Set the maximum levels of function calls allowed for a script in order to avoid
|
||||||
/// infinite recursion and stack overflows.
|
/// infinite recursion and stack overflows.
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_function`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -45,6 +47,8 @@ impl Engine {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// The maximum levels of function calls allowed for a script.
|
/// The maximum levels of function calls allowed for a script.
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_function`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -53,6 +57,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Set the maximum number of operations allowed for a script to run to avoid
|
/// Set the maximum number of operations allowed for a script to run to avoid
|
||||||
/// consuming too much resources (0 for unlimited).
|
/// consuming too much resources (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_max_operations(&mut self, operations: u64) -> &mut Self {
|
pub fn set_max_operations(&mut self, operations: u64) -> &mut Self {
|
||||||
@ -64,12 +70,16 @@ impl Engine {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// The maximum number of operations allowed for a script to run (0 for unlimited).
|
/// The maximum number of operations allowed for a script to run (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn max_operations(&self) -> u64 {
|
pub fn max_operations(&self) -> u64 {
|
||||||
self.limits.max_operations
|
self.limits.max_operations
|
||||||
}
|
}
|
||||||
/// Set the maximum number of imported [modules][crate::Module] allowed for a script.
|
/// Set the maximum number of imported [modules][crate::Module] allowed for a script.
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_module`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -78,6 +88,8 @@ impl Engine {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// The maximum number of imported [modules][crate::Module] allowed for a script.
|
/// The maximum number of imported [modules][crate::Module] allowed for a script.
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_module`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -85,6 +97,8 @@ impl Engine {
|
|||||||
self.limits.max_modules
|
self.limits.max_modules
|
||||||
}
|
}
|
||||||
/// Set the depth limits for expressions (0 for unlimited).
|
/// Set the depth limits for expressions (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_max_expr_depths(
|
pub fn set_max_expr_depths(
|
||||||
@ -108,12 +122,16 @@ impl Engine {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// The depth limit for expressions (0 for unlimited).
|
/// The depth limit for expressions (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn max_expr_depth(&self) -> usize {
|
pub fn max_expr_depth(&self) -> usize {
|
||||||
self.limits.max_expr_depth
|
self.limits.max_expr_depth
|
||||||
}
|
}
|
||||||
/// The depth limit for expressions in functions (0 for unlimited).
|
/// The depth limit for expressions in functions (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_function`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -121,6 +139,8 @@ impl Engine {
|
|||||||
self.limits.max_function_expr_depth
|
self.limits.max_function_expr_depth
|
||||||
}
|
}
|
||||||
/// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
/// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self {
|
pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self {
|
||||||
@ -128,12 +148,16 @@ impl Engine {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// The maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
/// The maximum length of [strings][crate::ImmutableString] (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn max_string_size(&self) -> usize {
|
pub fn max_string_size(&self) -> usize {
|
||||||
self.limits.max_string_size
|
self.limits.max_string_size
|
||||||
}
|
}
|
||||||
/// Set the maximum length of [arrays][crate::Array] (0 for unlimited).
|
/// Set the maximum length of [arrays][crate::Array] (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_index`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -142,13 +166,17 @@ impl Engine {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// The maximum length of [arrays][crate::Array] (0 for unlimited).
|
/// The maximum length of [arrays][crate::Array] (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_index`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn max_array_size(&self) -> usize {
|
pub fn max_array_size(&self) -> usize {
|
||||||
self.limits.max_array_size
|
self.limits.max_array_size
|
||||||
}
|
}
|
||||||
/// Set the maximum length of [object maps][crate::Map] (0 for unlimited).
|
/// Set the maximum size of [object maps][crate::Map] (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_object`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -156,7 +184,9 @@ impl Engine {
|
|||||||
self.limits.max_map_size = if max_size == usize::MAX { 0 } else { max_size };
|
self.limits.max_map_size = if max_size == usize::MAX { 0 } else { max_size };
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// The maximum length of [object maps][crate::Map] (0 for unlimited).
|
/// The maximum size of [object maps][crate::Map] (0 for unlimited).
|
||||||
|
///
|
||||||
|
/// Not available under `unchecked` or `no_object`.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -165,7 +195,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Set the module resolution service used by the [`Engine`].
|
/// Set the module resolution service used by the [`Engine`].
|
||||||
///
|
///
|
||||||
/// Not available under the `no_module` feature.
|
/// Not available under `no_module`.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_module_resolver(
|
pub fn set_module_resolver(
|
||||||
|
223
src/fn_call.rs
223
src/fn_call.rs
@ -155,7 +155,7 @@ pub fn ensure_no_data_race(
|
|||||||
impl Engine {
|
impl Engine {
|
||||||
/// Call a native Rust function registered with the [`Engine`].
|
/// Call a native Rust function registered with the [`Engine`].
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// Function call arguments be _consumed_ when the function requires them to be passed by value.
|
/// Function call arguments be _consumed_ when the function requires them to be passed by value.
|
||||||
/// All function arguments not in the first position are always passed by value and thus consumed.
|
/// All function arguments not in the first position are always passed by value and thus consumed.
|
||||||
@ -175,32 +175,31 @@ impl Engine {
|
|||||||
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
) -> Result<(Dynamic, bool), Box<EvalAltResult>> {
|
||||||
self.inc_operations(state, pos)?;
|
self.inc_operations(state, pos)?;
|
||||||
|
|
||||||
let func = state.functions_cache.get(&hash_fn).cloned();
|
// Check if function access already in the cache
|
||||||
|
let func = &*state.functions_cache.entry(hash_fn).or_insert_with(|| {
|
||||||
let func = if let Some(ref f) = func {
|
|
||||||
f.as_ref()
|
|
||||||
} else {
|
|
||||||
// Search for the native function
|
// Search for the native function
|
||||||
// First search registered functions (can override packages)
|
// First search registered functions (can override packages)
|
||||||
// Then search packages
|
// Then search packages
|
||||||
// Finally search modules
|
// Finally search modules
|
||||||
|
|
||||||
//lib.get_fn(hash_fn, pub_only)
|
//lib.get_fn(hash_fn, pub_only)
|
||||||
let f = self
|
self.global_namespace
|
||||||
.global_namespace
|
|
||||||
.get_fn(hash_fn, pub_only)
|
.get_fn(hash_fn, pub_only)
|
||||||
|
.cloned()
|
||||||
|
.map(|f| (f, None))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.global_modules
|
self.global_modules.iter().find_map(|m| {
|
||||||
.iter()
|
m.get_fn(hash_fn, false)
|
||||||
.find_map(|m| m.get_fn(hash_fn, false))
|
.map(|f| (f.clone(), m.id_raw().cloned()))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.or_else(|| mods.get_fn(hash_fn));
|
.or_else(|| {
|
||||||
|
mods.get_fn(hash_fn)
|
||||||
|
.map(|(f, source)| (f.clone(), source.cloned()))
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
state.functions_cache.insert(hash_fn, f.cloned());
|
if let Some((func, source)) = func {
|
||||||
f
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(func) = func {
|
|
||||||
assert!(func.is_native());
|
assert!(func.is_native());
|
||||||
|
|
||||||
// Calling pure function but the first argument is a reference?
|
// Calling pure function but the first argument is a reference?
|
||||||
@ -208,11 +207,16 @@ impl Engine {
|
|||||||
backup.change_first_arg_to_copy(is_ref && func.is_pure(), args);
|
backup.change_first_arg_to_copy(is_ref && func.is_pure(), args);
|
||||||
|
|
||||||
// Run external function
|
// Run external function
|
||||||
|
let source = if source.is_none() {
|
||||||
|
state.source.as_ref()
|
||||||
|
} else {
|
||||||
|
source.as_ref()
|
||||||
|
};
|
||||||
let result = if func.is_plugin_fn() {
|
let result = if func.is_plugin_fn() {
|
||||||
func.get_plugin_fn()
|
func.get_plugin_fn()
|
||||||
.call((self, &state.source, mods, lib).into(), args)
|
.call((self, source, mods, lib).into(), args)
|
||||||
} else {
|
} else {
|
||||||
func.get_native_fn()((self, &state.source, mods, lib).into(), args)
|
func.get_native_fn()((self, source, mods, lib).into(), args)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Restore the original reference
|
// Restore the original reference
|
||||||
@ -338,7 +342,7 @@ impl Engine {
|
|||||||
|
|
||||||
/// Call a script-defined function.
|
/// Call a script-defined function.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
||||||
/// All function arguments not in the first position are always passed by value and thus consumed.
|
/// All function arguments not in the first position are always passed by value and thus consumed.
|
||||||
@ -413,9 +417,26 @@ impl Engine {
|
|||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
// Convert return statement to return value
|
// Convert return statement to return value
|
||||||
EvalAltResult::Return(x, _) => Ok(x),
|
EvalAltResult::Return(x, _) => Ok(x),
|
||||||
EvalAltResult::ErrorInFunctionCall(name, err, _) => {
|
EvalAltResult::ErrorInFunctionCall(name, src, err, _) => {
|
||||||
EvalAltResult::ErrorInFunctionCall(
|
EvalAltResult::ErrorInFunctionCall(
|
||||||
format!("{} > {}", fn_def.name, name),
|
format!(
|
||||||
|
"{}{} < {}",
|
||||||
|
name,
|
||||||
|
if src.is_empty() {
|
||||||
|
"".to_string()
|
||||||
|
} else {
|
||||||
|
format!(" @ '{}'", src)
|
||||||
|
},
|
||||||
|
fn_def.name
|
||||||
|
),
|
||||||
|
fn_def
|
||||||
|
.lib
|
||||||
|
.as_ref()
|
||||||
|
.map(|m| m.id())
|
||||||
|
.flatten()
|
||||||
|
.or_else(|| state.source.as_ref().map(|s| s.as_str()))
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string(),
|
||||||
err,
|
err,
|
||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
@ -424,7 +445,20 @@ impl Engine {
|
|||||||
// System errors are passed straight-through
|
// System errors are passed straight-through
|
||||||
err if err.is_system_exception() => Err(Box::new(err)),
|
err if err.is_system_exception() => Err(Box::new(err)),
|
||||||
// Other errors are wrapped in `ErrorInFunctionCall`
|
// Other errors are wrapped in `ErrorInFunctionCall`
|
||||||
_ => EvalAltResult::ErrorInFunctionCall(fn_def.name.to_string(), err, pos).into(),
|
_ => EvalAltResult::ErrorInFunctionCall(
|
||||||
|
fn_def.name.to_string(),
|
||||||
|
fn_def
|
||||||
|
.lib
|
||||||
|
.as_ref()
|
||||||
|
.map(|m| m.id())
|
||||||
|
.flatten()
|
||||||
|
.or_else(|| state.source.as_ref().map(|s| s.as_str()))
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string(),
|
||||||
|
err,
|
||||||
|
pos,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove all local variables
|
// Remove all local variables
|
||||||
@ -478,7 +512,7 @@ impl Engine {
|
|||||||
|
|
||||||
/// Perform an actual function call, native Rust or scripted, taking care of special functions.
|
/// Perform an actual function call, native Rust or scripted, taking care of special functions.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
/// Function call arguments may be _consumed_ when the function requires them to be passed by value.
|
||||||
/// All function arguments not in the first position are always passed by value and thus consumed.
|
/// All function arguments not in the first position are always passed by value and thus consumed.
|
||||||
@ -549,100 +583,85 @@ impl Engine {
|
|||||||
.iter()
|
.iter()
|
||||||
.find_map(|&m| {
|
.find_map(|&m| {
|
||||||
m.get_fn(hash_script, pub_only)
|
m.get_fn(hash_script, pub_only)
|
||||||
.map(|f| (f, m.id_raw().clone()))
|
.map(|f| (f, m.id_raw().cloned()))
|
||||||
})
|
})
|
||||||
//.or_else(|| self.global_namespace.get_fn(hash_script, pub_only))
|
//.or_else(|| self.global_namespace.get_fn(hash_script, pub_only))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.global_modules
|
self.global_modules.iter().find_map(|m| {
|
||||||
.iter()
|
m.get_fn(hash_script, false)
|
||||||
.find_map(|m| m.get_fn(hash_script, false))
|
.map(|f| (f, m.id_raw().cloned()))
|
||||||
.map(|f| (f, None))
|
})
|
||||||
})
|
})
|
||||||
//.or_else(|| mods.iter().find_map(|(_, m)| m.get_qualified_fn(hash_script).map(|f| (f, m.id_raw().clone()))))
|
//.or_else(|| mods.iter().find_map(|(_, m)| m.get_qualified_fn(hash_script).map(|f| (f, m.id_raw().clone()))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if func.is_script() {
|
assert!(func.is_script());
|
||||||
let func = func.get_fn_def();
|
|
||||||
|
|
||||||
let scope: &mut Scope = &mut Default::default();
|
let func = func.get_fn_def();
|
||||||
|
|
||||||
// Move captured variables into scope
|
let scope: &mut Scope = &mut Default::default();
|
||||||
#[cfg(not(feature = "no_closure"))]
|
|
||||||
if let Some(captured) = _capture_scope {
|
// Move captured variables into scope
|
||||||
if !func.externals.is_empty() {
|
#[cfg(not(feature = "no_closure"))]
|
||||||
captured
|
if let Some(captured) = _capture_scope {
|
||||||
.into_iter()
|
if !func.externals.is_empty() {
|
||||||
.filter(|(name, _, _)| func.externals.iter().any(|ex| ex == name))
|
captured
|
||||||
.for_each(|(name, value, _)| {
|
.into_iter()
|
||||||
// Consume the scope values.
|
.filter(|(name, _, _)| func.externals.iter().any(|ex| ex == name))
|
||||||
scope.push_dynamic(name, value);
|
.for_each(|(name, value, _)| {
|
||||||
});
|
// Consume the scope values.
|
||||||
}
|
scope.push_dynamic(name, value);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let result = if _is_method {
|
let result = if _is_method {
|
||||||
// Method call of script function - map first argument to `this`
|
// Method call of script function - map first argument to `this`
|
||||||
let (first, rest) = args.split_first_mut().unwrap();
|
let (first, rest) = args.split_first_mut().unwrap();
|
||||||
|
|
||||||
mem::swap(&mut state.source, &mut source);
|
mem::swap(&mut state.source, &mut source);
|
||||||
|
|
||||||
let level = _level + 1;
|
let level = _level + 1;
|
||||||
|
|
||||||
let result = self.call_script_fn(
|
let result = self.call_script_fn(
|
||||||
scope,
|
scope,
|
||||||
mods,
|
|
||||||
state,
|
|
||||||
lib,
|
|
||||||
&mut Some(*first),
|
|
||||||
func,
|
|
||||||
rest,
|
|
||||||
pos,
|
|
||||||
level,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Restore the original source
|
|
||||||
state.source = source;
|
|
||||||
|
|
||||||
result?
|
|
||||||
} else {
|
|
||||||
// Normal call of script function
|
|
||||||
// The first argument is a reference?
|
|
||||||
let mut backup: ArgBackup = Default::default();
|
|
||||||
backup.change_first_arg_to_copy(is_ref, args);
|
|
||||||
|
|
||||||
mem::swap(&mut state.source, &mut source);
|
|
||||||
|
|
||||||
let level = _level + 1;
|
|
||||||
|
|
||||||
let result = self.call_script_fn(
|
|
||||||
scope, mods, state, lib, &mut None, func, args, pos, level,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Restore the original source
|
|
||||||
state.source = source;
|
|
||||||
|
|
||||||
// Restore the original reference
|
|
||||||
backup.restore_first_arg(args);
|
|
||||||
|
|
||||||
result?
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((result, false))
|
|
||||||
} else {
|
|
||||||
// If it is a native function, redirect it
|
|
||||||
self.call_native_fn(
|
|
||||||
mods,
|
mods,
|
||||||
state,
|
state,
|
||||||
lib,
|
lib,
|
||||||
fn_name,
|
&mut Some(*first),
|
||||||
hash_script,
|
func,
|
||||||
args,
|
rest,
|
||||||
is_ref,
|
|
||||||
pub_only,
|
|
||||||
pos,
|
pos,
|
||||||
def_val,
|
level,
|
||||||
)
|
);
|
||||||
}
|
|
||||||
|
// Restore the original source
|
||||||
|
state.source = source;
|
||||||
|
|
||||||
|
result?
|
||||||
|
} else {
|
||||||
|
// Normal call of script function
|
||||||
|
// The first argument is a reference?
|
||||||
|
let mut backup: ArgBackup = Default::default();
|
||||||
|
backup.change_first_arg_to_copy(is_ref, args);
|
||||||
|
|
||||||
|
mem::swap(&mut state.source, &mut source);
|
||||||
|
|
||||||
|
let level = _level + 1;
|
||||||
|
|
||||||
|
let result = self
|
||||||
|
.call_script_fn(scope, mods, state, lib, &mut None, func, args, pos, level);
|
||||||
|
|
||||||
|
// Restore the original source
|
||||||
|
state.source = source;
|
||||||
|
|
||||||
|
// Restore the original reference
|
||||||
|
backup.restore_first_arg(args);
|
||||||
|
|
||||||
|
result?
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((result, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal native function call
|
// Normal native function call
|
||||||
@ -675,7 +694,7 @@ impl Engine {
|
|||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
statements
|
statements
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_fold(().into(), |_, stmt| {
|
.try_fold(Dynamic::UNIT, |_, stmt| {
|
||||||
self.eval_stmt(scope, mods, state, lib, &mut None, stmt, level)
|
self.eval_stmt(scope, mods, state, lib, &mut None, stmt, level)
|
||||||
})
|
})
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -1204,7 +1223,7 @@ impl Engine {
|
|||||||
let new_scope = &mut Default::default();
|
let new_scope = &mut Default::default();
|
||||||
let fn_def = f.get_fn_def().clone();
|
let fn_def = f.get_fn_def().clone();
|
||||||
|
|
||||||
let mut source = module.id_raw().clone();
|
let mut source = module.id_raw().cloned();
|
||||||
mem::swap(&mut state.source, &mut source);
|
mem::swap(&mut state.source, &mut source);
|
||||||
|
|
||||||
let level = level + 1;
|
let level = level + 1;
|
||||||
|
@ -12,6 +12,7 @@ pub trait Func<ARGS, RET> {
|
|||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Create a Rust closure from an [`AST`].
|
/// Create a Rust closure from an [`AST`].
|
||||||
|
///
|
||||||
/// The [`Engine`] and [`AST`] are consumed and basically embedded into the closure.
|
/// The [`Engine`] and [`AST`] are consumed and basically embedded into the closure.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -43,6 +44,7 @@ pub trait Func<ARGS, RET> {
|
|||||||
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output;
|
fn create_from_ast(self, ast: AST, entry_point: &str) -> Self::Output;
|
||||||
|
|
||||||
/// Create a Rust closure from a script.
|
/// Create a Rust closure from a script.
|
||||||
|
///
|
||||||
/// The [`Engine`] is consumed and basically embedded into the closure.
|
/// The [`Engine`] is consumed and basically embedded into the closure.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -10,11 +10,12 @@ use crate::stdlib::{
|
|||||||
iter::empty,
|
iter::empty,
|
||||||
mem,
|
mem,
|
||||||
string::String,
|
string::String,
|
||||||
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use crate::token::is_valid_identifier;
|
use crate::token::is_valid_identifier;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_script_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ImmutableString, Module,
|
calc_script_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ImmutableString, Module,
|
||||||
Position, StaticVec,
|
Position,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
@ -62,14 +63,14 @@ pub struct NativeCallContext<'e, 's, 'a, 'm, 'pm: 'm> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'e, 's, 'a, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized>
|
impl<'e, 's, 'a, 'm, 'pm: 'm, M: AsRef<[&'pm Module]> + ?Sized>
|
||||||
From<(&'e Engine, &'s Option<ImmutableString>, &'a Imports, &'m M)>
|
From<(&'e Engine, Option<&'s ImmutableString>, &'a Imports, &'m M)>
|
||||||
for NativeCallContext<'e, 's, 'a, 'm, 'pm>
|
for NativeCallContext<'e, 's, 'a, 'm, 'pm>
|
||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: (&'e Engine, &'s Option<ImmutableString>, &'a Imports, &'m M)) -> Self {
|
fn from(value: (&'e Engine, Option<&'s ImmutableString>, &'a Imports, &'m M)) -> Self {
|
||||||
Self {
|
Self {
|
||||||
engine: value.0,
|
engine: value.0,
|
||||||
source: value.1.as_ref().map(|s| s.as_str()),
|
source: value.1.map(|s| s.as_str()),
|
||||||
mods: Some(value.2),
|
mods: Some(value.2),
|
||||||
lib: value.3.as_ref(),
|
lib: value.3.as_ref(),
|
||||||
}
|
}
|
||||||
@ -121,14 +122,20 @@ impl<'e, 's, 'a, 'm, 'pm> NativeCallContext<'e, 's, 'a, 'm, 'pm> {
|
|||||||
}
|
}
|
||||||
/// The current [`Engine`].
|
/// The current [`Engine`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn engine(&self) -> &'e Engine {
|
pub fn engine(&self) -> &Engine {
|
||||||
self.engine
|
self.engine
|
||||||
}
|
}
|
||||||
/// The current source.
|
/// The current source.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn source<'z: 's>(&'z self) -> Option<&'s str> {
|
pub fn source(&self) -> Option<&str> {
|
||||||
self.source
|
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<Item = (&str, &Module)> {
|
||||||
|
self.mods.iter().flat_map(|&m| m.iter())
|
||||||
|
}
|
||||||
/// _(INTERNALS)_ The current set of modules imported via `import` statements.
|
/// _(INTERNALS)_ The current set of modules imported via `import` statements.
|
||||||
/// Available under the `internals` feature only.
|
/// Available under the `internals` feature only.
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
@ -137,14 +144,21 @@ impl<'e, 's, 'a, 'm, 'pm> NativeCallContext<'e, 's, 'a, 'm, 'pm> {
|
|||||||
pub fn imports(&self) -> Option<&Imports> {
|
pub fn imports(&self) -> Option<&Imports> {
|
||||||
self.mods
|
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)]
|
#[inline(always)]
|
||||||
pub fn iter_namespaces(&self) -> impl Iterator<Item = &'pm Module> + 'm {
|
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
|
||||||
self.lib.iter().cloned()
|
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.
|
/// Call a function inside the call context.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// All arguments may be _consumed_, meaning that they may be replaced by `()`.
|
/// All arguments may be _consumed_, meaning that they may be replaced by `()`.
|
||||||
/// This is to avoid unnecessarily cloning the arguments.
|
/// This is to avoid unnecessarily cloning the arguments.
|
||||||
@ -224,7 +238,7 @@ pub type FnCallArgs<'a> = [&'a mut Dynamic];
|
|||||||
/// A general function pointer, which may carry additional (i.e. curried) argument values
|
/// A general function pointer, which may carry additional (i.e. curried) argument values
|
||||||
/// to be passed onto a function during a call.
|
/// to be passed onto a function during a call.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FnPtr(ImmutableString, StaticVec<Dynamic>);
|
pub struct FnPtr(ImmutableString, Vec<Dynamic>);
|
||||||
|
|
||||||
impl FnPtr {
|
impl FnPtr {
|
||||||
/// Create a new function pointer.
|
/// Create a new function pointer.
|
||||||
@ -234,10 +248,7 @@ impl FnPtr {
|
|||||||
}
|
}
|
||||||
/// Create a new function pointer without checking its parameters.
|
/// Create a new function pointer without checking its parameters.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn new_unchecked(
|
pub(crate) fn new_unchecked(name: impl Into<ImmutableString>, curry: Vec<Dynamic>) -> Self {
|
||||||
name: impl Into<ImmutableString>,
|
|
||||||
curry: StaticVec<Dynamic>,
|
|
||||||
) -> Self {
|
|
||||||
Self(name.into(), curry)
|
Self(name.into(), curry)
|
||||||
}
|
}
|
||||||
/// Get the name of the function.
|
/// Get the name of the function.
|
||||||
@ -252,7 +263,7 @@ impl FnPtr {
|
|||||||
}
|
}
|
||||||
/// Get the underlying data of the function pointer.
|
/// Get the underlying data of the function pointer.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn take_data(self) -> (ImmutableString, StaticVec<Dynamic>) {
|
pub(crate) fn take_data(self) -> (ImmutableString, Vec<Dynamic>) {
|
||||||
(self.0, self.1)
|
(self.0, self.1)
|
||||||
}
|
}
|
||||||
/// Get the curried arguments.
|
/// Get the curried arguments.
|
||||||
@ -287,7 +298,7 @@ impl FnPtr {
|
|||||||
///
|
///
|
||||||
/// If this function is a script-defined function, it must not be marked private.
|
/// If this function is a script-defined function, it must not be marked private.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
|
||||||
/// This is to avoid unnecessarily cloning the arguments.
|
/// This is to avoid unnecessarily cloning the arguments.
|
||||||
@ -307,9 +318,9 @@ impl FnPtr {
|
|||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.chain(arg_values.iter_mut().map(mem::take))
|
.chain(arg_values.iter_mut().map(mem::take))
|
||||||
.collect::<StaticVec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut args = args_data.iter_mut().collect::<StaticVec<_>>();
|
let mut args = args_data.iter_mut().collect::<Vec<_>>();
|
||||||
|
|
||||||
let is_method = this_ptr.is_some();
|
let is_method = this_ptr.is_some();
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ pub type INT = i32;
|
|||||||
///
|
///
|
||||||
/// If the `f32_float` feature is enabled, this will be [`i32`] instead.
|
/// If the `f32_float` feature is enabled, this will be [`i32`] instead.
|
||||||
///
|
///
|
||||||
/// Not available under the `no_float` feature.
|
/// Not available under `no_float`.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
#[cfg(not(feature = "f32_float"))]
|
#[cfg(not(feature = "f32_float"))]
|
||||||
pub type FLOAT = f64;
|
pub type FLOAT = f64;
|
||||||
@ -114,7 +114,7 @@ pub type FLOAT = f64;
|
|||||||
///
|
///
|
||||||
/// If the `f32_float` feature is not used, this will be `f64` instead.
|
/// If the `f32_float` feature is not used, this will be `f64` instead.
|
||||||
///
|
///
|
||||||
/// Not available under the `no_float` feature.
|
/// Not available under `no_float`.
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
#[cfg(feature = "f32_float")]
|
#[cfg(feature = "f32_float")]
|
||||||
pub type FLOAT = f32;
|
pub type FLOAT = f32;
|
||||||
@ -148,13 +148,13 @@ pub use fn_func::Func;
|
|||||||
|
|
||||||
/// Variable-sized array of [`Dynamic`] values.
|
/// Variable-sized array of [`Dynamic`] values.
|
||||||
///
|
///
|
||||||
/// Not available under the `no_index` feature.
|
/// Not available under `no_index`.
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
pub type Array = stdlib::vec::Vec<Dynamic>;
|
pub type Array = stdlib::vec::Vec<Dynamic>;
|
||||||
|
|
||||||
/// Hash map of [`Dynamic`] values with [`ImmutableString`] keys.
|
/// Hash map of [`Dynamic`] values with [`ImmutableString`] keys.
|
||||||
///
|
///
|
||||||
/// Not available under the `no_object` feature.
|
/// Not available under `no_object`.
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub type Map = stdlib::collections::HashMap<ImmutableString, Dynamic>;
|
pub type Map = stdlib::collections::HashMap<ImmutableString, Dynamic>;
|
||||||
|
|
||||||
|
@ -125,17 +125,15 @@ impl FuncInfo {
|
|||||||
|
|
||||||
/// A module which may contain variables, sub-modules, external Rust functions,
|
/// A module which may contain variables, sub-modules, external Rust functions,
|
||||||
/// and/or script-defined functions.
|
/// and/or script-defined functions.
|
||||||
///
|
|
||||||
/// Not available under the `no_module` feature.
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
/// ID identifying the module.
|
/// ID identifying the module.
|
||||||
id: Option<ImmutableString>,
|
id: Option<ImmutableString>,
|
||||||
/// Sub-modules.
|
/// Sub-modules.
|
||||||
modules: HashMap<ImmutableString, Shared<Module>>,
|
modules: HashMap<ImmutableString, Shared<Module>>,
|
||||||
/// Module variables.
|
/// [`Module`] variables.
|
||||||
variables: HashMap<ImmutableString, Dynamic>,
|
variables: HashMap<ImmutableString, Dynamic>,
|
||||||
/// Flattened collection of all module variables, including those in sub-modules.
|
/// Flattened collection of all [`Module`] variables, including those in sub-modules.
|
||||||
all_variables: HashMap<NonZeroU64, Dynamic, StraightHasherBuilder>,
|
all_variables: HashMap<NonZeroU64, Dynamic, StraightHasherBuilder>,
|
||||||
/// External Rust functions.
|
/// External Rust functions.
|
||||||
functions: HashMap<NonZeroU64, FuncInfo, StraightHasherBuilder>,
|
functions: HashMap<NonZeroU64, FuncInfo, StraightHasherBuilder>,
|
||||||
@ -146,7 +144,7 @@ pub struct Module {
|
|||||||
type_iterators: HashMap<TypeId, IteratorFn>,
|
type_iterators: HashMap<TypeId, IteratorFn>,
|
||||||
/// Flattened collection of iterator functions, including those in sub-modules.
|
/// Flattened collection of iterator functions, including those in sub-modules.
|
||||||
all_type_iterators: HashMap<TypeId, IteratorFn>,
|
all_type_iterators: HashMap<TypeId, IteratorFn>,
|
||||||
/// Is the module indexed?
|
/// Is the [`Module`] indexed?
|
||||||
indexed: bool,
|
indexed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +201,7 @@ impl AsRef<Module> for Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
/// Create a new module.
|
/// Create a new [`Module`].
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -219,7 +217,7 @@ impl Module {
|
|||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new module with a specified capacity for native Rust functions.
|
/// Create a new [`Module`] with a specified capacity for native Rust functions.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -238,7 +236,7 @@ impl Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the ID of the module, if any.
|
/// Get the ID of the [`Module`], if any.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -249,16 +247,28 @@ impl Module {
|
|||||||
/// module.set_id(Some("hello"));
|
/// module.set_id(Some("hello"));
|
||||||
/// assert_eq!(module.id(), Some("hello"));
|
/// assert_eq!(module.id(), Some("hello"));
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
pub fn id(&self) -> Option<&str> {
|
pub fn id(&self) -> Option<&str> {
|
||||||
self.id.as_ref().map(|s| s.as_str())
|
self.id_raw().map(|s| s.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the ID of the module, if any.
|
/// Get the ID of the [`Module`] as an [`ImmutableString`], if any.
|
||||||
pub(crate) fn id_raw(&self) -> &Option<ImmutableString> {
|
///
|
||||||
&self.id
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use rhai::Module;
|
||||||
|
///
|
||||||
|
/// let mut module = Module::new();
|
||||||
|
/// module.set_id(Some("hello"));
|
||||||
|
/// assert_eq!(module.id_raw().map(|s| s.as_str()), Some("hello"));
|
||||||
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn id_raw(&self) -> Option<&ImmutableString> {
|
||||||
|
self.id.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the ID of the module.
|
/// Set the ID of the [`Module`].
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -269,11 +279,12 @@ impl Module {
|
|||||||
/// module.set_id(Some("hello"));
|
/// module.set_id(Some("hello"));
|
||||||
/// assert_eq!(module.id(), Some("hello"));
|
/// assert_eq!(module.id(), Some("hello"));
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
pub fn set_id<S: Into<ImmutableString>>(&mut self, id: Option<S>) {
|
pub fn set_id<S: Into<ImmutableString>>(&mut self, id: Option<S>) {
|
||||||
self.id = id.map(|s| s.into());
|
self.id = id.map(|s| s.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the module empty?
|
/// Is the [`Module`] empty?
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -294,7 +305,7 @@ impl Module {
|
|||||||
&& self.all_type_iterators.is_empty()
|
&& self.all_type_iterators.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is the module indexed?
|
/// Is the [`Module`] indexed?
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -310,11 +321,13 @@ impl Module {
|
|||||||
/// assert!(module.is_indexed());
|
/// assert!(module.is_indexed());
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline(always)]
|
||||||
pub fn is_indexed(&self) -> bool {
|
pub fn is_indexed(&self) -> bool {
|
||||||
self.indexed
|
self.indexed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate signatures for all the functions in the module.
|
/// Generate signatures for all the functions in the [`Module`].
|
||||||
|
#[inline(always)]
|
||||||
pub fn gen_fn_signatures<'a>(&'a self) -> impl Iterator<Item = String> + 'a {
|
pub fn gen_fn_signatures<'a>(&'a self) -> impl Iterator<Item = String> + 'a {
|
||||||
self.functions
|
self.functions
|
||||||
.values()
|
.values()
|
||||||
@ -322,7 +335,7 @@ impl Module {
|
|||||||
.map(FuncInfo::gen_signature)
|
.map(FuncInfo::gen_signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does a variable exist in the module?
|
/// Does a variable exist in the [`Module`]?
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -338,7 +351,7 @@ impl Module {
|
|||||||
self.variables.contains_key(name)
|
self.variables.contains_key(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the value of a module variable.
|
/// Get the value of a [`Module`] variable.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -354,7 +367,7 @@ impl Module {
|
|||||||
self.get_var(name).and_then(Dynamic::try_cast::<T>)
|
self.get_var(name).and_then(Dynamic::try_cast::<T>)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a module variable as a [`Dynamic`].
|
/// Get a [`Module`] variable as a [`Dynamic`].
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -370,7 +383,7 @@ impl Module {
|
|||||||
self.variables.get(name).cloned()
|
self.variables.get(name).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a variable into the module.
|
/// Set a variable into the [`Module`].
|
||||||
///
|
///
|
||||||
/// If there is an existing variable of the same name, it is replaced.
|
/// If there is an existing variable of the same name, it is replaced.
|
||||||
///
|
///
|
||||||
@ -395,9 +408,9 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a reference to a namespace-qualified variable.
|
/// Get a reference to a namespace-qualified variable.
|
||||||
/// Name and Position in `EvalAltResult` are None and must be set afterwards.
|
/// Name and Position in [`EvalAltResult`] are [`None`] and [`NONE`][Position::NONE] and must be set afterwards.
|
||||||
///
|
///
|
||||||
/// The [`NonZeroU64`] hash is calculated by the function [`crate::calc_native_fn_hash`].
|
/// The [`NonZeroU64`] hash is calculated by the function [`calc_native_fn_hash`][crate::calc_native_fn_hash].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_qualified_var(
|
pub(crate) fn get_qualified_var(
|
||||||
&self,
|
&self,
|
||||||
@ -408,7 +421,7 @@ impl Module {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a script-defined function into the module.
|
/// Set a script-defined function into the [`Module`].
|
||||||
///
|
///
|
||||||
/// If there is an existing function of the same name and number of arguments, it is replaced.
|
/// If there is an existing function of the same name and number of arguments, it is replaced.
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
@ -437,7 +450,7 @@ impl Module {
|
|||||||
hash_script
|
hash_script
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a script-defined function in the module based on name and number of parameters.
|
/// Get a script-defined function in the [`Module`] based on name and number of parameters.
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_script_fn(
|
pub fn get_script_fn(
|
||||||
@ -465,10 +478,10 @@ impl Module {
|
|||||||
|
|
||||||
/// Get a mutable reference to the underlying [`HashMap`] of sub-modules.
|
/// Get a mutable reference to the underlying [`HashMap`] of sub-modules.
|
||||||
///
|
///
|
||||||
/// ## Warning
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// By taking a mutable reference, it is assumed that some sub-modules will be modified.
|
/// By taking a mutable reference, it is assumed that some sub-modules will be modified.
|
||||||
/// Thus the module is automatically set to be non-indexed.
|
/// Thus the [`Module`] is automatically set to be non-indexed.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn sub_modules_mut(&mut self) -> &mut HashMap<ImmutableString, Shared<Module>> {
|
pub(crate) fn sub_modules_mut(&mut self) -> &mut HashMap<ImmutableString, Shared<Module>> {
|
||||||
@ -482,7 +495,7 @@ impl Module {
|
|||||||
&mut self.modules
|
&mut self.modules
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does a sub-module exist in the module?
|
/// Does a sub-module exist in the [`Module`]?
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -499,7 +512,7 @@ impl Module {
|
|||||||
self.modules.contains_key(name)
|
self.modules.contains_key(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a sub-module.
|
/// Get a sub-module in the [`Module`].
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -516,7 +529,7 @@ impl Module {
|
|||||||
self.modules.get(name).map(|m| m.as_ref())
|
self.modules.get(name).map(|m| m.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a sub-module into the module.
|
/// Set a sub-module into the [`Module`].
|
||||||
///
|
///
|
||||||
/// If there is an existing sub-module of the same name, it is replaced.
|
/// If there is an existing sub-module of the same name, it is replaced.
|
||||||
///
|
///
|
||||||
@ -541,9 +554,9 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does the particular Rust function exist in the module?
|
/// Does the particular Rust function exist in the [`Module`]?
|
||||||
///
|
///
|
||||||
/// The [`NonZeroU64`] hash is calculated by the function [`crate::calc_native_fn_hash`].
|
/// The [`NonZeroU64`] hash is calculated by the function [`calc_native_fn_hash`][crate::calc_native_fn_hash].
|
||||||
/// It is also returned by the `set_fn_XXX` calls.
|
/// It is also returned by the `set_fn_XXX` calls.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -569,13 +582,19 @@ impl Module {
|
|||||||
|
|
||||||
/// Update the metadata (parameter names/types and return type) of a registered function.
|
/// Update the metadata (parameter names/types and return type) of a registered function.
|
||||||
///
|
///
|
||||||
/// The [`NonZeroU64`] hash is calculated either by the function [`crate::calc_native_fn_hash`] or
|
/// The [`NonZeroU64`] hash is calculated either by the function
|
||||||
/// the function [`crate::calc_script_fn_hash`].
|
/// [`calc_native_fn_hash`][crate::calc_native_fn_hash] or the function
|
||||||
|
/// [`calc_script_fn_hash`][crate::calc_script_fn_hash].
|
||||||
|
///
|
||||||
|
/// ## Parameter Names and Types
|
||||||
///
|
///
|
||||||
/// Each parameter name/type pair should be a single string of the format: `var_name: type`.
|
/// Each parameter name/type pair should be a single string of the format: `var_name: type`.
|
||||||
///
|
///
|
||||||
/// The last entry in the list should be the return type of the function.
|
/// ## Return Type
|
||||||
|
///
|
||||||
|
/// The _last entry_ in the list should be the _return type_ of the function.
|
||||||
/// In other words, the number of entries should be one larger than the number of parameters.
|
/// In other words, the number of entries should be one larger than the number of parameters.
|
||||||
|
#[inline(always)]
|
||||||
pub fn update_fn_metadata<'a>(
|
pub fn update_fn_metadata<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
hash_fn: NonZeroU64,
|
hash_fn: NonZeroU64,
|
||||||
@ -589,8 +608,10 @@ impl Module {
|
|||||||
|
|
||||||
/// Update the namespace of a registered function.
|
/// Update the namespace of a registered function.
|
||||||
///
|
///
|
||||||
/// The [`NonZeroU64`] hash is calculated either by the function [`crate::calc_native_fn_hash`] or
|
/// The [`NonZeroU64`] hash is calculated either by the function
|
||||||
/// the function [`crate::calc_script_fn_hash`].
|
/// [`calc_native_fn_hash`][crate::calc_native_fn_hash] or the function
|
||||||
|
/// [`calc_script_fn_hash`][crate::calc_script_fn_hash].
|
||||||
|
#[inline(always)]
|
||||||
pub fn update_fn_namespace(
|
pub fn update_fn_namespace(
|
||||||
&mut self,
|
&mut self,
|
||||||
hash_fn: NonZeroU64,
|
hash_fn: NonZeroU64,
|
||||||
@ -603,13 +624,14 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function into the module, returning a hash key.
|
/// Set a Rust function into the [`Module`], returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is an existing Rust function of the same hash, it is replaced.
|
/// If there is an existing Rust function of the same hash, it is replaced.
|
||||||
///
|
///
|
||||||
/// ## WARNING - Low Level API
|
/// # WARNING - Low Level API
|
||||||
///
|
///
|
||||||
/// This function is very low level.
|
/// This function is very low level.
|
||||||
|
#[inline]
|
||||||
pub fn set_fn(
|
pub fn set_fn(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -660,7 +682,7 @@ impl Module {
|
|||||||
|
|
||||||
/// Set a Rust function taking a reference to the scripting [`Engine`][crate::Engine],
|
/// Set a Rust function taking a reference to the scripting [`Engine`][crate::Engine],
|
||||||
/// the current set of functions, plus a list of mutable [`Dynamic`] references
|
/// the current set of functions, plus a list of mutable [`Dynamic`] references
|
||||||
/// into the module, returning a hash key.
|
/// into the [`Module`], returning a hash key.
|
||||||
///
|
///
|
||||||
/// Use this to register a built-in function which must reference settings on the scripting
|
/// Use this to register a built-in function which must reference settings on the scripting
|
||||||
/// [`Engine`][crate::Engine] (e.g. to prevent growing an array beyond the allowed maximum size),
|
/// [`Engine`][crate::Engine] (e.g. to prevent growing an array beyond the allowed maximum size),
|
||||||
@ -668,13 +690,13 @@ impl Module {
|
|||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
///
|
///
|
||||||
/// ## WARNING - Low Level API
|
/// # WARNING - Low Level API
|
||||||
///
|
///
|
||||||
/// This function is very low level.
|
/// This function is very low level.
|
||||||
///
|
///
|
||||||
/// A list of [`TypeId`]'s is taken as the argument types.
|
/// A list of [`TypeId`]'s is taken as the argument types.
|
||||||
///
|
///
|
||||||
/// Arguments are simply passed in as a mutable array of [`&mut Dynamic`],
|
/// Arguments are simply passed in as a mutable array of [`&mut Dynamic`][Dynamic],
|
||||||
/// which is guaranteed to contain enough arguments of the correct types.
|
/// which is guaranteed to contain enough arguments of the correct types.
|
||||||
///
|
///
|
||||||
/// The function is assumed to be a _method_, meaning that the first argument should not be consumed.
|
/// The function is assumed to be a _method_, meaning that the first argument should not be consumed.
|
||||||
@ -722,7 +744,7 @@ impl Module {
|
|||||||
///
|
///
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_raw_fn<T: Variant + Clone>(
|
pub fn set_raw_fn<T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -746,7 +768,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking no parameters into the module, returning a hash key.
|
/// Set a Rust function taking no parameters into the [`Module`], returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
///
|
///
|
||||||
@ -763,7 +785,7 @@ impl Module {
|
|||||||
/// let hash = module.set_fn_0("calc", || Ok(42_i64));
|
/// let hash = module.set_fn_0("calc", || Ok(42_i64));
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_0<T: Variant + Clone>(
|
pub fn set_fn_0<T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -781,7 +803,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking one parameter into the module, returning a hash key.
|
/// Set a Rust function taking one parameter into the [`Module`], returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
///
|
///
|
||||||
@ -798,7 +820,7 @@ impl Module {
|
|||||||
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
/// let hash = module.set_fn_1("calc", |x: i64| Ok(x + 1));
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_1<A: Variant + Clone, T: Variant + Clone>(
|
pub fn set_fn_1<A: Variant + Clone, T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -818,7 +840,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking one mutable parameter into the module, returning a hash key.
|
/// Set a Rust function taking one mutable parameter into the [`Module`], returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
///
|
///
|
||||||
@ -837,7 +859,7 @@ impl Module {
|
|||||||
/// );
|
/// );
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_1_mut<A: Variant + Clone, T: Variant + Clone>(
|
pub fn set_fn_1_mut<A: Variant + Clone, T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -877,7 +899,7 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_getter_fn<A: Variant + Clone, T: Variant + Clone>(
|
pub fn set_getter_fn<A: Variant + Clone, T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -890,7 +912,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking two parameters into the module, returning a hash key.
|
/// Set a Rust function taking two parameters into the [`Module`], returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
///
|
///
|
||||||
@ -909,7 +931,7 @@ impl Module {
|
|||||||
/// });
|
/// });
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_2<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
pub fn set_fn_2<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -932,7 +954,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking two parameters (the first one mutable) into the module,
|
/// Set a Rust function taking two parameters (the first one mutable) into the [`Module`],
|
||||||
/// returning a hash key.
|
/// returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
@ -955,7 +977,7 @@ impl Module {
|
|||||||
/// );
|
/// );
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_2_mut<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
pub fn set_fn_2_mut<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -979,7 +1001,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust setter function taking two parameters (the first one mutable) into the module,
|
/// Set a Rust setter function taking two parameters (the first one mutable) into the [`Module`],
|
||||||
/// returning a hash key.
|
/// returning a hash key.
|
||||||
/// This function is automatically exposed to the global namespace.
|
/// This function is automatically exposed to the global namespace.
|
||||||
///
|
///
|
||||||
@ -1002,7 +1024,7 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_setter_fn<A: Variant + Clone, B: Variant + Clone>(
|
pub fn set_setter_fn<A: Variant + Clone, B: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
@ -1015,7 +1037,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust index getter taking two parameters (the first one mutable) into the module,
|
/// Set a Rust index getter taking two parameters (the first one mutable) into the [`Module`],
|
||||||
/// returning a hash key.
|
/// returning a hash key.
|
||||||
/// This function is automatically exposed to the global namespace.
|
/// This function is automatically exposed to the global namespace.
|
||||||
///
|
///
|
||||||
@ -1042,7 +1064,7 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_indexer_get_fn<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
pub fn set_indexer_get_fn<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: impl Fn(&mut A, B) -> Result<T, Box<EvalAltResult>> + SendSync + 'static,
|
func: impl Fn(&mut A, B) -> Result<T, Box<EvalAltResult>> + SendSync + 'static,
|
||||||
@ -1064,7 +1086,7 @@ impl Module {
|
|||||||
self.set_fn_2_mut(crate::engine::FN_IDX_GET, FnNamespace::Global, func)
|
self.set_fn_2_mut(crate::engine::FN_IDX_GET, FnNamespace::Global, func)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking three parameters into the module, returning a hash key.
|
/// Set a Rust function taking three parameters into the [`Module`], returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
///
|
///
|
||||||
@ -1083,7 +1105,7 @@ impl Module {
|
|||||||
/// });
|
/// });
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_3<
|
pub fn set_fn_3<
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
B: Variant + Clone,
|
B: Variant + Clone,
|
||||||
@ -1112,7 +1134,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking three parameters (the first one mutable) into the module,
|
/// Set a Rust function taking three parameters (the first one mutable) into the [`Module`],
|
||||||
/// returning a hash key.
|
/// returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
@ -1135,7 +1157,7 @@ impl Module {
|
|||||||
/// );
|
/// );
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_3_mut<
|
pub fn set_fn_3_mut<
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
B: Variant + Clone,
|
B: Variant + Clone,
|
||||||
@ -1165,7 +1187,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust index setter taking three parameters (the first one mutable) into the module,
|
/// Set a Rust index setter taking three parameters (the first one mutable) into the [`Module`],
|
||||||
/// returning a hash key.
|
/// returning a hash key.
|
||||||
/// This function is automatically exposed to the global namespace.
|
/// This function is automatically exposed to the global namespace.
|
||||||
///
|
///
|
||||||
@ -1193,7 +1215,7 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_indexer_set_fn<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone>(
|
pub fn set_indexer_set_fn<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: impl Fn(&mut A, B, C) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
|
func: impl Fn(&mut A, B, C) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
|
||||||
@ -1264,7 +1286,7 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash_set, true));
|
/// assert!(module.contains_fn(hash_set, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_indexer_get_set_fn<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
pub fn set_indexer_get_set_fn<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
getter: impl Fn(&mut A, B) -> Result<T, Box<EvalAltResult>> + SendSync + 'static,
|
getter: impl Fn(&mut A, B) -> Result<T, Box<EvalAltResult>> + SendSync + 'static,
|
||||||
@ -1276,7 +1298,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking four parameters into the module, returning a hash key.
|
/// Set a Rust function taking four parameters into the [`Module`], returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
///
|
///
|
||||||
@ -1295,7 +1317,7 @@ impl Module {
|
|||||||
/// });
|
/// });
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_4<
|
pub fn set_fn_4<
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
B: Variant + Clone,
|
B: Variant + Clone,
|
||||||
@ -1331,7 +1353,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a Rust function taking four parameters (the first one mutable) into the module,
|
/// Set a Rust function taking four parameters (the first one mutable) into the [`Module`],
|
||||||
/// returning a hash key.
|
/// returning a hash key.
|
||||||
///
|
///
|
||||||
/// If there is a similar existing Rust function, it is replaced.
|
/// If there is a similar existing Rust function, it is replaced.
|
||||||
@ -1354,7 +1376,7 @@ impl Module {
|
|||||||
/// );
|
/// );
|
||||||
/// assert!(module.contains_fn(hash, true));
|
/// assert!(module.contains_fn(hash, true));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
pub fn set_fn_4_mut<
|
pub fn set_fn_4_mut<
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
B: Variant + Clone,
|
B: Variant + Clone,
|
||||||
@ -1393,7 +1415,7 @@ impl Module {
|
|||||||
|
|
||||||
/// Get a Rust function.
|
/// Get a Rust function.
|
||||||
///
|
///
|
||||||
/// The [`NonZeroU64`] hash is calculated by the function [`crate::calc_native_fn_hash`].
|
/// The [`NonZeroU64`] hash is calculated by the function [`calc_native_fn_hash`][crate::calc_native_fn_hash].
|
||||||
/// It is also returned by the `set_fn_XXX` calls.
|
/// It is also returned by the `set_fn_XXX` calls.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_fn(
|
pub(crate) fn get_fn(
|
||||||
@ -1410,9 +1432,10 @@ impl Module {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Does the particular namespace-qualified function exist in the module?
|
/// Does the particular namespace-qualified function exist in the [`Module`]?
|
||||||
///
|
///
|
||||||
/// The [`NonZeroU64`] hash is calculated by the function [`crate::calc_native_fn_hash`] and must match
|
/// The [`NonZeroU64`] hash is calculated by the function
|
||||||
|
/// [`calc_native_fn_hash`][crate::calc_native_fn_hash] and must match
|
||||||
/// the hash calculated by [`build_index`][Module::build_index].
|
/// the hash calculated by [`build_index`][Module::build_index].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn contains_qualified_fn(&self, hash_fn: NonZeroU64) -> bool {
|
pub fn contains_qualified_fn(&self, hash_fn: NonZeroU64) -> bool {
|
||||||
@ -1420,9 +1443,9 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a namespace-qualified function.
|
/// Get a namespace-qualified function.
|
||||||
/// Name and Position in `EvalAltResult` are None and must be set afterwards.
|
|
||||||
///
|
///
|
||||||
/// The [`NonZeroU64`] hash is calculated by the function [`crate::calc_native_fn_hash`] and must match
|
/// The [`NonZeroU64`] hash is calculated by the function
|
||||||
|
/// [`calc_native_fn_hash`][crate::calc_native_fn_hash] and must match
|
||||||
/// the hash calculated by [`build_index`][Module::build_index].
|
/// the hash calculated by [`build_index`][Module::build_index].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn get_qualified_fn(
|
pub(crate) fn get_qualified_fn(
|
||||||
@ -1432,8 +1455,8 @@ impl Module {
|
|||||||
self.all_functions.get(&hash_qualified_fn)
|
self.all_functions.get(&hash_qualified_fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Combine another module into this module.
|
/// Combine another [`Module`] into this [`Module`].
|
||||||
/// The other module is consumed to merge into this module.
|
/// The other [`Module`] is _consumed_ to merge into this [`Module`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn combine(&mut self, other: Self) -> &mut Self {
|
pub fn combine(&mut self, other: Self) -> &mut Self {
|
||||||
self.modules.extend(other.modules.into_iter());
|
self.modules.extend(other.modules.into_iter());
|
||||||
@ -1447,9 +1470,9 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Combine another module into this module.
|
/// Combine another [`Module`] into this [`Module`].
|
||||||
/// The other module is consumed to merge into this module.
|
/// The other [`Module`] is _consumed_ to merge into this [`Module`].
|
||||||
/// Sub-modules are flattened onto the root module, with higher level overriding lower level.
|
/// Sub-modules are flattened onto the root [`Module`], with higher level overriding lower level.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn combine_flatten(&mut self, other: Self) -> &mut Self {
|
pub fn combine_flatten(&mut self, other: Self) -> &mut Self {
|
||||||
other.modules.into_iter().for_each(|(_, m)| {
|
other.modules.into_iter().for_each(|(_, m)| {
|
||||||
@ -1465,8 +1488,8 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Poly-fill this module with another module.
|
/// Polyfill this [`Module`] with another [`Module`].
|
||||||
/// Only items not existing in this module are added.
|
/// Only items not existing in this [`Module`] are added.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn fill_with(&mut self, other: &Self) -> &mut Self {
|
pub fn fill_with(&mut self, other: &Self) -> &mut Self {
|
||||||
other.modules.iter().for_each(|(k, v)| {
|
other.modules.iter().for_each(|(k, v)| {
|
||||||
@ -1492,13 +1515,13 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge another module into this module.
|
/// Merge another [`Module`] into this [`Module`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn merge(&mut self, other: &Self) -> &mut Self {
|
pub fn merge(&mut self, other: &Self) -> &mut Self {
|
||||||
self.merge_filtered(other, &mut |_, _, _, _, _| true)
|
self.merge_filtered(other, &mut |_, _, _, _, _| true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge another module into this module based on a filter predicate.
|
/// Merge another [`Module`] into this [`Module`] based on a filter predicate.
|
||||||
pub(crate) fn merge_filtered(
|
pub(crate) fn merge_filtered(
|
||||||
&mut self,
|
&mut self,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
@ -1584,7 +1607,7 @@ impl Module {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of variables, functions and type iterators in the module.
|
/// Get the number of variables, functions and type iterators in the [`Module`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn count(&self) -> (usize, usize, usize) {
|
pub fn count(&self) -> (usize, usize, usize) {
|
||||||
(
|
(
|
||||||
@ -1594,19 +1617,19 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator to the sub-modules in the module.
|
/// Get an iterator to the sub-modules in the [`Module`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_sub_modules(&self) -> impl Iterator<Item = (&str, Shared<Module>)> {
|
pub fn iter_sub_modules(&self) -> impl Iterator<Item = (&str, Shared<Module>)> {
|
||||||
self.modules.iter().map(|(k, m)| (k.as_str(), m.clone()))
|
self.modules.iter().map(|(k, m)| (k.as_str(), m.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator to the variables in the module.
|
/// Get an iterator to the variables in the [`Module`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_var(&self) -> impl Iterator<Item = (&str, &Dynamic)> {
|
pub fn iter_var(&self) -> impl Iterator<Item = (&str, &Dynamic)> {
|
||||||
self.variables.iter().map(|(k, v)| (k.as_str(), v))
|
self.variables.iter().map(|(k, v)| (k.as_str(), v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator to the functions in the module.
|
/// Get an iterator to the functions in the [`Module`].
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -1614,7 +1637,7 @@ impl Module {
|
|||||||
self.functions.values()
|
self.functions.values()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator over all script-defined functions in the module.
|
/// Get an iterator over all script-defined functions in the [`Module`].
|
||||||
///
|
///
|
||||||
/// Function metadata includes:
|
/// Function metadata includes:
|
||||||
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
||||||
@ -1647,7 +1670,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator over all script-defined functions in the module.
|
/// Get an iterator over all script-defined functions in the [`Module`].
|
||||||
///
|
///
|
||||||
/// Function metadata includes:
|
/// Function metadata includes:
|
||||||
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
||||||
@ -1671,7 +1694,7 @@ impl Module {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator over all script-defined functions in the module.
|
/// Get an iterator over all script-defined functions in the [`Module`].
|
||||||
///
|
///
|
||||||
/// Function metadata includes:
|
/// Function metadata includes:
|
||||||
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
|
||||||
@ -1689,11 +1712,11 @@ impl Module {
|
|||||||
self.iter_script_fn()
|
self.iter_script_fn()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new module by evaluating an [`AST`][crate::AST].
|
/// Create a new [`Module`] by evaluating an [`AST`][crate::AST].
|
||||||
///
|
///
|
||||||
/// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions
|
/// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions
|
||||||
/// to cross-call each other. Functions in the global namespace, plus all functions
|
/// to cross-call each other. Functions in the global namespace, plus all functions
|
||||||
/// defined in the module, are _merged_ into a _unified_ namespace before each call.
|
/// defined in the [`Module`], are _merged_ into a _unified_ namespace before each call.
|
||||||
/// Therefore, all functions will be found.
|
/// Therefore, all functions will be found.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -1766,10 +1789,10 @@ impl Module {
|
|||||||
Ok(module)
|
Ok(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scan through all the sub-modules in the module and build a hash index of all
|
/// Scan through all the sub-modules in the [`Module`] and build a hash index of all
|
||||||
/// variables and functions as one flattened namespace.
|
/// variables and functions as one flattened namespace.
|
||||||
///
|
///
|
||||||
/// If the module is already indexed, this method has no effect.
|
/// If the [`Module`] is already indexed, this method has no effect.
|
||||||
pub fn build_index(&mut self) -> &mut Self {
|
pub fn build_index(&mut self) -> &mut Self {
|
||||||
// Collect a particular module.
|
// Collect a particular module.
|
||||||
fn index_module<'a>(
|
fn index_module<'a>(
|
||||||
@ -1887,14 +1910,14 @@ impl Module {
|
|||||||
self.type_iterators.contains_key(&id)
|
self.type_iterators.contains_key(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a type iterator into the module.
|
/// Set a type iterator into the [`Module`].
|
||||||
pub fn set_iter(&mut self, typ: TypeId, func: IteratorFn) -> &mut Self {
|
pub fn set_iter(&mut self, typ: TypeId, func: IteratorFn) -> &mut Self {
|
||||||
self.type_iterators.insert(typ, func);
|
self.type_iterators.insert(typ, func);
|
||||||
self.indexed = false;
|
self.indexed = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a type iterator into the module.
|
/// Set a type iterator into the [`Module`].
|
||||||
pub fn set_iterable<T>(&mut self) -> &mut Self
|
pub fn set_iterable<T>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
T: Variant + Clone + IntoIterator,
|
T: Variant + Clone + IntoIterator,
|
||||||
@ -1905,7 +1928,7 @@ impl Module {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set an iterator type into the module as a type iterator.
|
/// Set an iterator type into the [`Module`] as a type iterator.
|
||||||
pub fn set_iterator<T>(&mut self) -> &mut Self
|
pub fn set_iterator<T>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
T: Variant + Clone + Iterator,
|
T: Variant + Clone + Iterator,
|
||||||
@ -1935,7 +1958,7 @@ impl Module {
|
|||||||
/// A [`StaticVec`] is used because most namespace-qualified access contains only one level,
|
/// A [`StaticVec`] is used because most namespace-qualified access contains only one level,
|
||||||
/// and it is wasteful to always allocate a [`Vec`] with one element.
|
/// and it is wasteful to always allocate a [`Vec`] with one element.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
||||||
@ -2019,10 +2042,9 @@ impl NamespaceRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Re-export module resolver trait.
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub use resolvers::ModuleResolver;
|
pub use resolvers::ModuleResolver;
|
||||||
|
|
||||||
/// Re-export module resolvers.
|
/// Module containing all built-in [module resolvers][ModuleResolver].
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub mod resolvers;
|
pub mod resolvers;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::stdlib::{boxed::Box, ops::AddAssign, vec::Vec};
|
use crate::stdlib::{boxed::Box, ops::AddAssign, vec::Vec};
|
||||||
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
||||||
|
|
||||||
/// Module resolution service that holds a collection of module resolves,
|
/// [Module] resolution service that holds a collection of [module][Module] resolves,
|
||||||
/// to be searched in sequential order.
|
/// to be searched in sequential order.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -42,13 +42,13 @@ impl ModuleResolversCollection {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
/// Append a module resolver to the end.
|
/// Append a [module resolver][ModuleResolver] to the end.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push(&mut self, resolver: impl ModuleResolver + 'static) -> &mut Self {
|
pub fn push(&mut self, resolver: impl ModuleResolver + 'static) -> &mut Self {
|
||||||
self.0.push(Box::new(resolver));
|
self.0.push(Box::new(resolver));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Insert a module resolver to an offset index.
|
/// Insert a [module resolver][ModuleResolver] to an offset index.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
@ -58,12 +58,12 @@ impl ModuleResolversCollection {
|
|||||||
self.0.insert(index, Box::new(resolver));
|
self.0.insert(index, Box::new(resolver));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/// Remove the last module resolver from the end, if any.
|
/// Remove the last [module resolver][ModuleResolver] from the end, if any.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn pop(&mut self) -> Option<Box<dyn ModuleResolver>> {
|
pub fn pop(&mut self) -> Option<Box<dyn ModuleResolver>> {
|
||||||
self.0.pop()
|
self.0.pop()
|
||||||
}
|
}
|
||||||
/// Remove a module resolver at an offset index.
|
/// Remove a [module resolver][ModuleResolver] at an offset index.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
@ -72,17 +72,17 @@ impl ModuleResolversCollection {
|
|||||||
pub fn remove(&mut self, index: usize) -> Box<dyn ModuleResolver> {
|
pub fn remove(&mut self, index: usize) -> Box<dyn ModuleResolver> {
|
||||||
self.0.remove(index)
|
self.0.remove(index)
|
||||||
}
|
}
|
||||||
/// Get an iterator of all the module resolvers.
|
/// Get an iterator of all the [module resolvers][ModuleResolver].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &dyn ModuleResolver> {
|
pub fn iter(&self) -> impl Iterator<Item = &dyn ModuleResolver> {
|
||||||
self.0.iter().map(|v| v.as_ref())
|
self.0.iter().map(|v| v.as_ref())
|
||||||
}
|
}
|
||||||
/// Get a mutable iterator of all the modules.
|
/// Get a mutable iterator of all the [module resolvers][ModuleResolver].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn into_iter(self) -> impl Iterator<Item = Box<dyn ModuleResolver>> {
|
pub fn into_iter(self) -> impl Iterator<Item = Box<dyn ModuleResolver>> {
|
||||||
self.0.into_iter()
|
self.0.into_iter()
|
||||||
}
|
}
|
||||||
/// Remove all module resolvers.
|
/// Remove all [module resolvers][ModuleResolver].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear(&mut self) -> &mut Self {
|
pub fn clear(&mut self) -> &mut Self {
|
||||||
self.0.clear();
|
self.0.clear();
|
||||||
@ -93,7 +93,7 @@ impl ModuleResolversCollection {
|
|||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.is_empty()
|
self.0.is_empty()
|
||||||
}
|
}
|
||||||
/// Get the number of module resolvers in this [`ModuleResolversCollection`].
|
/// Get the number of [module resolvers][ModuleResolver] in this [`ModuleResolversCollection`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.len()
|
self.0.len()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::stdlib::boxed::Box;
|
use crate::stdlib::boxed::Box;
|
||||||
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
||||||
|
|
||||||
/// Empty/disabled module resolution service that acts as a dummy.
|
/// Empty/disabled [module][Module] resolution service that acts as a dummy.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -7,21 +7,15 @@ use crate::stdlib::{
|
|||||||
};
|
};
|
||||||
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
||||||
|
|
||||||
/// Module resolution service that loads module script files from the file system.
|
/// [Module] resolution service that loads [module][Module] script files from the file system.
|
||||||
///
|
///
|
||||||
/// Script files are cached so they are are not reloaded and recompiled in subsequent requests.
|
/// Script files are cached so they are are not reloaded and recompiled in subsequent requests.
|
||||||
///
|
///
|
||||||
/// The [`new_with_path`][FileModuleResolver::new_with_path] and
|
|
||||||
/// [`new_with_path_and_extension`][FileModuleResolver::new_with_path_and_extension] constructor functions
|
|
||||||
/// allow specification of a base directory with module path used as a relative path offset
|
|
||||||
/// to the base directory. The script file is then forced to be in a specified extension
|
|
||||||
/// (default `.rhai`).
|
|
||||||
///
|
|
||||||
/// # Function Namespace
|
/// # Function Namespace
|
||||||
///
|
///
|
||||||
/// When a function within a script file module is loaded, all functions in the _global_ namespace
|
/// When a function within a script file module is called, all functions in the _global_ namespace
|
||||||
/// plus all those defined within the same module are _merged_ into a _unified_ namespace before
|
/// plus all those defined within the same module are _merged_ into a _unified_ namespace before
|
||||||
/// the call. Therefore, functions in a module script can cross-call each other.
|
/// the call. Therefore, functions in a module script can always cross-call each other.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -58,6 +52,8 @@ impl Default for FileModuleResolver {
|
|||||||
impl FileModuleResolver {
|
impl FileModuleResolver {
|
||||||
/// Create a new [`FileModuleResolver`] with a specific base path.
|
/// Create a new [`FileModuleResolver`] with a specific base path.
|
||||||
///
|
///
|
||||||
|
/// The default extension is `.rhai`.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -78,8 +74,6 @@ impl FileModuleResolver {
|
|||||||
|
|
||||||
/// Create a new [`FileModuleResolver`] with a specific base path and file extension.
|
/// Create a new [`FileModuleResolver`] with a specific base path and file extension.
|
||||||
///
|
///
|
||||||
/// The default extension is `.rhai`.
|
|
||||||
///
|
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -107,6 +101,8 @@ impl FileModuleResolver {
|
|||||||
|
|
||||||
/// Create a new [`FileModuleResolver`] with the current directory as base path.
|
/// Create a new [`FileModuleResolver`] with the current directory as base path.
|
||||||
///
|
///
|
||||||
|
/// The default extension is `.rhai`.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -159,7 +155,9 @@ impl FileModuleResolver {
|
|||||||
self.cache.write().unwrap().clear();
|
self.cache.write().unwrap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Empty the internal cache.
|
/// Remove the specified path from internal cache.
|
||||||
|
///
|
||||||
|
/// The next time this path is resolved, the script file will be loaded once again.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear_cache_for_path(&mut self, path: impl AsRef<Path>) -> Option<Shared<Module>> {
|
pub fn clear_cache_for_path(&mut self, path: impl AsRef<Path>) -> Option<Shared<Module>> {
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
@ -190,52 +188,43 @@ impl ModuleResolver for FileModuleResolver {
|
|||||||
file_path.push(path);
|
file_path.push(path);
|
||||||
file_path.set_extension(&self.extension); // Force extension
|
file_path.set_extension(&self.extension); // Force extension
|
||||||
|
|
||||||
let scope = Default::default();
|
|
||||||
|
|
||||||
// See if it is cached
|
// See if it is cached
|
||||||
let mut module: Option<Shared<Module>> = None;
|
{
|
||||||
|
|
||||||
let mut module_ref = {
|
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
let c = self.cache.borrow();
|
let c = self.cache.borrow();
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
let c = self.cache.read().unwrap();
|
let c = self.cache.read().unwrap();
|
||||||
|
|
||||||
if let Some(module) = c.get(&file_path) {
|
if let Some(module) = c.get(&file_path) {
|
||||||
Some(module.clone())
|
return Ok(module.clone());
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if module_ref.is_none() {
|
|
||||||
// Load the script file and compile it
|
|
||||||
let ast = engine
|
|
||||||
.compile_file(file_path.clone())
|
|
||||||
.map_err(|err| match *err {
|
|
||||||
EvalAltResult::ErrorSystem(_, err) if err.is::<IoError>() => {
|
|
||||||
Box::new(EvalAltResult::ErrorModuleNotFound(path.to_string(), pos))
|
|
||||||
}
|
|
||||||
_ => Box::new(EvalAltResult::ErrorInModule(path.to_string(), err, pos)),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let mut m = Module::eval_ast_as_new(scope, &ast, engine).map_err(|err| {
|
|
||||||
Box::new(EvalAltResult::ErrorInModule(path.to_string(), err, pos))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
m.set_id(Some(path));
|
|
||||||
module = Some(m.into());
|
|
||||||
module_ref = module.clone();
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(module) = module {
|
|
||||||
// Put it into the cache
|
|
||||||
#[cfg(not(feature = "sync"))]
|
|
||||||
self.cache.borrow_mut().insert(file_path, module);
|
|
||||||
#[cfg(feature = "sync")]
|
|
||||||
self.cache.write().unwrap().insert(file_path, module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(module_ref.unwrap())
|
// Load the script file and compile it
|
||||||
|
let scope = Default::default();
|
||||||
|
|
||||||
|
let mut ast = engine
|
||||||
|
.compile_file(file_path.clone())
|
||||||
|
.map_err(|err| match *err {
|
||||||
|
EvalAltResult::ErrorSystem(_, err) if err.is::<IoError>() => {
|
||||||
|
Box::new(EvalAltResult::ErrorModuleNotFound(path.to_string(), pos))
|
||||||
|
}
|
||||||
|
_ => Box::new(EvalAltResult::ErrorInModule(path.to_string(), err, pos)),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
ast.set_source(Some(path));
|
||||||
|
|
||||||
|
// Make a module from the AST
|
||||||
|
let m: Shared<Module> = Module::eval_ast_as_new(scope, &ast, engine)
|
||||||
|
.map_err(|err| Box::new(EvalAltResult::ErrorInModule(path.to_string(), err, pos)))?
|
||||||
|
.into();
|
||||||
|
|
||||||
|
// Put it into the cache
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
self.cache.borrow_mut().insert(file_path, m.clone());
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
self.cache.write().unwrap().insert(file_path, m.clone());
|
||||||
|
|
||||||
|
Ok(m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::stdlib::{boxed::Box, collections::HashMap, ops::AddAssign, string::String};
|
use crate::stdlib::{boxed::Box, collections::HashMap, ops::AddAssign, string::String};
|
||||||
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
use crate::{Engine, EvalAltResult, Module, ModuleResolver, Position, Shared};
|
||||||
|
|
||||||
/// Module resolution service that serves modules added into it.
|
/// [Module] resolution service that serves [modules][Module] added into it.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -42,13 +42,13 @@ impl StaticModuleResolver {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
/// Add a module keyed by its path.
|
/// Add a [module][Module] keyed by its path.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn insert(&mut self, path: impl Into<String>, mut module: Module) {
|
pub fn insert(&mut self, path: impl Into<String>, mut module: Module) {
|
||||||
module.build_index();
|
module.build_index();
|
||||||
self.0.insert(path.into(), module.into());
|
self.0.insert(path.into(), module.into());
|
||||||
}
|
}
|
||||||
/// Remove a module given its path.
|
/// Remove a [module][Module] given its path.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn remove(&mut self, path: &str) -> Option<Shared<Module>> {
|
pub fn remove(&mut self, path: &str) -> Option<Shared<Module>> {
|
||||||
self.0.remove(path)
|
self.0.remove(path)
|
||||||
@ -58,12 +58,12 @@ impl StaticModuleResolver {
|
|||||||
pub fn contains_path(&self, path: &str) -> bool {
|
pub fn contains_path(&self, path: &str) -> bool {
|
||||||
self.0.contains_key(path)
|
self.0.contains_key(path)
|
||||||
}
|
}
|
||||||
/// Get an iterator of all the modules.
|
/// Get an iterator of all the [modules][Module].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter(&self) -> impl Iterator<Item = (&str, &Shared<Module>)> {
|
pub fn iter(&self) -> impl Iterator<Item = (&str, &Shared<Module>)> {
|
||||||
self.0.iter().map(|(k, v)| (k.as_str(), v))
|
self.0.iter().map(|(k, v)| (k.as_str(), v))
|
||||||
}
|
}
|
||||||
/// Get a mutable iterator of all the modules.
|
/// Get a mutable iterator of all the [modules][Module].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&str, &mut Shared<Module>)> {
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&str, &mut Shared<Module>)> {
|
||||||
self.0.iter_mut().map(|(k, v)| (k.as_str(), v))
|
self.0.iter_mut().map(|(k, v)| (k.as_str(), v))
|
||||||
@ -73,17 +73,17 @@ impl StaticModuleResolver {
|
|||||||
pub fn into_iter(self) -> impl Iterator<Item = (String, Shared<Module>)> {
|
pub fn into_iter(self) -> impl Iterator<Item = (String, Shared<Module>)> {
|
||||||
self.0.into_iter()
|
self.0.into_iter()
|
||||||
}
|
}
|
||||||
/// Get an iterator of all the module paths.
|
/// Get an iterator of all the [module][Module] paths.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn paths(&self) -> impl Iterator<Item = &str> {
|
pub fn paths(&self) -> impl Iterator<Item = &str> {
|
||||||
self.0.keys().map(String::as_str)
|
self.0.keys().map(String::as_str)
|
||||||
}
|
}
|
||||||
/// Get an iterator of all the modules.
|
/// Get an iterator of all the [modules][Module].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn values(&self) -> impl Iterator<Item = &Shared<Module>> {
|
pub fn values(&self) -> impl Iterator<Item = &Shared<Module>> {
|
||||||
self.0.values().map(|m| m)
|
self.0.values().map(|m| m)
|
||||||
}
|
}
|
||||||
/// Remove all modules.
|
/// Remove all [modules][Module].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.0.clear();
|
self.0.clear();
|
||||||
@ -93,7 +93,7 @@ impl StaticModuleResolver {
|
|||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.0.is_empty()
|
self.0.is_empty()
|
||||||
}
|
}
|
||||||
/// Get the number of modules in this [`StaticModuleResolver`].
|
/// Get the number of [modules][Module] in this [`StaticModuleResolver`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.0.len()
|
self.0.len()
|
||||||
|
@ -19,8 +19,6 @@ use crate::utils::get_hasher;
|
|||||||
use crate::{calc_native_fn_hash, Dynamic, Engine, Module, Position, Scope, StaticVec, AST};
|
use crate::{calc_native_fn_hash, Dynamic, Engine, Module, Position, Scope, StaticVec, AST};
|
||||||
|
|
||||||
/// Level of optimization performed.
|
/// Level of optimization performed.
|
||||||
///
|
|
||||||
/// Not available under the `no_optimize` feature.
|
|
||||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
||||||
pub enum OptimizationLevel {
|
pub enum OptimizationLevel {
|
||||||
/// No optimization performed.
|
/// No optimization performed.
|
||||||
|
@ -214,6 +214,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"map".to_string(),
|
"map".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -245,6 +246,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"filter".to_string(),
|
"filter".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -278,6 +280,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"index_of".to_string(),
|
"index_of".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -311,6 +314,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"some".to_string(),
|
"some".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -344,6 +348,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"all".to_string(),
|
"all".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -379,6 +384,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"reduce".to_string(),
|
"reduce".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -397,6 +403,7 @@ mod array_functions {
|
|||||||
let mut result = initial.call_dynamic(ctx, None, []).map_err(|err| {
|
let mut result = initial.call_dynamic(ctx, None, []).map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"reduce".to_string(),
|
"reduce".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -416,6 +423,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"reduce".to_string(),
|
"reduce".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -446,6 +454,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"reduce_rev".to_string(),
|
"reduce_rev".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -464,6 +473,7 @@ mod array_functions {
|
|||||||
let mut result = initial.call_dynamic(ctx, None, []).map_err(|err| {
|
let mut result = initial.call_dynamic(ctx, None, []).map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"reduce_rev".to_string(),
|
"reduce_rev".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -483,6 +493,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"reduce_rev".to_string(),
|
"reduce_rev".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -553,6 +564,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"drain".to_string(),
|
"drain".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
@ -612,6 +624,7 @@ mod array_functions {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
||||||
"retain".to_string(),
|
"retain".to_string(),
|
||||||
|
ctx.source().unwrap_or("").to_string(),
|
||||||
err,
|
err,
|
||||||
Position::NONE,
|
Position::NONE,
|
||||||
))
|
))
|
||||||
|
@ -41,9 +41,9 @@ pub trait Package {
|
|||||||
|
|
||||||
/// Retrieve the generic package library from this package.
|
/// Retrieve the generic package library from this package.
|
||||||
///
|
///
|
||||||
/// ## Deprecated
|
/// # Deprecated
|
||||||
///
|
///
|
||||||
/// Use `as_shared_module` instead.
|
/// Use [`as_shared_module`][Package::as_shared_module] instead.
|
||||||
#[deprecated = "use `as_shared_module` instead"]
|
#[deprecated = "use `as_shared_module` instead"]
|
||||||
fn get(&self) -> Shared<Module> {
|
fn get(&self) -> Shared<Module> {
|
||||||
self.as_shared_module()
|
self.as_shared_module()
|
||||||
|
@ -11,7 +11,7 @@ use crate::{EvalAltResult, Position};
|
|||||||
/// _(INTERNALS)_ Error encountered when tokenizing the script text.
|
/// _(INTERNALS)_ Error encountered when tokenizing the script text.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
||||||
|
@ -173,11 +173,9 @@ impl<'e> ParseState<'e> {
|
|||||||
) -> ImmutableString {
|
) -> ImmutableString {
|
||||||
#[allow(clippy::map_entry)]
|
#[allow(clippy::map_entry)]
|
||||||
if !self.strings.contains_key(text.as_ref()) {
|
if !self.strings.contains_key(text.as_ref()) {
|
||||||
let value: ImmutableString = text.into();
|
let value = text.into();
|
||||||
let result = value.clone();
|
self.strings.insert(value.clone().into(), value.clone());
|
||||||
let key = value.to_string();
|
value
|
||||||
self.strings.insert(key, value);
|
|
||||||
result
|
|
||||||
} else {
|
} else {
|
||||||
self.strings.get(text.as_ref()).unwrap().clone()
|
self.strings.get(text.as_ref()).unwrap().clone()
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ pub enum EvalAltResult {
|
|||||||
/// Call to an unknown function. Wrapped value is the function signature.
|
/// Call to an unknown function. Wrapped value is the function signature.
|
||||||
ErrorFunctionNotFound(String, Position),
|
ErrorFunctionNotFound(String, Position),
|
||||||
/// An error has occurred inside a called function.
|
/// An error has occurred inside a called function.
|
||||||
/// Wrapped values are the function name and the interior error.
|
/// Wrapped values are the function name, function source, and the interior error.
|
||||||
ErrorInFunctionCall(String, Box<EvalAltResult>, Position),
|
ErrorInFunctionCall(String, String, Box<EvalAltResult>, Position),
|
||||||
/// Usage of an unknown [module][crate::Module]. Wrapped value is the [module][crate::Module] name.
|
/// Usage of an unknown [module][crate::Module]. Wrapped value is the [module][crate::Module] name.
|
||||||
ErrorModuleNotFound(String, Position),
|
ErrorModuleNotFound(String, Position),
|
||||||
/// An error has occurred while loading a [module][crate::Module].
|
/// An error has occurred while loading a [module][crate::Module].
|
||||||
@ -98,7 +98,7 @@ impl EvalAltResult {
|
|||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
Self::ErrorSystem(_, s) => s.description(),
|
Self::ErrorSystem(_, s) => s.description(),
|
||||||
Self::ErrorParsing(p, _) => p.desc(),
|
Self::ErrorParsing(p, _) => p.desc(),
|
||||||
Self::ErrorInFunctionCall(_, _, _) => "Error in called function",
|
Self::ErrorInFunctionCall(_,_, _, _) => "Error in called function",
|
||||||
Self::ErrorInModule(_, _, _) => "Error in module",
|
Self::ErrorInModule(_, _, _) => "Error in module",
|
||||||
Self::ErrorFunctionNotFound(_, _) => "Function not found",
|
Self::ErrorFunctionNotFound(_, _) => "Function not found",
|
||||||
Self::ErrorUnboundThis(_) => "'this' is not bound",
|
Self::ErrorUnboundThis(_) => "'this' is not bound",
|
||||||
@ -152,12 +152,19 @@ impl fmt::Display for EvalAltResult {
|
|||||||
Self::ErrorParsing(p, _) => write!(f, "Syntax error: {}", p)?,
|
Self::ErrorParsing(p, _) => write!(f, "Syntax error: {}", p)?,
|
||||||
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
Self::ErrorInFunctionCall(s, err, _) if crate::engine::is_anonymous_fn(s) => {
|
Self::ErrorInFunctionCall(s, src, err, _) if crate::engine::is_anonymous_fn(s) => {
|
||||||
write!(f, "Error in call to closure: {}", err)?
|
write!(f, "{}, in call to closure", err)?;
|
||||||
|
if !src.is_empty() {
|
||||||
|
write!(f, " @ '{}'", src)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Self::ErrorInFunctionCall(s, err, _) => {
|
Self::ErrorInFunctionCall(s, src, err, _) => {
|
||||||
write!(f, "Error in call to function '{}': {}", s, err)?
|
write!(f, "{}, in call to function {}", err, s)?;
|
||||||
|
if !src.is_empty() {
|
||||||
|
write!(f, " @ '{}'", src)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::ErrorInModule(s, err, _) if s.is_empty() => {
|
Self::ErrorInModule(s, err, _) if s.is_empty() => {
|
||||||
write!(f, "Error in module: {}", err)?
|
write!(f, "Error in module: {}", err)?
|
||||||
}
|
}
|
||||||
@ -165,8 +172,9 @@ impl fmt::Display for EvalAltResult {
|
|||||||
|
|
||||||
Self::ErrorFunctionNotFound(s, _)
|
Self::ErrorFunctionNotFound(s, _)
|
||||||
| Self::ErrorVariableNotFound(s, _)
|
| Self::ErrorVariableNotFound(s, _)
|
||||||
| Self::ErrorDataRace(s, _)
|
| Self::ErrorDataRace(s, _) => write!(f, "{}: {}", desc, s)?,
|
||||||
| Self::ErrorModuleNotFound(s, _) => write!(f, "{}: '{}'", desc, s)?,
|
|
||||||
|
Self::ErrorModuleNotFound(s, _) => write!(f, "{}: '{}'", desc, s)?,
|
||||||
|
|
||||||
Self::ErrorDotExpr(s, _) if !s.is_empty() => write!(f, "{}", s)?,
|
Self::ErrorDotExpr(s, _) if !s.is_empty() => write!(f, "{}", s)?,
|
||||||
|
|
||||||
@ -187,9 +195,7 @@ impl fmt::Display for EvalAltResult {
|
|||||||
Self::ErrorRuntime(d, _) if d.is::<()>() => f.write_str(desc)?,
|
Self::ErrorRuntime(d, _) if d.is::<()>() => f.write_str(desc)?,
|
||||||
Self::ErrorRuntime(d, _) => write!(f, "{}: {}", desc, d)?,
|
Self::ErrorRuntime(d, _) => write!(f, "{}: {}", desc, d)?,
|
||||||
|
|
||||||
Self::ErrorAssignmentToConstant(s, _) => {
|
Self::ErrorAssignmentToConstant(s, _) => write!(f, "Cannot assign to constant {}", s)?,
|
||||||
write!(f, "Cannot assign to constant '{}'", s)?
|
|
||||||
}
|
|
||||||
Self::ErrorMismatchOutputType(s, r, _) => {
|
Self::ErrorMismatchOutputType(s, r, _) => {
|
||||||
write!(f, "Output type is incorrect: {} (expecting {})", r, s)?
|
write!(f, "Output type is incorrect: {} (expecting {})", r, s)?
|
||||||
}
|
}
|
||||||
@ -276,7 +282,7 @@ impl EvalAltResult {
|
|||||||
Self::ErrorParsing(_, _) => false,
|
Self::ErrorParsing(_, _) => false,
|
||||||
|
|
||||||
Self::ErrorFunctionNotFound(_, _)
|
Self::ErrorFunctionNotFound(_, _)
|
||||||
| Self::ErrorInFunctionCall(_, _, _)
|
| Self::ErrorInFunctionCall(_, _, _, _)
|
||||||
| Self::ErrorInModule(_, _, _)
|
| Self::ErrorInModule(_, _, _)
|
||||||
| Self::ErrorUnboundThis(_)
|
| Self::ErrorUnboundThis(_)
|
||||||
| Self::ErrorMismatchDataType(_, _, _)
|
| Self::ErrorMismatchDataType(_, _, _)
|
||||||
@ -334,7 +340,7 @@ impl EvalAltResult {
|
|||||||
|
|
||||||
Self::ErrorParsing(_, pos)
|
Self::ErrorParsing(_, pos)
|
||||||
| Self::ErrorFunctionNotFound(_, pos)
|
| Self::ErrorFunctionNotFound(_, pos)
|
||||||
| Self::ErrorInFunctionCall(_, _, pos)
|
| Self::ErrorInFunctionCall(_, _, _, pos)
|
||||||
| Self::ErrorInModule(_, _, pos)
|
| Self::ErrorInModule(_, _, pos)
|
||||||
| Self::ErrorUnboundThis(pos)
|
| Self::ErrorUnboundThis(pos)
|
||||||
| Self::ErrorMismatchDataType(_, _, pos)
|
| Self::ErrorMismatchDataType(_, _, pos)
|
||||||
@ -367,7 +373,7 @@ impl EvalAltResult {
|
|||||||
|
|
||||||
Self::ErrorParsing(_, pos)
|
Self::ErrorParsing(_, pos)
|
||||||
| Self::ErrorFunctionNotFound(_, pos)
|
| Self::ErrorFunctionNotFound(_, pos)
|
||||||
| Self::ErrorInFunctionCall(_, _, pos)
|
| Self::ErrorInFunctionCall(_, _, _, pos)
|
||||||
| Self::ErrorInModule(_, _, pos)
|
| Self::ErrorInModule(_, _, pos)
|
||||||
| Self::ErrorUnboundThis(pos)
|
| Self::ErrorUnboundThis(pos)
|
||||||
| Self::ErrorMismatchDataType(_, _, pos)
|
| Self::ErrorMismatchDataType(_, _, pos)
|
||||||
|
@ -445,7 +445,7 @@ impl<'a> Scope<'a> {
|
|||||||
/// let mut my_scope = Scope::new();
|
/// let mut my_scope = Scope::new();
|
||||||
///
|
///
|
||||||
/// my_scope.push("x", 42_i64);
|
/// my_scope.push("x", 42_i64);
|
||||||
/// my_scope.push_constant("foo", "hello".to_string());
|
/// my_scope.push_constant("foo", "hello");
|
||||||
///
|
///
|
||||||
/// let mut iter = my_scope.iter();
|
/// let mut iter = my_scope.iter();
|
||||||
///
|
///
|
||||||
|
@ -64,7 +64,7 @@ impl Expression<'_> {
|
|||||||
impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_, '_> {
|
impl EvalContext<'_, '_, '_, '_, '_, '_, '_, '_, '_> {
|
||||||
/// Evaluate an [expression tree][Expression].
|
/// Evaluate an [expression tree][Expression].
|
||||||
///
|
///
|
||||||
/// ## WARNING - Low Level API
|
/// # WARNING - Low Level API
|
||||||
///
|
///
|
||||||
/// This function is very low level. It evaluates an expression from an [`AST`][crate::AST].
|
/// This function is very low level. It evaluates an expression from an [`AST`][crate::AST].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -210,7 +210,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Register a custom syntax with the [`Engine`].
|
/// Register a custom syntax with the [`Engine`].
|
||||||
///
|
///
|
||||||
/// ## WARNING - Low Level API
|
/// # WARNING - Low Level API
|
||||||
///
|
///
|
||||||
/// This function is very low level.
|
/// This function is very low level.
|
||||||
///
|
///
|
||||||
|
10
src/token.rs
10
src/token.rs
@ -149,7 +149,7 @@ impl fmt::Debug for Position {
|
|||||||
/// _(INTERNALS)_ A Rhai language token.
|
/// _(INTERNALS)_ A Rhai language token.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -741,7 +741,7 @@ impl From<Token> for String {
|
|||||||
/// _(INTERNALS)_ State of the tokenizer.
|
/// _(INTERNALS)_ State of the tokenizer.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
||||||
@ -763,7 +763,7 @@ pub struct TokenizeState {
|
|||||||
/// _(INTERNALS)_ Trait that encapsulates a peekable character input stream.
|
/// _(INTERNALS)_ Trait that encapsulates a peekable character input stream.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This trait is volatile and may change.
|
/// This trait is volatile and may change.
|
||||||
pub trait InputStream {
|
pub trait InputStream {
|
||||||
@ -777,7 +777,7 @@ pub trait InputStream {
|
|||||||
/// _(INTERNALS)_ Parse a string literal wrapped by `enclosing_char`.
|
/// _(INTERNALS)_ Parse a string literal wrapped by `enclosing_char`.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
pub fn parse_string_literal(
|
pub fn parse_string_literal(
|
||||||
@ -968,7 +968,7 @@ fn scan_block_comment(
|
|||||||
/// _(INTERNALS)_ Get the next token from the `stream`.
|
/// _(INTERNALS)_ Get the next token from the `stream`.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// ## WARNING
|
/// # WARNING
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -212,6 +212,12 @@ impl From<&str> for ImmutableString {
|
|||||||
Self(value.to_string().into())
|
Self(value.to_string().into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<&String> for ImmutableString {
|
||||||
|
#[inline(always)]
|
||||||
|
fn from(value: &String) -> Self {
|
||||||
|
Self(value.to_string().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl From<String> for ImmutableString {
|
impl From<String> for ImmutableString {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: String) -> Self {
|
fn from(value: String) -> Self {
|
||||||
|
@ -73,7 +73,7 @@ fn test_fn_ptr() -> Result<(), Box<EvalAltResult>> {
|
|||||||
"#
|
"#
|
||||||
)
|
)
|
||||||
.expect_err("should error"),
|
.expect_err("should error"),
|
||||||
EvalAltResult::ErrorInFunctionCall(fn_name, err, _)
|
EvalAltResult::ErrorInFunctionCall(fn_name, _, err, _)
|
||||||
if fn_name == "foo" && matches!(*err, EvalAltResult::ErrorUnboundThis(_))
|
if fn_name == "foo" && matches!(*err, EvalAltResult::ErrorUnboundThis(_))
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ fn test_module_resolver() -> Result<(), Box<EvalAltResult>> {
|
|||||||
"#
|
"#
|
||||||
)
|
)
|
||||||
.expect_err("should error"),
|
.expect_err("should error"),
|
||||||
EvalAltResult::ErrorInFunctionCall(fn_name, _, _) if fn_name == "foo"
|
EvalAltResult::ErrorInFunctionCall(fn_name, _, _, _) if fn_name == "foo"
|
||||||
));
|
));
|
||||||
|
|
||||||
engine.set_max_modules(1000);
|
engine.set_max_modules(1000);
|
||||||
|
Loading…
Reference in New Issue
Block a user