Add linkcheck, fix typos and expand.

This commit is contained in:
Stephen Chung 2020-06-20 22:56:56 +08:00
parent ffe0c559be
commit 6121aaec9d
17 changed files with 285 additions and 81 deletions

View File

@ -7,10 +7,16 @@ language = "en"
[output.html]
no-section-label = true
git-repository-url = "https://github.com/jonathandturner/rhai"
curly-quotes = true
[output.html.fold]
enable = true
level = 4
[outputX.linkcheck]
follow-web-links = false
traverse-parent-directories = false
warning-policy = "ignore"
[preprocessor.tera]
command = "mdbook-tera --json ./src/context.json"

View File

@ -4,7 +4,7 @@ The Rhai Scripting Language
1. [What is Rhai](about.md)
1. [Features](about/features.md)
2. [Supported Targets and Builds](about/targets.md)
3. [What Rhai Doesn't Do](about/non-design.md)
3. [What Rhai Isn't](about/non-design.md)
4. [Related Resources](about/related.md)
2. [Getting Started](start.md)
1. [Install the Rhai Crate](start/install.md)
@ -12,7 +12,7 @@ The Rhai Scripting Language
3. [Special Builds](start/builds.md)
1. [Performance Build](start/builds/performance.md)
2. [Minimal Build](start/builds/minimal.md)
3. [`no-std` Build](start/builds/no-std.md)
3. [no-std Build](start/builds/no-std.md)
4. [WebAssembly (WASM)](start/builds/wasm.md)
4. [Examples](start/examples.md)
1. [Rust](start/examples/rust.md)
@ -23,14 +23,16 @@ The Rhai Scripting Language
3. [Call a Rhai Function from Rust](engine/call-fn.md)
4. [Create a Rust Anonymous Function from a Rhai Function](engine/func.md)
5. [Evaluate Expressions Only](engine/expressions.md)
6. [Raw `Engine`](engine/raw.md)
6. [Raw Engine](engine/raw.md)
4. [Extend Rhai with Rust](rust.md)
1. [Traits](rust/traits.md)
2. [Register a Rust Function](rust/functions.md)
1. [`String` Parameters in Rust Functions](rust/strings.md)
1. [String Parameters in Rust Functions](rust/strings.md)
3. [Register a Generic Rust Function](rust/generic.md)
4. [Register a Fallible Rust Function](rust/fallible.md)
5. [Packages](rust/packages.md)
1. [Built-in Packages](rust/packages/builtin.md)
2. [Create a Custom Package](rust/packages/create.md)
6. [Override a Built-in Function](rust/override.md)
7. [Operator Overloading](rust/operators.md)
8. [Register a Custom Type and its Methods](rust/custom.md)
@ -38,13 +40,13 @@ The Rhai Scripting Language
2. [Indexers](rust/indexers.md)
3. [Disable Custom Types](rust/disable-custom.md)
4. [Printing Custom Types](rust/print-custom.md)
9. [`Scope` - Initializing and Maintaining State](rust/scope.md)
9. [Scope - Initializing and Maintaining State](rust/scope.md)
10. [Engine Configuration Options](rust/options.md)
5. [Rhai Language Reference](language.md)
1. [Comments](language/comments.md)
2. [Values and Types](language/values-and-types.md)
1. [`Dynamic` Values](language/dynamic.md)
2. [`type-of`](language/type-of.md)
1. [Dynamic Values](language/dynamic.md)
2. [type-of()](language/type-of.md)
3. [Numbers](language/numbers.md)
1. [Operators](language/num-op.md)
2. [Functions](language/num-fn.md)
@ -71,11 +73,12 @@ The Rhai Scripting Language
2. [Call Method as Function](language/method.md)
15. [Print and Debug](language/print-debug.md)
16. [Modules](language/modules.md)
1. [Export Variables and Functions](language/modules/export.md)
1. [Export Variables, Functions and Sub-Modules](language/modules/export.md)
2. [Import Modules](language/modules/import.md)
3. [Create from Rust](language/modules/rust.md)
4. [Create from `AST`](language/modules/ast.md)
4. [Create from AST](language/modules/ast.md)
5. [Module Resolvers](language/modules/resolvers.md)
1. [Implement a Custom Module Resolver](language/modules/imp-resolver.md)
6. [Safety and Protection](safety.md)
1. [Checked Arithmetic](safety/checked.md)
2. [Sand-Boxing](safety/sandbox.md)

View File

@ -1,5 +1,5 @@
What Rhai Doesn't Do
====================
What Rhai Isn't
===============
{{#include ../links.md}}

View File

@ -7,6 +7,6 @@ The following targets and builds are support by Rhai:
* All common CPU targets for Windows, Linux and MacOS.
* [WASM]
* WebAssembly ([WASM])
* [`no-std`]

View File

@ -5,20 +5,22 @@ Raw `Engine`
{{#include ../links.md}}
`Engine::new` creates a scripting [`Engine`] with common functionalities (e.g. printing to the console via `print`).
In many controlled embedded environments, however, these are not needed.
Use `Engine::new_raw` to create a _raw_ `Engine`, in which only a minimal set of basic arithmetic and logical operators
are supported.
In many controlled embedded environments, however, these may not be needed and unnecessarily occupy
program code storage space.
Use `Engine::new_raw` to create a _raw_ `Engine`, in which only a minimal set of
basic arithmetic and logical operators are supported.
Built-in Operators
------------------
| Operators | Assignment operators | Supported for type (see [standard types]) |
| Operators | Assignment operators | Supported for types (see [standard types]) |
| ------------------------ | ---------------------------- | ----------------------------------------------------------------------------- |
| `+`, | `+=` | `INT`, `FLOAT` (if not [`no_float`]), `ImmutableString` |
| `-`, `*`, `/`, `%`, `~`, | `-=`, `*=`, `/=`, `%=`, `~=` | `INT`, `FLOAT` (if not [`no_float`]) |
| `<<`, `>>`, `^`, | `<<=`, `>>=`, `^=` | `INT` |
| `&`, `\|`, | `&=`, `\|=` | `INT`, `bool` |
| `&&`, `\|\|` | | `bool` |
| `&`, `|`, | `&=`, `|=` | `INT`, `bool` |
| `&&`, `||` | | `bool` |
| `==`, `!=` | | `INT`, `FLOAT` (if not [`no_float`]), `bool`, `char`, `()`, `ImmutableString` |
| `>`, `>=`, `<`, `<=` | | `INT`, `FLOAT` (if not [`no_float`]), `char`, `()`, `ImmutableString` |

View File

@ -40,9 +40,9 @@ Boolean operators
| -------- | ------------------------------------- |
| `!` | Boolean _Not_ |
| `&&` | Boolean _And_ (short-circuits) |
| `\|\|` | Boolean _Or_ (short-circuits) |
| `||` | Boolean _Or_ (short-circuits) |
| `&` | Boolean _And_ (doesn't short-circuit) |
| `\|` | Boolean _Or_ (doesn't short-circuit) |
| `|` | Boolean _Or_ (doesn't short-circuit) |
Double boolean operators `&&` and `||` _short-circuit_, meaning that the second operand will not be evaluated
if the first one already proves the condition wrong.

View File

@ -5,3 +5,14 @@ Modules
Rhai allows organizing code (functions, both Rust-based or script-based, and variables) into _modules_.
Modules can be disabled via the [`no_module`] feature.
A module is of the type `Module` and encapsulates a Rhai script together with the functions defined
by that script.
The script text is run, variables are then selectively exposed via the [`export`] statement.
Functions defined by the script are automatically exported.
Modules loaded within this module at the global level become _sub-modules_ and are also automatically exported.
Other scripts can then load this module and use the variables and functions exported
as if they were defined inside the same script.

View File

@ -1,17 +1,53 @@
Export Variables and Functions from Modules
==========================================
Export Variables, Functions and Sub-Modules in Module
===================================================
{{#include ../../links.md}}
A _module_ is a single script (or pre-compiled `AST`) containing global variables and functions.
A _module_ is a single script (or pre-compiled `AST`) containing global variables, functions and sub-modules.
A module can be created from a script via the `Module::eval_ast_as_new` method. When given an `AST`,
it is first evaluated, then the following items are exposed as members of the new module:
* Global variables - essentially all variables that remain in the [`Scope`] at the end of a script run - that are exported. Variables not exported (via the `export` statement) remain hidden.
* Functions not specifically marked `private`.
* Global modules that remain in the [`Scope`] at the end of a script run.
Global Variables
----------------
The `export` statement, which can only be at global level, exposes selected variables as members of a module.
Variables not exported are _private_ and invisible to the outside.
Variables not exported are _private_ and hidden to the outside.
On the other hand, all functions are automatically exported, _unless_ it is explicitly opt-out with the [`private`] prefix.
```rust
// This is a module script.
Functions declared [`private`] are invisible to the outside.
let private = 123; // variable not exported - default hidden
let x = 42; // this will be exported below
export x; // the variable 'x' is exported under its own name
export x as answer; // the variable 'x' is exported under the alias 'answer'
// another script can load this module and access 'x' as 'module::answer'
{
let inner = 0; // local variable - it disappears when the statement block ends,
// therefore it is not 'global' and is not exported
export inner; // exporting an temporary variable has no effect
}
```
Functions
---------
All functions are automatically exported, _unless_ it is explicitly opt-out with the [`private`] prefix.
Functions declared [`private`] are hidden to the outside.
Everything exported from a module is **constant** (**read-only**).
@ -20,13 +56,25 @@ Everything exported from a module is **constant** (**read-only**).
fn inc(x) { x + 1 } // script-defined function - default public
private fn foo() {} // private function - invisible to outside
let private = 123; // variable not exported - default invisible to outside
let x = 42; // this will be exported below
export x; // the variable 'x' is exported under its own name
export x as answer; // the variable 'x' is exported under the alias 'answer'
// another script can load this module and access 'x' as 'module::answer'
private fn foo() {} // private function - hidden
```
Sub-Modules
-----------
All loaded modules are automatically exported as sub-modules.
To prevent a module from being exported, load it inside a block statement so that it goes away at the
end of the block.
```rust
// This is a module script.
import "hello" as foo; // exported as sub-module 'foo'
{
import "world" as bar; // not exported - the module disappears at the end
// of the statement block and is not 'global'
}
```

View File

@ -0,0 +1,60 @@
Implement a Custom Module Resolver
=================================
{{#include ../../links.md}}
For many applications in which Rhai is embedded, it is necessary to customize the way that modules
are resolved. For instance, modules may need to be loaded from script texts stored in a database,
not in the file system.
A module resolver must implement the trait `rhai::ModuleResolver`, which contains only one function:
`resolve`.
When Rhai prepares to load a module, `ModuleResolver::resolve` is called with the name
of the _module path_ (i.e. the path specified in the [`import`] statement). Upon success, it should
return a [`Module`]; if the module cannot be load, return `EvalAltResult::ErrorModuleNotFound`.
Example
-------
```rust
use rhai::{ModuleResolver, Module, Engine, EvalAltResult};
// Define a custom module resolver.
struct MyModuleResolver {}
// Implement the 'ModuleResolver' trait.
impl ModuleResolver for MyModuleResolver {
// Only required function.
fn resolve(
&self,
engine: &Engine, // reference to the current 'Engine'
path: &str, // the module path
pos: Position, // location of the 'import' statement
) -> Result<Module, Box<EvalAltResult>> {
// Check module path.
if is_valid_module_path(path) {
// Load the custom module.
let module: Module = load_secret_module(path);
Ok(module)
} else {
Err(Box::new(EvalAltResult::ErrorModuleNotFound(path.into(), pos)))
}
}
}
fn main() -> Result<(), Box<EvalAltResult>> {
let mut engine = Engine::new();
// Set the custom module resolver into the 'Engine'.
engine.set_module_resolver(Some(MyModuleResolver {}));
engine.consume(r#"
import "hello" as foo; // this 'import' statement will call
// 'MyModuleResolver::resolve' with "hello" as path
foo:bar();
"#)?;
Ok(())
}
```

View File

@ -18,10 +18,11 @@ lock::status = "off"; // <- runtime error - cannot modify a constant
```
`import` statements are _scoped_, meaning that they are only accessible inside the scope that they're imported.
They can appear anywhere a normal statement can be, but in the vast majority of cases `import` statements are
group at the beginning of a script.
It is, however, not advised to deviate from this common practice unless there is a _Very Good Reason™_.
They can appear anywhere a normal statement can be, but in the vast majority of cases `import` statements are
group at the beginning of a script. It is, however, not advised to deviate from this common practice unless
there is a _Very Good Reason™_.
Especially, do not place an `import` statement within a loop; doing so will repeatedly re-load the same module
during every iteration of the loop!
@ -34,7 +35,7 @@ if secured { // new block scope
c::encrypt(key); // use a function in the module
} // the module disappears at the end of the block scope
crypto::encrypt(others); // <- this causes a run-time error because the 'crypto' module
c::encrypt(others); // <- this causes a run-time error because the 'crypto' module
// is no longer available!
for x in range(0, 1000) {

View File

@ -31,7 +31,7 @@ Binary Operators
| `%` | Modulo (remainder) | |
| `~` | Power | |
| `&` | Binary _And_ bit-mask | Yes |
| `\|` | Binary _Or_ bit-mask | Yes |
| `|` | Binary _Or_ bit-mask | Yes |
| `^` | Binary _Xor_ bit-mask | Yes |
| `<<` | Left bit-shift | Yes |
| `>>` | Right bit-shift | Yes |

View File

@ -5,20 +5,20 @@ Values and Types
The following primitive types are supported natively:
| Category | Equivalent Rust types | [`type_of()`] | `to_string()` |
| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------- | --------------------- |
| **Integer number** | `u8`, `i8`, `u16`, `i16`, <br/>`u32`, `i32` (default for [`only_i32`]),<br/>`u64`, `i64` _(default)_ | `"i32"`, `"u64"` etc. | `"42"`, `"123"` etc. |
| **Floating-point number** (disabled with [`no_float`]) | `f32`, `f64` _(default)_ | `"f32"` or `"f64"` | `"123.4567"` etc. |
| **Boolean value** | `bool` | `"bool"` | `"true"` or `"false"` |
| **Unicode character** | `char` | `"char"` | `"A"`, `"x"` etc. |
| **Immutable Unicode string** | `rhai::ImmutableString` (implemented as `Rc<String>` or `Arc<String>`) | `"string"` | `"hello"` etc. |
| **Array** (disabled with [`no_index`]) | `rhai::Array` | `"array"` | `"[ ?, ?, ? ]"` |
| **Object map** (disabled with [`no_object`]) | `rhai::Map` | `"map"` | `#{ "a": 1, "b": 2 }` |
| **Timestamp** (implemented in the [`BasicTimePackage`]({{rootUrl}}/rust/packages.md)) | `std::time::Instant` | `"timestamp"` | _not supported_ |
| **Dynamic value** (i.e. can be anything) | `rhai::Dynamic` | _the actual type_ | _actual value_ |
| **System integer** (current configuration) | `rhai::INT` (`i32` or `i64`) | `"i32"` or `"i64"` | `"42"`, `"123"` etc. |
| **System floating-point** (current configuration, disabled with [`no_float`]) | `rhai::FLOAT` (`f32` or `f64`) | `"f32"` or `"f64"` | `"123.456"` etc. |
| **Nothing/void/nil/null** (or whatever it is called) | `()` | `"()"` | `""` _(empty string)_ |
| Category | Equivalent Rust types | [`type_of()`] | `to_string()` |
| --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------- | --------------------- |
| **Integer number** | `u8`, `i8`, `u16`, `i16`, <br/>`u32`, `i32` (default for [`only_i32`]),<br/>`u64`, `i64` _(default)_ | `"i32"`, `"u64"` etc. | `"42"`, `"123"` etc. |
| **Floating-point number** (disabled with [`no_float`]) | `f32`, `f64` _(default)_ | `"f32"` or `"f64"` | `"123.4567"` etc. |
| **Boolean value** | `bool` | `"bool"` | `"true"` or `"false"` |
| **Unicode character** | `char` | `"char"` | `"A"`, `"x"` etc. |
| **Immutable Unicode string** | `rhai::ImmutableString` (implemented as `Rc<String>` or `Arc<String>`) | `"string"` | `"hello"` etc. |
| **Array** (disabled with [`no_index`]) | `rhai::Array` | `"array"` | `"[ ?, ?, ? ]"` |
| **Object map** (disabled with [`no_object`]) | `rhai::Map` | `"map"` | `#{ "a": 1, "b": 2 }` |
| **Timestamp** (implemented in the [`BasicTimePackage`]({{rootUrl}}/rust/packages.md), disabled with [`no_std`]) | `std::time::Instant` ([instant::Instant](https://crates.io/crates/instant) if not [WASM] build) | `"timestamp"` | _not supported_ |
| **Dynamic value** (i.e. can be anything) | `rhai::Dynamic` | _the actual type_ | _actual value_ |
| **System integer** (current configuration) | `rhai::INT` (`i32` or `i64`) | `"i32"` or `"i64"` | `"42"`, `"123"` etc. |
| **System floating-point** (current configuration, disabled with [`no_float`]) | `rhai::FLOAT` (`f32` or `f64`) | `"f32"` or `"f64"` | `"123.456"` etc. |
| **Nothing/void/nil/null/Unit** (or whatever it is called) | `()` | `"()"` | `""` _(empty string)_ |
All types are treated strictly separate by Rhai, meaning that `i32` and `i64` and `u32` are completely different -
they even cannot be added together. This is very similar to Rust.

View File

@ -17,7 +17,7 @@
[WASM]: {{rootUrl}}/start/builds/wasm.md
[`Engine`]: {{rootUrl}}/engine/hello-world.md
[`private`]: {{rootUrl}}/engine/call_fn.md
[`private`]: {{rootUrl}}/engine/call-fn.md
[`Func`]: {{rootUrl}}/engine/func.md
[`eval_expression`]: {{rootUrl}}/engine/expressions.md
[`eval_expression_with_scope`]: {{rootUrl}}/engine/expressions.md
@ -27,7 +27,7 @@
[packages]: {{rootUrl}}/rust/packages.md
[`Scope`]: {{rootUrl}}/rust/scope.md
[`type_of()`]: {{rootUrl}}/language/type_of.md
[`type_of()`]: {{rootUrl}}/language/type-of.md
[`to_string()`]: {{rootUrl}}/language/values-and-types.md
[`()`]: {{rootUrl}}/language/values-and-types.md
[standard types]: {{rootUrl}}/language/values-and-types.md
@ -35,8 +35,8 @@
[`to_int`]: {{rootUrl}}/language/convert.md
[`to_float`]: {{rootUrl}}/language/convert.md
[custom type]: {{rootUrl}}/language/custom.md
[custom types]: {{rootUrl}}/language/custom.md
[custom type]: {{rootUrl}}/rust/custom.md
[custom types]: {{rootUrl}}/rust/custom.md
[`print`]: {{rootUrl}}/language/print-debug.md
[`debug`]: {{rootUrl}}/language/print-debug.md

View File

@ -0,0 +1 @@
# Built-in Packages

View File

@ -8,6 +8,12 @@ Standard built-in Rhai features are provided in various _packages_ that can be l
Packages reside under `rhai::packages::*` and the trait `rhai::packages::Package` must be loaded in order for
packages to be used.
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).
Once a package is created (e.g. via `new`), it can be _shared_ (via `get`) among multiple instances of [`Engine`],
even across threads (under [`sync`]). Therefore, a package only has to be created _once_.
```rust
use rhai::Engine;
use rhai::packages::Package // load the 'Package' trait to use packages
@ -19,34 +25,14 @@ let package = CorePackage::new(); // create a package - can be shared among mu
engine.load_package(package.get()); // load the package manually. 'get' returns a reference to the shared package
```
The follow packages are available:
| Package | Description | In `Core` | In `Standard` |
| ---------------------- | ------------------------------------------------------------------------------------------------------ | :-------: | :-----------: |
| `ArithmeticPackage` | Arithmetic operators (e.g. `+`, `-`, `*`, `/`) for numeric types that are not built in (e.g. `u16`) | Yes | Yes |
| `BasicIteratorPackage` | Numeric ranges (e.g. `range(1, 10)`) | Yes | Yes |
| `LogicPackage` | Logical and comparison operators (e.g. `==`, `>`) for numeric types that are not built in (e.g. `u16`) | Yes | Yes |
| `BasicStringPackage` | Basic string functions (e.g. `print`, `debug`, `len`) that are not built in | Yes | Yes |
| `BasicTimePackage` | Basic time functions (e.g. [timestamps]) | Yes | Yes |
| `MoreStringPackage` | Additional string functions, including converting common types to string | No | Yes |
| `BasicMathPackage` | Basic math functions (e.g. `sin`, `sqrt`) | No | Yes |
| `BasicArrayPackage` | Basic [array] functions (not available under `no_index`) | No | Yes |
| `BasicMapPackage` | Basic [object map] functions (not available under `no_object`) | No | Yes |
| `EvalPackage` | Disable [`eval`] | No | No |
| `CorePackage` | Basic essentials | Yes | Yes |
| `StandardPackage` | Standard library (default for `Engine::new`) | No | Yes |
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).
Once a package is created (e.g. via `new`), it can be _shared_ (via `get`) among multiple instances of [`Engine`],
even across threads (under [`sync`]). Therefore, a package only has to be created _once_.
Difference Between a Package and a Module
----------------------------------------
Packages are actually implemented as [modules], so they share a lot of behavior and characteristics.
The main difference is that a package loads under the _global_ namespace, while a module loads under its own
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
the `import` statement).
Custom packages can also be created. See the macro [`def_package!`](https://docs.rs/rhai/0.13.0/rhai/macro.def_package.html).

View File

@ -0,0 +1,39 @@
Built-In Packages
================
{{#include ../../links.md}}
`Engine::new` creates an [`Engine`] with the `StandardPackage` loaded.
`Engine::new_raw` creates an [`Engine`] with _no_ package loaded.
| Package | Description | In `Core` | In `Standard` |
| ---------------------- | ------------------------------------------------------------------------------------------------------ | :-------: | :-----------: |
| `ArithmeticPackage` | Arithmetic operators (e.g. `+`, `-`, `*`, `/`) for numeric types that are not built in (e.g. `u16`) | Yes | Yes |
| `BasicIteratorPackage` | Numeric ranges (e.g. `range(1, 10)`) | Yes | Yes |
| `LogicPackage` | Logical and comparison operators (e.g. `==`, `>`) for numeric types that are not built in (e.g. `u16`) | Yes | Yes |
| `BasicStringPackage` | Basic string functions (e.g. `print`, `debug`, `len`) that are not built in | Yes | Yes |
| `BasicTimePackage` | Basic time functions (e.g. [timestamps]) | Yes | Yes |
| `MoreStringPackage` | Additional string functions, including converting common types to string | No | Yes |
| `BasicMathPackage` | Basic math functions (e.g. `sin`, `sqrt`) | No | Yes |
| `BasicArrayPackage` | Basic [array] functions (not available under `no_index`) | No | Yes |
| `BasicMapPackage` | Basic [object map] functions (not available under `no_object`) | No | Yes |
| `EvalPackage` | Disable [`eval`] | No | No |
| `CorePackage` | Basic essentials | Yes | Yes |
| `StandardPackage` | Standard library (default for `Engine::new`) | No | Yes |
Load the `CorePackage`
---------------------
If only minimal functionalities is required, load the `CorePackage` instead:
```rust
use rhai::Engine;
use rhai::packages::{Package, CorePackage};
let mut engine = Engine::new_raw();
let package = CorePackage::new();
engine.load_package(package.get());
```

View File

@ -0,0 +1,47 @@
Create a Custom Package
======================
{{#include ../../links.md}}
Sometimes specific functionalities are needed, so custom packages can be created.
The macro `rhai::def_package!` is used to create a new custom package.
Macro Parameters
---------------
`def_package!(root:package_name:description, variable, block)`
* `root` - root namespace, usually `"rhai"`.
* `package_name` - name of the package, usually ending in `Package`.
* `description` - doc comment for the package.
* `variable` - a variable name holding a reference to the [module] that is to form the package.
* `block` - a code block that initializes the package.
```rust
// Import necessary types and traits.
use rhai::{
def_package,
packages::Package,
packages::{ArithmeticPackage, BasicArrayPackage, BasicMapPackage, LogicPackage}
};
// 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);
// Register additional Rust functions using the standard 'set_fn_XXX' module API.
module.set_fn_1("foo", |s: ImmutableString| {
Ok(foo(s.into_owned()))
});
});
```