Merge pull request #46 from schungx/plugins_dev
Better formatting of plugin code blocks, add documentation.
This commit is contained in:
commit
cd3270c44e
@ -43,7 +43,11 @@ The Rhai Scripting Language
|
|||||||
4. [Printing Custom Types](rust/print-custom.md)
|
4. [Printing Custom Types](rust/print-custom.md)
|
||||||
9. [Packages](rust/packages/index.md)
|
9. [Packages](rust/packages/index.md)
|
||||||
1. [Built-in Packages](rust/packages/builtin.md)
|
1. [Built-in Packages](rust/packages/builtin.md)
|
||||||
2. [Create a Custom Package](rust/packages/create.md)
|
2. [Load a Plugin Module as a Package](rust/packages/plugin.md)
|
||||||
|
3. [Manually Create a Custom Package](rust/packages/create.md)
|
||||||
|
10. [Plugins](plugins/index.md)
|
||||||
|
1. [Create a Plugin Module](plugins/module.md)
|
||||||
|
2. [Create a Plugin Function](plugins/function.md)
|
||||||
5. [Rhai Language Reference](language/index.md)
|
5. [Rhai Language Reference](language/index.md)
|
||||||
1. [Comments](language/comments.md)
|
1. [Comments](language/comments.md)
|
||||||
2. [Values and Types](language/values-and-types.md)
|
2. [Values and Types](language/values-and-types.md)
|
||||||
@ -84,7 +88,7 @@ The Rhai Scripting Language
|
|||||||
17. [Modules](language/modules/index.md)
|
17. [Modules](language/modules/index.md)
|
||||||
1. [Export Variables, Functions and Sub-Modules](language/modules/export.md)
|
1. [Export Variables, Functions and Sub-Modules](language/modules/export.md)
|
||||||
2. [Import Modules](language/modules/import.md)
|
2. [Import Modules](language/modules/import.md)
|
||||||
3. [Create from Rust](rust/modules/index.md)
|
3. [Create from Rust](rust/modules/create.md)
|
||||||
4. [Create from AST](language/modules/ast.md)
|
4. [Create from AST](language/modules/ast.md)
|
||||||
5. [Module Resolvers](rust/modules/resolvers.md)
|
5. [Module Resolvers](rust/modules/resolvers.md)
|
||||||
1. [Custom Implementation](rust/modules/imp-resolver.md)
|
1. [Custom Implementation](rust/modules/imp-resolver.md)
|
||||||
|
@ -9,11 +9,11 @@ Integer Functions
|
|||||||
The following standard functions (defined in the [`BasicMathPackage`][packages] but excluded if using a [raw `Engine`])
|
The following standard functions (defined in the [`BasicMathPackage`][packages] but excluded if using a [raw `Engine`])
|
||||||
operate on `i8`, `i16`, `i32`, `i64`, `f32` and `f64` only:
|
operate on `i8`, `i16`, `i32`, `i64`, `f32` and `f64` only:
|
||||||
|
|
||||||
| Function | Description |
|
| Function | Description |
|
||||||
| ------------ | --------------------------------------------------------------- |
|
| ------------ | ----------------------------------------------------------------------- |
|
||||||
| `abs` | absolute value |
|
| `abs` | absolute value |
|
||||||
| `sign` | returns -1 if the number is negative, +1 if positive, 0 if zero |
|
| `sign` | returns -1 (`INT`) if the number is negative, +1 if positive, 0 if zero |
|
||||||
| [`to_float`] | converts an integer type to `f64` |
|
| [`to_float`] | converts an integer type to `FLOAT` |
|
||||||
|
|
||||||
Floating-Point Functions
|
Floating-Point Functions
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -33,6 +33,12 @@
|
|||||||
[packages]: {{rootUrl}}/rust/packages/index.md
|
[packages]: {{rootUrl}}/rust/packages/index.md
|
||||||
[custom package]: {{rootUrl}}/rust/packages/create.md
|
[custom package]: {{rootUrl}}/rust/packages/create.md
|
||||||
[custom packages]: {{rootUrl}}/rust/packages/create.md
|
[custom packages]: {{rootUrl}}/rust/packages/create.md
|
||||||
|
[plugin]: {{rootUrl}}/plugins/index.md
|
||||||
|
[plugins]: {{rootUrl}}/plugins/index.md
|
||||||
|
[plugin module]: {{rootUrl}}/plugins/module.md
|
||||||
|
[plugin modules]: {{rootUrl}}/plugins/module.md
|
||||||
|
[plugin function]: {{rootUrl}}/plugins/function.md
|
||||||
|
[plugin functions]: {{rootUrl}}/plugins/function.md
|
||||||
[`Scope`]: {{rootUrl}}/engine/scope.md
|
[`Scope`]: {{rootUrl}}/engine/scope.md
|
||||||
[`serde`]: {{rootUrl}}/rust/serde.md
|
[`serde`]: {{rootUrl}}/rust/serde.md
|
||||||
|
|
||||||
|
78
doc/src/plugins/function.md
Normal file
78
doc/src/plugins/function.md
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
Create a Plugin Function
|
||||||
|
========================
|
||||||
|
|
||||||
|
{{#include ../links.md}}
|
||||||
|
|
||||||
|
|
||||||
|
Sometimes only a few ad hoc functions are required and it is simpler to register
|
||||||
|
individual functions instead of a full-blown [plugin module].
|
||||||
|
|
||||||
|
|
||||||
|
Macros
|
||||||
|
------
|
||||||
|
|
||||||
|
| Macro | Apply to | Behavior |
|
||||||
|
| ------------------------ | ------------------------------------------------------------- | --------------------------------------------------------- |
|
||||||
|
| `#[export_fn]` | Rust function defined in module | Export the function |
|
||||||
|
| `#[rhai_fn(return_raw)]` | Rust function returning `Result<Dynamic, Box<EvalAltResult>>` | Specify that this is a fallible function |
|
||||||
|
| `register_exported_fn!` | [`Engine`] instance, register name, function name | Register function with the [`Engine`] under specific name |
|
||||||
|
| `set_exported_fn!` | [`Module`], register name, function name | Register function with the [`Module`] under specific name |
|
||||||
|
|
||||||
|
|
||||||
|
`#[export_fn]` and `register_exported_fn!`
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
Apply `#[export_fn]` onto a function defined at _module level_ to convert it into a Rhai plugin function.
|
||||||
|
|
||||||
|
The function cannot be nested inside another function - it can only be defined directly under a module.
|
||||||
|
|
||||||
|
To register the plugin function, simply call `register_exported_fn!`. The name of the function can be
|
||||||
|
any text string, so it is possible to register _overloaded_ functions as well as operators.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use rhai::plugins::*; // import macros
|
||||||
|
|
||||||
|
#[export_fn]
|
||||||
|
fn increment(num: &mut i64) {
|
||||||
|
*num += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
// 'register_exported_fn!' registers the function as 'inc' with the Engine.
|
||||||
|
register_exported_fn!(engine, "inc", increment);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Fallible Functions
|
||||||
|
------------------
|
||||||
|
|
||||||
|
To register [fallible functions] (i.e. functions that may return errors), apply the
|
||||||
|
`#[rhai_fn(return_raw)]` attribute on plugin functions that return `Result<Dynamic, Box<EvalAltResult>>`.
|
||||||
|
|
||||||
|
A syntax error is generated if the function with `#[rhai_fn(return_raw)]` does not
|
||||||
|
have the appropriate return type.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use rhai::plugins::*; // import macros
|
||||||
|
|
||||||
|
#[export_fn]
|
||||||
|
#[rhai_fn(return_raw)]
|
||||||
|
pub fn double_and_divide(x: i64, y: i64) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
if y == 0 {
|
||||||
|
Err("Division by zero!".into())
|
||||||
|
} else {
|
||||||
|
let result = (x * 2) / y;
|
||||||
|
Ok(result.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
// Overloads the operator '+' with the Engine.
|
||||||
|
register_exported_fn!(engine, "+", double_and_divide);
|
||||||
|
}
|
||||||
|
```
|
11
doc/src/plugins/index.md
Normal file
11
doc/src/plugins/index.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Plugins
|
||||||
|
=======
|
||||||
|
|
||||||
|
{{#include ../links.md}}
|
||||||
|
|
||||||
|
Rhai contains a robust _plugin_ system that greatly simplifies registration of custom functions.
|
||||||
|
|
||||||
|
Instead of the large `Engine::register_XXX` API, and the parallel `Module::set_fn_XXX` API,
|
||||||
|
a _plugin_ simplifies the work of creating and registering multiple functions into an [`Engine`].
|
||||||
|
|
||||||
|
Plugins are processed via a set of procedural macros under the `rhai::plugins` module.
|
194
doc/src/plugins/module.md
Normal file
194
doc/src/plugins/module.md
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
Create a Plugin Module
|
||||||
|
======================
|
||||||
|
|
||||||
|
{{#include ../links.md}}
|
||||||
|
|
||||||
|
|
||||||
|
The core of creating a plugin [module] is the `#[export_module]` attribute.
|
||||||
|
|
||||||
|
When applied on a module definition, `#[export_module]` automatically generates Rhai-acceptable
|
||||||
|
functions from all `pub` functions defined within.
|
||||||
|
|
||||||
|
The resulting module can then be loaded into an [`Engine`] as a normal [module],
|
||||||
|
or as a [custom package].
|
||||||
|
|
||||||
|
|
||||||
|
Macros
|
||||||
|
------
|
||||||
|
|
||||||
|
| Macro | Apply to | Behavior |
|
||||||
|
| --------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------- |
|
||||||
|
| `#[export_module]` | Rust module | Export all `pub` functions |
|
||||||
|
| `#[rhai_fn(skip)]` | Function in Rust module | Do not export this function |
|
||||||
|
| `#[rhai_fn(return_raw)]` | `pub` function in Rust module returning `Result<Dynamic, Box<EvalAltResult>>` | Specify that this is a fallible function |
|
||||||
|
| `#[rhai_fn(name = "...")]` | `pub` function in Rust module | Register function under specific name |
|
||||||
|
| `#[rhai_fn(get = "...")]` | `pub` function in Rust module (first parameter must be `&mut`) | Register a property getter under specific name |
|
||||||
|
| `#[rhai_fn(set = "...")]` | `pub` function in Rust module (first parameter must be `&mut`) | Register a property setter under specific name |
|
||||||
|
| `#[rhai_fn(index_get]` | `pub` function in Rust module (first parameter must be `&mut`) | Register a index getter |
|
||||||
|
| `#[rhai_fn(index_set)]` | `pub` function in Rust module (first parameter must be `&mut`) | Register a index setter |
|
||||||
|
| `#[rhai_mod(name = "...")]` | `pub` sub-module in Rust module | Export the sub-module under specific name |
|
||||||
|
| `exported_module!` | Rust module name | Create a [module] containing exported functions |
|
||||||
|
|
||||||
|
|
||||||
|
`#[export_module]` and `exported_module!`
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
Apply `#[export_module]` onto a standard module to convert all `pub` functions
|
||||||
|
into Rhai plugin functions.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use rhai::plugins::*; // import macros
|
||||||
|
|
||||||
|
#[export_module]
|
||||||
|
mod my_module {
|
||||||
|
// This function will be registered as 'greet'.
|
||||||
|
pub fn greet(name: &str) -> String {
|
||||||
|
format!("hello, {}!", name)
|
||||||
|
}
|
||||||
|
// This function will be registered as 'get_num'.
|
||||||
|
pub fn get_num() -> i64 {
|
||||||
|
mystic_number()
|
||||||
|
}
|
||||||
|
// This function will be registered as 'increment'.
|
||||||
|
pub fn increment(num: &mut i64) {
|
||||||
|
*num += 1;
|
||||||
|
}
|
||||||
|
// This function is NOT registered.
|
||||||
|
fn mystic_number() -> i64 {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
// 'exported_module!' creates the plugin module.
|
||||||
|
let module = exported_module!(my_module);
|
||||||
|
|
||||||
|
// A module can simply be loaded as a custom package.
|
||||||
|
engine.load_package(module);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The above automatically defines a plugin module named `my_module` which can be converted into
|
||||||
|
a Rhai [module] via `exported_module!`. The functions contained within the module definition
|
||||||
|
(i.e. `greet`, `get_num` and `increment`) are automatically registered into the [`Engine`] when
|
||||||
|
`Engine::load_package` is called.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let x = greet("world");
|
||||||
|
x == "hello, world!";
|
||||||
|
|
||||||
|
let x = greet(get_num().to_string());
|
||||||
|
x == "hello, 42!";
|
||||||
|
|
||||||
|
let x = get_num();
|
||||||
|
x == 42;
|
||||||
|
|
||||||
|
increment(x);
|
||||||
|
x == 43;
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Getters, Setters and Indexers
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Functions can be marked as [getters/setters] and [indexers] for [custom types] via the `#[rhai_fn]`
|
||||||
|
attribute, which is applied on a function level.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use rhai::plugins::*; // import macros
|
||||||
|
|
||||||
|
#[export_module]
|
||||||
|
mod my_module {
|
||||||
|
// This is a normal function 'greet'.
|
||||||
|
pub fn greet(name: &str) -> String {
|
||||||
|
format!("hello, {}!", name)
|
||||||
|
}
|
||||||
|
// This is a getter for 'MyType::prop'.
|
||||||
|
#[rhai_fn(get = "prop")]
|
||||||
|
pub fn get_prop(obj: &mut MyType) -> i64 {
|
||||||
|
obj.prop
|
||||||
|
}
|
||||||
|
// This is a setter for 'MyType::prop'.
|
||||||
|
#[rhai_fn(set = "prop")]
|
||||||
|
pub fn set_prop(obj: &mut MyType, value: i64) {
|
||||||
|
obj.prop = value;
|
||||||
|
}
|
||||||
|
// This is an index getter for 'MyType'.
|
||||||
|
#[rhai_fn(index_get)]
|
||||||
|
pub fn get_index(obj: &mut MyType, index: i64) -> bool {
|
||||||
|
obj.list[index]
|
||||||
|
}
|
||||||
|
// This is an index setter for 'MyType'.
|
||||||
|
#[rhai_fn(index_get)]
|
||||||
|
pub fn get_index(obj: &mut MyType, index: i64, state: bool) {
|
||||||
|
obj.list[index] = state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Function Overloading and Operators
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
Operators and overloaded functions can be specified via `#[rhai_fn(name = "...")]` applied upon
|
||||||
|
individual functions.
|
||||||
|
|
||||||
|
The text string given as the `name` parameter to `#[rhai_fn]` is used to register the function with
|
||||||
|
the [`Engine`], disregarding the actual name of the function.
|
||||||
|
|
||||||
|
With `#[rhai_fn(name = "...")]`, multiple functions may be registered under the same name in Rhai.
|
||||||
|
|
||||||
|
Operators (which require function names that are not valid for Rust) can also be registered this way.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use rhai::plugins::*; // import macros
|
||||||
|
|
||||||
|
#[export_module]
|
||||||
|
mod my_module {
|
||||||
|
// This is the '+' operator for 'MyType'.
|
||||||
|
#[rhai_fn(name = "+")]
|
||||||
|
pub fn add(obj: &mut MyType, value: i64) {
|
||||||
|
obj.prop += value;
|
||||||
|
}
|
||||||
|
// This function is 'calc (i64)'.
|
||||||
|
#[rhai_fn(name = "calc")]
|
||||||
|
pub fn calc_with_default(num: i64) -> i64 {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
// This function is 'calc (i64, bool)'.
|
||||||
|
#[rhai_fn(name = "calc")]
|
||||||
|
pub fn calc_with_option(num: i64, option: bool) -> i64 {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Fallible Functions
|
||||||
|
------------------
|
||||||
|
|
||||||
|
To register [fallible functions] (i.e. functions that may return errors), apply the
|
||||||
|
`#[rhai_fn(return_raw)]` attribute on functions that return `Result<Dynamic, Box<EvalAltResult>>`.
|
||||||
|
|
||||||
|
A syntax error is generated if the function with `#[rhai_fn(return_raw)]` does not
|
||||||
|
have the appropriate return type.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use rhai::plugins::*; // import macros
|
||||||
|
|
||||||
|
#[export_module]
|
||||||
|
mod my_module {
|
||||||
|
// This overloads the '/' operator for i64.
|
||||||
|
#[rhai_fn(name = "/", return_raw)]
|
||||||
|
pub fn double_and_divide(x: i64, y: i64) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
if y == 0 {
|
||||||
|
Err("Division by zero!".into())
|
||||||
|
} else {
|
||||||
|
let result = (x * 2) / y;
|
||||||
|
Ok(result.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -3,13 +3,23 @@ Create a Module from Rust
|
|||||||
|
|
||||||
{{#include ../../links.md}}
|
{{#include ../../links.md}}
|
||||||
|
|
||||||
Manually creating a [`Module`] is possible via the `Module` API.
|
|
||||||
|
Create via Plugin
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
By far the simplest way to create a [module] is via a [plugin module].
|
||||||
|
|
||||||
|
|
||||||
|
Create via `Module` API
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Manually creating a [module] is possible via the `Module` API.
|
||||||
|
|
||||||
For the complete `Module` API, refer to the [documentation](https://docs.rs/rhai/{{version}}/rhai/struct.Module.html) online.
|
For the complete `Module` API, refer to the [documentation](https://docs.rs/rhai/{{version}}/rhai/struct.Module.html) online.
|
||||||
|
|
||||||
|
|
||||||
Make the Module Available to the Engine
|
Make the `Module` Available to the `Engine`
|
||||||
--------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
In order to _use_ a custom module, there must be a [module resolver].
|
In order to _use_ a custom module, there must be a [module resolver].
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
Create a Custom Package
|
Manually Create a Custom Package
|
||||||
======================
|
===============================
|
||||||
|
|
||||||
{{#include ../../links.md}}
|
{{#include ../../links.md}}
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ Loading a package into an [`Engine`] is functionally equivalent to calling `Engi
|
|||||||
on _each_ of the functions inside the package. But because packages are _shared_, loading an existing
|
on _each_ of the functions inside the package. But because packages are _shared_, loading an existing
|
||||||
package is _much_ cheaper than registering all the functions one by one.
|
package is _much_ cheaper than registering all the functions one by one.
|
||||||
|
|
||||||
The macro `rhai::def_package!` is used to create a new custom package.
|
The macro `rhai::def_package!` can be used to create a new custom package.
|
||||||
|
|
||||||
|
|
||||||
Macro Parameters
|
Macro Parameters
|
||||||
@ -53,3 +53,48 @@ def_package!(rhai:MyPackage:"My own personal super package", module, {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Create a Custom Package from a Plugin Module
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
By far the easiest way to create a custom module is to call `Module::merge_flatten` from within
|
||||||
|
`rhai::def_package!` which simply merges in all the functions defined within a [plugin module].
|
||||||
|
|
||||||
|
In fact, this exactly is how Rhai's built-in packages, such as `BasicMathPackage`, are implemented.
|
||||||
|
|
||||||
|
`rhai::plugins::exported_module!` generates a module from the [plugins][plugin module] definition,
|
||||||
|
and `Module::merge_flatten` consumes its, adding all its registered functions into the package itself.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// Import necessary types and traits.
|
||||||
|
use rhai::{
|
||||||
|
def_package,
|
||||||
|
packages::Package,
|
||||||
|
packages::{ArithmeticPackage, BasicArrayPackage, BasicMapPackage, LogicPackage}
|
||||||
|
};
|
||||||
|
use rhai::plugin::*;
|
||||||
|
|
||||||
|
// Define plugin module.
|
||||||
|
#[export_module]
|
||||||
|
mod my_module {
|
||||||
|
pub fn greet(name: &str) -> String {
|
||||||
|
format!("hello, {}!", name)
|
||||||
|
}
|
||||||
|
pub fn get_num() -> i64 {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the package 'MyPackage'.
|
||||||
|
def_package!(rhai:MyPackage:"My own personal super package", module, {
|
||||||
|
// Aggregate existing packages simply by calling 'init' on each.
|
||||||
|
ArithmeticPackage::init(module);
|
||||||
|
LogicPackage::init(module);
|
||||||
|
BasicArrayPackage::init(module);
|
||||||
|
BasicMapPackage::init(module);
|
||||||
|
|
||||||
|
// Merge the plugin module into the custom package.
|
||||||
|
module.merge_flatten(exported_module!(my_module));
|
||||||
|
});
|
||||||
|
```
|
||||||
|
@ -11,7 +11,7 @@ packages to be used.
|
|||||||
Packages typically contain Rust functions that are callable within a Rhai script.
|
Packages typically contain Rust functions that are callable within a Rhai script.
|
||||||
All functions registered in a package is loaded under the _global namespace_ (i.e. they're available without module qualifiers).
|
All functions registered in a package is loaded under the _global namespace_ (i.e. they're available without module qualifiers).
|
||||||
|
|
||||||
Once a package is created (e.g. via `new`), it can be _shared_ (via `get`) among multiple instances of [`Engine`],
|
Once a package is created (e.g. via `Package::new`), it can be _shared_ (via `Package::get`) among multiple instances of [`Engine`],
|
||||||
even across threads (under [`sync`]). Therefore, a package only has to be created _once_.
|
even across threads (under [`sync`]). Therefore, a package only has to be created _once_.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -36,3 +36,21 @@ namespace alias specified in an [`import`] statement (see also [modules]).
|
|||||||
|
|
||||||
A package is _static_ (i.e. pre-loaded into an [`Engine`]), while a module is _dynamic_ (i.e. loaded with
|
A package is _static_ (i.e. pre-loaded into an [`Engine`]), while a module is _dynamic_ (i.e. loaded with
|
||||||
the `import` statement).
|
the `import` statement).
|
||||||
|
|
||||||
|
|
||||||
|
Load a Module as a Package
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Stand-alone [modules] can be loaded directly into an [`Engine`] as a package via the same `Engine::load_package` API.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let mut module = Module::new();
|
||||||
|
:
|
||||||
|
// add functions into module
|
||||||
|
:
|
||||||
|
|
||||||
|
engine.load_package(module);
|
||||||
|
```
|
||||||
|
|
||||||
|
[Modules], however, are not _shared_, so use a [custom package] if it must be shared among multiple
|
||||||
|
instances of [`Engine`].
|
||||||
|
41
doc/src/rust/packages/plugin.md
Normal file
41
doc/src/rust/packages/plugin.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Load a Plugin Module as a Package
|
||||||
|
================================
|
||||||
|
|
||||||
|
{{#include ../../links.md}}
|
||||||
|
|
||||||
|
[Plugin modules] can be loaded as a package just like a normal [module].
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use rhai::Engine;
|
||||||
|
use rhai::plugin::*;
|
||||||
|
|
||||||
|
// Define plugin module.
|
||||||
|
#[export_module]
|
||||||
|
mod my_module {
|
||||||
|
pub fn greet(name: &str) -> String {
|
||||||
|
format!("hello, {}!", name)
|
||||||
|
}
|
||||||
|
pub fn get_num() -> i64 {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
// Create plugin module.
|
||||||
|
let module = exported_module!(my_module);
|
||||||
|
|
||||||
|
// Make the 'greet' and 'get_num' functions available to scripts.
|
||||||
|
engine.load_package(module);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Share a Package Among `Engine`s
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Loading a [module] via `Engine::load_package` consumes the module and it cannot be used again.
|
||||||
|
|
||||||
|
If the functions are needed for multiple instances of [`Engine`], create a [custom package] from the
|
||||||
|
[plugin module], which can then be shared with `Package::get`.
|
@ -17,250 +17,246 @@ use crate::stdlib::format;
|
|||||||
|
|
||||||
macro_rules! gen_arithmetic_functions {
|
macro_rules! gen_arithmetic_functions {
|
||||||
($root:ident => $($arg_type:ident),+) => {
|
($root:ident => $($arg_type:ident),+) => {
|
||||||
pub mod $root { $(
|
pub mod $root { $(pub mod $arg_type {
|
||||||
pub mod $arg_type {
|
use super::super::*;
|
||||||
use super::super::*;
|
|
||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
pub mod functions {
|
pub mod functions {
|
||||||
#[rhai_fn(name = "+", return_raw)]
|
#[rhai_fn(name = "+", return_raw)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_add(y).ok_or_else(|| {
|
x.checked_add(y).ok_or_else(|| {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Addition overflow: {} + {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}).map(Dynamic::from)
|
||||||
|
} else {
|
||||||
|
Ok(Dynamic::from(x + y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "-", return_raw)]
|
||||||
|
#[inline]
|
||||||
|
pub fn subtract(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
if cfg!(not(feature = "unchecked")) {
|
||||||
|
x.checked_sub(y).ok_or_else(|| {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Subtraction overflow: {} - {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}).map(Dynamic::from)
|
||||||
|
} else {
|
||||||
|
Ok(Dynamic::from(x - y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "*", return_raw)]
|
||||||
|
#[inline]
|
||||||
|
pub fn multiply(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
if cfg!(not(feature = "unchecked")) {
|
||||||
|
x.checked_mul(y).ok_or_else(|| {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Multiplication overflow: {} * {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}).map(Dynamic::from)
|
||||||
|
} else {
|
||||||
|
Ok(Dynamic::from(x * y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "/", return_raw)]
|
||||||
|
#[inline]
|
||||||
|
pub fn divide(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
if cfg!(not(feature = "unchecked")) {
|
||||||
|
// Detect division by zero
|
||||||
|
if y == 0 {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Division by zero: {} / {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
x.checked_div(y).ok_or_else(|| {
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Addition overflow: {} + {}", x, y),
|
format!("Division overflow: {} / {}", x, y),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
}).map(Dynamic::from)
|
}).map(Dynamic::from)
|
||||||
} else {
|
|
||||||
Ok(Dynamic::from(x + y))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(Dynamic::from(x / y))
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "-", return_raw)]
|
}
|
||||||
#[inline]
|
#[rhai_fn(name = "%", return_raw)]
|
||||||
pub fn subtract(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
#[inline]
|
||||||
if cfg!(not(feature = "unchecked")) {
|
pub fn modulo(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
x.checked_sub(y).ok_or_else(|| {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
|
x.checked_rem(y).ok_or_else(|| {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Modulo division by zero or overflow: {} % {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}).map(Dynamic::from)
|
||||||
|
} else {
|
||||||
|
Ok(Dynamic::from(x % y))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "~", return_raw)]
|
||||||
|
#[inline]
|
||||||
|
pub fn power(x: INT, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
if cfg!(not(feature = "unchecked")) {
|
||||||
|
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Integer raised to too large an index: {} ~ {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
} else if y < 0 {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Integer raised to a negative index: {} ~ {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
x.checked_pow(y as u32).ok_or_else(|| {
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Subtraction overflow: {} - {}", x, y),
|
format!("Power overflow: {} ~ {}", x, y),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
}).map(Dynamic::from)
|
}).map(Dynamic::from)
|
||||||
} else {
|
|
||||||
Ok(Dynamic::from(x - y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[rhai_fn(name = "*", return_raw)]
|
|
||||||
#[inline]
|
|
||||||
pub fn multiply(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
if cfg!(not(feature = "unchecked")) {
|
|
||||||
x.checked_mul(y).ok_or_else(|| {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Multiplication overflow: {} * {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}).map(Dynamic::from)
|
|
||||||
} else {
|
|
||||||
Ok(Dynamic::from(x * y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[rhai_fn(name = "/", return_raw)]
|
|
||||||
#[inline]
|
|
||||||
pub fn divide(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
if cfg!(not(feature = "unchecked")) {
|
|
||||||
// Detect division by zero
|
|
||||||
if y == 0 {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Division by zero: {} / {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
} else {
|
|
||||||
x.checked_div(y).ok_or_else(|| {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Division overflow: {} / {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}).map(Dynamic::from)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(Dynamic::from(x / y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[rhai_fn(name = "%", return_raw)]
|
|
||||||
#[inline]
|
|
||||||
pub fn modulo(x: $arg_type, y: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
if cfg!(not(feature = "unchecked")) {
|
|
||||||
x.checked_rem(y).ok_or_else(|| {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Modulo division by zero or overflow: {} % {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}).map(Dynamic::from)
|
|
||||||
} else {
|
|
||||||
Ok(Dynamic::from(x % y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[rhai_fn(name = "~", return_raw)]
|
|
||||||
#[inline]
|
|
||||||
pub fn power(x: INT, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
if cfg!(not(feature = "unchecked")) {
|
|
||||||
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Integer raised to too large an index: {} ~ {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
} else if y < 0 {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Integer raised to a negative index: {} ~ {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
} else {
|
|
||||||
x.checked_pow(y as u32).ok_or_else(|| {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Power overflow: {} ~ {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}).map(Dynamic::from)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(Dynamic::from(x.pow(y as u32)))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(Dynamic::from(x.pow(y as u32)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "<<", return_raw)]
|
#[rhai_fn(name = "<<", return_raw)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shift_left(x: $arg_type, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn shift_left(x: $arg_type, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Left-shift by too many bits: {} << {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
} else if y < 0 {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Left-shift by a negative number: {} << {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
x.checked_shl(y as u32).ok_or_else(|| {
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Left-shift by too many bits: {} << {}", x, y),
|
format!("Left-shift by too many bits: {} << {}", x, y),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
} else if y < 0 {
|
}).map(Dynamic::from)
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Left-shift by a negative number: {} << {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
} else {
|
|
||||||
x.checked_shl(y as u32).ok_or_else(|| {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Left-shift by too many bits: {} << {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}).map(Dynamic::from)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(Dynamic::from(x << y))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok(Dynamic::from(x << y))
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = ">>", return_raw)]
|
}
|
||||||
#[inline]
|
#[rhai_fn(name = ">>", return_raw)]
|
||||||
pub fn shift_right(x: $arg_type, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
#[inline]
|
||||||
if cfg!(not(feature = "unchecked")) {
|
pub fn shift_right(x: $arg_type, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
|
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Right-shift by too many bits: {} >> {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
} else if y < 0 {
|
||||||
|
EvalAltResult::ErrorArithmetic(
|
||||||
|
format!("Right-shift by a negative number: {} >> {}", x, y),
|
||||||
|
Position::none(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
x.checked_shr(y as u32).ok_or_else(|| {
|
||||||
EvalAltResult::ErrorArithmetic(
|
EvalAltResult::ErrorArithmetic(
|
||||||
format!("Right-shift by too many bits: {} >> {}", x, y),
|
format!("Right-shift by too many bits: {} >> {}", x, y),
|
||||||
Position::none(),
|
Position::none(),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
} else if y < 0 {
|
}).map(Dynamic::from)
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Right-shift by a negative number: {} >> {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
} else {
|
|
||||||
x.checked_shr(y as u32).ok_or_else(|| {
|
|
||||||
EvalAltResult::ErrorArithmetic(
|
|
||||||
format!("Right-shift by too many bits: {} >> {}", x, y),
|
|
||||||
Position::none(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
}).map(Dynamic::from)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(Dynamic::from(x >> y))
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
#[rhai_fn(name = "&")]
|
Ok(Dynamic::from(x >> y))
|
||||||
#[inline(always)]
|
|
||||||
pub fn binary_and(x: $arg_type, y: $arg_type) -> $arg_type {
|
|
||||||
x & y
|
|
||||||
}
|
|
||||||
#[rhai_fn(name = "|")]
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn binary_or(x: $arg_type, y: $arg_type) -> $arg_type {
|
|
||||||
x | y
|
|
||||||
}
|
|
||||||
#[rhai_fn(name = "^")]
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn binary_xor(x: $arg_type, y: $arg_type) -> $arg_type {
|
|
||||||
x ^ y
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[rhai_fn(name = "&")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn binary_and(x: $arg_type, y: $arg_type) -> $arg_type {
|
||||||
|
x & y
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "|")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn binary_or(x: $arg_type, y: $arg_type) -> $arg_type {
|
||||||
|
x | y
|
||||||
|
}
|
||||||
|
#[rhai_fn(name = "^")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn binary_xor(x: $arg_type, y: $arg_type) -> $arg_type {
|
||||||
|
x ^ y
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)* }
|
})* }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! gen_signed_functions {
|
macro_rules! gen_signed_functions {
|
||||||
($root:ident => $($arg_type:ident),+) => {
|
($root:ident => $($arg_type:ident),+) => {
|
||||||
pub mod $root { $(
|
pub mod $root { $(pub mod $arg_type {
|
||||||
pub mod $arg_type {
|
use super::super::*;
|
||||||
use super::super::*;
|
|
||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
pub mod functions {
|
pub mod functions {
|
||||||
#[rhai_fn(name = "-", return_raw)]
|
#[rhai_fn(name = "-", return_raw)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn neg(x: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn neg(x: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if cfg!(not(feature = "unchecked")) {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_neg().ok_or_else(|| {
|
x.checked_neg().ok_or_else(|| {
|
||||||
EvalAltResult::ErrorArithmetic(format!("Negation overflow: -{}", x), Position::none())
|
EvalAltResult::ErrorArithmetic(format!("Negation overflow: -{}", x), Position::none())
|
||||||
.into()
|
.into()
|
||||||
}).map(Dynamic::from)
|
}).map(Dynamic::from)
|
||||||
} else {
|
} else {
|
||||||
Ok(Dynamic::from(-x))
|
Ok(Dynamic::from(-x))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
}
|
||||||
#[inline]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn abs(x: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
#[inline]
|
||||||
if cfg!(not(feature = "unchecked")) {
|
pub fn abs(x: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
x.checked_abs().ok_or_else(|| {
|
if cfg!(not(feature = "unchecked")) {
|
||||||
EvalAltResult::ErrorArithmetic(format!("Negation overflow: -{}", x), Position::none())
|
x.checked_abs().ok_or_else(|| {
|
||||||
.into()
|
EvalAltResult::ErrorArithmetic(format!("Negation overflow: -{}", x), Position::none())
|
||||||
}).map(Dynamic::from)
|
.into()
|
||||||
} else {
|
}).map(Dynamic::from)
|
||||||
Ok(Dynamic::from(x.abs()))
|
} else {
|
||||||
}
|
Ok(Dynamic::from(x.abs()))
|
||||||
}
|
}
|
||||||
#[inline]
|
}
|
||||||
pub fn sign(x: $arg_type) -> INT {
|
#[inline]
|
||||||
if x == 0 {
|
pub fn sign(x: $arg_type) -> INT {
|
||||||
0
|
if x == 0 {
|
||||||
} else if x < 0 {
|
0
|
||||||
-1
|
} else if x < 0 {
|
||||||
} else {
|
-1
|
||||||
1
|
} else {
|
||||||
}
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)* }
|
})* }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,30 +23,33 @@ pub type Unit = ();
|
|||||||
|
|
||||||
macro_rules! gen_array_functions {
|
macro_rules! gen_array_functions {
|
||||||
($root:ident => $($arg_type:ident),+ ) => {
|
($root:ident => $($arg_type:ident),+ ) => {
|
||||||
pub mod $root { $(
|
pub mod $root { $(pub mod $arg_type {
|
||||||
pub mod $arg_type {
|
use super::super::*;
|
||||||
use super::super::*;
|
|
||||||
|
|
||||||
#[export_fn]
|
#[export_fn]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn push_func(list: &mut Array, item: $arg_type) {
|
pub fn push(list: &mut Array, item: $arg_type) {
|
||||||
super::super::push(list, item);
|
list.push(Dynamic::from(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[export_fn]
|
#[export_fn]
|
||||||
#[inline(always)]
|
pub fn insert(list: &mut Array, position: INT, item: $arg_type) {
|
||||||
pub fn insert_func(list: &mut Array, len: INT, item: $arg_type) {
|
if position <= 0 {
|
||||||
super::super::insert(list, len, item);
|
list.insert(0, Dynamic::from(item));
|
||||||
|
} else if (position as usize) >= list.len() - 1 {
|
||||||
|
push(list, item);
|
||||||
|
} else {
|
||||||
|
list.insert(position as usize, Dynamic::from(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)* }
|
})* }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! reg_functions {
|
macro_rules! reg_functions {
|
||||||
($mod_name:ident += $root:ident ; $($arg_type:ident),+) => { $(
|
($mod_name:ident += $root:ident ; $($arg_type:ident),+) => { $(
|
||||||
set_exported_fn!($mod_name, "push", $root::$arg_type::push_func);
|
set_exported_fn!($mod_name, "push", $root::$arg_type::push);
|
||||||
set_exported_fn!($mod_name, "insert", $root::$arg_type::insert_func);
|
set_exported_fn!($mod_name, "insert", $root::$arg_type::insert);
|
||||||
|
|
||||||
$mod_name.set_raw_fn("pad",
|
$mod_name.set_raw_fn("pad",
|
||||||
&[TypeId::of::<Array>(), TypeId::of::<INT>(), TypeId::of::<$arg_type>()],
|
&[TypeId::of::<Array>(), TypeId::of::<INT>(), TypeId::of::<$arg_type>()],
|
||||||
@ -138,20 +141,6 @@ mod array_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register array utility functions
|
|
||||||
#[inline(always)]
|
|
||||||
fn push<T: Variant + Clone>(list: &mut Array, item: T) {
|
|
||||||
list.push(Dynamic::from(item));
|
|
||||||
}
|
|
||||||
fn insert<T: Variant + Clone>(list: &mut Array, position: INT, item: T) {
|
|
||||||
if position <= 0 {
|
|
||||||
list.insert(0, Dynamic::from(item));
|
|
||||||
} else if (position as usize) >= list.len() - 1 {
|
|
||||||
push(list, item);
|
|
||||||
} else {
|
|
||||||
list.insert(position as usize, Dynamic::from(item));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn pad<T: Variant + Clone>(
|
fn pad<T: Variant + Clone>(
|
||||||
_engine: &Engine,
|
_engine: &Engine,
|
||||||
_: &Module,
|
_: &Module,
|
||||||
|
@ -3,45 +3,43 @@ use crate::plugin::*;
|
|||||||
|
|
||||||
macro_rules! gen_cmp_functions {
|
macro_rules! gen_cmp_functions {
|
||||||
($root:ident => $($arg_type:ident),+) => {
|
($root:ident => $($arg_type:ident),+) => {
|
||||||
mod $root { $(
|
mod $root { $(pub mod $arg_type {
|
||||||
pub mod $arg_type {
|
use super::super::*;
|
||||||
use crate::plugin::*;
|
|
||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
pub mod functions {
|
pub mod functions {
|
||||||
#[rhai_fn(name = "<")]
|
#[rhai_fn(name = "<")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn lt(x: $arg_type, y: $arg_type) -> bool {
|
pub fn lt(x: $arg_type, y: $arg_type) -> bool {
|
||||||
x < y
|
x < y
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "<=")]
|
#[rhai_fn(name = "<=")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn lte(x: $arg_type, y: $arg_type) -> bool {
|
pub fn lte(x: $arg_type, y: $arg_type) -> bool {
|
||||||
x <= y
|
x <= y
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = ">")]
|
#[rhai_fn(name = ">")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn gt(x: $arg_type, y: $arg_type) -> bool {
|
pub fn gt(x: $arg_type, y: $arg_type) -> bool {
|
||||||
x > y
|
x > y
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = ">=")]
|
#[rhai_fn(name = ">=")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn gte(x: $arg_type, y: $arg_type) -> bool {
|
pub fn gte(x: $arg_type, y: $arg_type) -> bool {
|
||||||
x >= y
|
x >= y
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "==")]
|
#[rhai_fn(name = "==")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eq(x: $arg_type, y: $arg_type) -> bool {
|
pub fn eq(x: $arg_type, y: $arg_type) -> bool {
|
||||||
x == y
|
x == y
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "!=")]
|
#[rhai_fn(name = "!=")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn ne(x: $arg_type, y: $arg_type) -> bool {
|
pub fn ne(x: $arg_type, y: $arg_type) -> bool {
|
||||||
x != y
|
x != y
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)* }
|
})* }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,17 +26,15 @@ pub const MAX_INT: INT = i64::MAX;
|
|||||||
|
|
||||||
macro_rules! gen_conversion_functions {
|
macro_rules! gen_conversion_functions {
|
||||||
($root:ident => $func_name:ident ( $($arg_type:ident),+ ) -> $result_type:ty) => {
|
($root:ident => $func_name:ident ( $($arg_type:ident),+ ) -> $result_type:ty) => {
|
||||||
pub mod $root { $(
|
pub mod $root { $(pub mod $arg_type {
|
||||||
pub mod $arg_type {
|
use super::super::*;
|
||||||
use super::super::*;
|
|
||||||
|
|
||||||
#[export_fn]
|
#[export_fn]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn $func_name(x: $arg_type) -> $result_type {
|
pub fn $func_name(x: $arg_type) -> $result_type {
|
||||||
x as $result_type
|
x as $result_type
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)* }
|
})* }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,17 +22,15 @@ type Unit = ();
|
|||||||
|
|
||||||
macro_rules! gen_functions {
|
macro_rules! gen_functions {
|
||||||
($root:ident => $fn_name:ident ( $($arg_type:ident),+ )) => {
|
($root:ident => $fn_name:ident ( $($arg_type:ident),+ )) => {
|
||||||
pub mod $root { $(
|
pub mod $root { $(pub mod $arg_type {
|
||||||
pub mod $arg_type {
|
use super::super::*;
|
||||||
use super::super::*;
|
|
||||||
|
|
||||||
#[export_fn]
|
#[export_fn]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn to_string_func(x: &mut $arg_type) -> ImmutableString {
|
pub fn to_string_func(x: &mut $arg_type) -> ImmutableString {
|
||||||
super::super::$fn_name(x)
|
super::super::$fn_name(x)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)* }
|
})* }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +141,7 @@ fn print_string(s: ImmutableString) -> ImmutableString {
|
|||||||
#[export_fn]
|
#[export_fn]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString {
|
fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString {
|
||||||
f.to_string().into()
|
to_string(f)
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn to_string<T: Display>(x: &mut T) -> ImmutableString {
|
fn to_string<T: Display>(x: &mut T) -> ImmutableString {
|
||||||
|
@ -12,28 +12,26 @@ use crate::utils::StaticVec;
|
|||||||
use crate::{result::EvalAltResult, token::Position};
|
use crate::{result::EvalAltResult, token::Position};
|
||||||
|
|
||||||
use crate::stdlib::{
|
use crate::stdlib::{
|
||||||
any::TypeId, boxed::Box, fmt::Display, format, mem, string::String, string::ToString, vec::Vec,
|
any::TypeId, boxed::Box, format, mem, string::String, string::ToString, vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! gen_concat_functions {
|
macro_rules! gen_concat_functions {
|
||||||
($root:ident => $($arg_type:ident),+ ) => {
|
($root:ident => $($arg_type:ident),+ ) => {
|
||||||
pub mod $root { $(
|
pub mod $root { $(pub mod $arg_type {
|
||||||
pub mod $arg_type {
|
use super::super::*;
|
||||||
use super::super::*;
|
|
||||||
|
|
||||||
#[export_fn]
|
#[export_fn]
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
pub fn append_func(x: &mut ImmutableString, y: $arg_type) -> String {
|
pub fn append_func(x: &mut ImmutableString, y: $arg_type) -> String {
|
||||||
super::super::add_append(x, y)
|
format!("{}{}", x, y)
|
||||||
}
|
|
||||||
|
|
||||||
#[export_fn]
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn prepend_func(x: &mut $arg_type, y: ImmutableString) -> String {
|
|
||||||
super::super::add_prepend(x, y)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)* }
|
|
||||||
|
#[export_fn]
|
||||||
|
#[inline]
|
||||||
|
pub fn prepend_func(x: &mut $arg_type, y: ImmutableString) -> String {
|
||||||
|
format!("{}{}", x, y)
|
||||||
|
}
|
||||||
|
})* }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,15 +114,6 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn add_prepend<T: Display>(x: &mut T, y: ImmutableString) -> String {
|
|
||||||
format!("{}{}", x, y)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn add_append<T: Display>(x: &mut ImmutableString, y: T) -> String {
|
|
||||||
format!("{}{}", x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_concat_functions!(basic => INT, bool, char, FnPtr);
|
gen_concat_functions!(basic => INT, bool, char, FnPtr);
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
Loading…
Reference in New Issue
Block a user