Add FnNamespace for module functions.

This commit is contained in:
Stephen Chung
2020-11-17 12:23:53 +08:00
parent a19865d811
commit 038e3c2554
20 changed files with 264 additions and 171 deletions

View File

@@ -3,7 +3,7 @@
{{#include ../links.md}}
Iterating through a range or an [array], or any type with a registered _iterator_,
Iterating through a range or an [array], or any type with a registered _type iterator_,
is provided by the `for` ... `in` loop.
Like C, `continue` can be used to skip to the next iteration, by-passing all following statements;

View File

@@ -6,7 +6,7 @@ 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 holds a collection of functions, variables, iterators and sub-modules.
A module is of the type `Module` and holds a collection of functions, variables, type iterators and sub-modules.
It may be created entirely from Rust functions, or it may encapsulate a Rhai script together with the functions
and variables defined by that script.

View File

@@ -91,7 +91,7 @@ Many script-oriented exceptions can be caught via `try` ... `catch`:
| [Array]/[string] indexing out-of-bounds | error message [string] |
| Indexing with an inappropriate data type | error message [string] |
| Error in a dot expression | error message [string] |
| `for` statement without an iterator | error message [string] |
| `for` statement without an type iterator | error message [string] |
| Error in an `in` expression | error message [string] |
| Data race detected | error message [string] |

View File

@@ -37,7 +37,7 @@ mod MyEnumModule {
MyEnum::Baz(val1, val2)
}
// Access to fields
#[rhai_fn(get = "enum_type")]
#[rhai_fn(global, get = "enum_type")]
pub fn get_type(a: &mut MyEnum) -> String {
match a {
MyEnum::Foo => "Foo".to_string(),
@@ -45,7 +45,7 @@ mod MyEnumModule {
MyEnum::Baz(_, _) => "Baz".to_string()
}
}
#[rhai_fn(get = "field_0")]
#[rhai_fn(global, get = "field_0")]
pub fn get_field_0(a: &mut MyEnum) -> Dynamic {
match a {
MyEnum::Foo => Dynamic::UNIT,
@@ -53,7 +53,7 @@ mod MyEnumModule {
MyEnum::Baz(x, _) => Dynamic::from(x)
}
}
#[rhai_fn(get = "field_1")]
#[rhai_fn(global, get = "field_1")]
pub fn get_field_1(a: &mut MyEnum) -> Dynamic {
match a {
MyEnum::Foo | MyEnum::Bar(_) => Dynamic::UNIT,
@@ -61,41 +61,41 @@ mod MyEnumModule {
}
}
// Printing
#[rhai(name = "to_string", name = "print", name = "debug")]
#[rhai(global, name = "to_string", name = "print", name = "debug")]
pub fn to_string(a: &mut MyEnum) -> String {
format!("{:?}", a))
}
#[rhai_fn(name = "+")]
#[rhai_fn(global, name = "+")]
pub fn add_to_str(s: &str, a: MyEnum) -> String {
format!("{}{:?}", s, a))
}
#[rhai_fn(name = "+")]
#[rhai_fn(global, name = "+")]
pub fn add_str(a: &mut MyEnum, s: &str) -> String {
format!("{:?}", a).push_str(s))
}
#[rhai_fn(name = "+=")]
#[rhai_fn(global, name = "+=")]
pub fn append_to_str(s: &mut ImmutableString, a: MyEnum) -> String {
s += a.to_string())
}
// '==' and '!=' operators
#[rhai_fn(name = "==")]
#[rhai_fn(global, name = "==")]
pub fn eq(a: &mut MyEnum, b: MyEnum) -> bool {
a == &b
}
#[rhai_fn(name = "!=")]
#[rhai_fn(global, name = "!=")]
pub fn neq(a: &mut MyEnum, b: MyEnum) -> bool {
a != &b
}
// Array functions
#[rhai_fn(name = "push")]
#[rhai_fn(global, name = "push")]
pub fn append_to_array(list: &mut Array, item: MyEnum) {
list.push(Dynamic::from(item)));
}
#[rhai_fn(name = "+=")]
#[rhai_fn(global, name = "+=")]
pub fn append_to_array_op(list: &mut Array, item: MyEnum) {
list.push(Dynamic::from(item)));
}
#[rhai_fn(name = "insert")]
#[rhai_fn(global, name = "insert")]
pub fn insert_to_array(list: &mut Array, position: i64, item: MyEnum) {
if position <= 0 {
list.insert(0, Dynamic::from(item));
@@ -105,7 +105,7 @@ mod MyEnumModule {
list.insert(position as usize, Dynamic::from(item));
}
}
#[rhai_fn(name = "pad")]
#[rhai_fn(global, name = "pad")]
pub fn pad_array(list: &mut Array, len: i64, item: MyEnum) {
if len as usize > list.len() { list.resize(len as usize, item); }
}

View File

@@ -54,6 +54,8 @@ mod my_module {
mystic_number()
}
// This function will be registered as 'increment'.
// It will also be exposed to the global namespace since 'global' is set.
#[rhai_fn(global)]
pub fn increment(num: &mut i64) {
*num += 1;
}
@@ -159,10 +161,12 @@ service::increment(x);
x == 43;
```
`Engine::register_module` also exposes all _methods_ and _iterators_ from the module to the
_global_ namespace, so [getters/setters] and [indexers] for [custom types] work as expected.
Any functions (usually _methods_) defined in the module with `#[rhai_fn(global)]`, as well as
all _type iterators_, are automatically exposed to the _global_ namespace, so iteration,
[getters/setters] and [indexers] for [custom types] can work as expected.
Therefore, in the example able, `increment` works fine when called in method-call style:
Therefore, in the example above, the `increment` method (defined with `#[rhai_fn(global)]`)
works fine when called in method-call style:
```rust
let x = 42;

View File

@@ -60,17 +60,22 @@ engine.register_module("calc", module);
engine.eval::<i64>("calc::inc(41)")? == 42; // refer to the 'Calc' module
```
`Engine::register_module` also exposes all _methods_ and _iterators_ from the module to the
_global_ namespace, so [getters/setters] and [indexers] for [custom types] work as expected.
`Module::set_fn_namespace` can expose functions (usually _methods_) in the module
to the _global_ namespace, so [getters/setters] and [indexers] for [custom types] can work as expected.
Type iterators, because of their special nature, are always exposed to the _global_ namespace.
```rust
use rhai::{Engine, Module};
use rhai::{Engine, Module, FnNamespace};
let mut module = Module::new(); // new module
module.set_fn_1_mut("inc", // add new method
let hash = module.set_fn_1_mut("inc", // add new method
|x: &mut i64| Ok(x+1)
);
// Expose 'inc' to the global namespace (default is 'Internal')
module.set_fn_namespace(hash, FnNamespace::Global);
// Load the module into the Engine as a sub-module named 'calc'
let mut engine = Engine::new();
engine.register_module("calc", module);

View File

@@ -6,7 +6,7 @@ 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 holds a collection of functions, variables, iterators and sub-modules.
A module is of the type `Module` and holds a collection of functions, variables, type iterators and sub-modules.
It may be created entirely from Rust functions, or it may encapsulate a Rhai script together with the functions
and variables defined by that script.