diff --git a/doc/src/about/features.md b/doc/src/about/features.md
index bcfe5a6e..2cef773b 100644
--- a/doc/src/about/features.md
+++ b/doc/src/about/features.md
@@ -14,8 +14,8 @@ Easy
* Easily [call a script-defined function]({{rootUrl}}/engine/call-fn.md) from Rust.
-* Very few additional dependencies (right now only [`smallvec`](https://crates.io/crates/smallvec/));
- for [`no-std`] builds, a number of additional dependencies are pulled in to provide for functionalities that used to be in `std`.
+* Very few additional dependencies - right now only [`smallvec`](https://crates.io/crates/smallvec/) plus crates for procedural macros;
+ for [`no-std`] and `WASM` builds, a number of additional dependencies are pulled in to provide for missing functionalities.
Fast
----
diff --git a/doc/src/about/index.md b/doc/src/about/index.md
index cf021da5..2c6efcc8 100644
--- a/doc/src/about/index.md
+++ b/doc/src/about/index.md
@@ -3,6 +3,8 @@ What is Rhai
{{#include ../links.md}}
+
+
Rhai is an embedded scripting language and evaluation engine for Rust that gives a safe and easy way
to add scripting to any application.
@@ -13,3 +15,27 @@ Versions
This Book is for version **{{version}}** of Rhai.
For the latest development version, see [here]({{rootUrl}}/vnext/).
+
+
+Etymology of the name "Rhai"
+---------------------------
+
+### As per Rhai's author Johnathan Turner
+
+In the beginning there was [ChaiScript](http://chaiscript.com),
+which is an embedded scripting language for C++.
+Originally it was intended to be a scripting language similar to **JavaScript**.
+
+With java being a kind of hot beverage, the new language was named after
+another hot beverage - **Chai**, which is the word for "tea" in many world languages
+and, in particular, a popular kind of milk tea consumed in India.
+
+Later, when the novel implementation technique behind ChaiScript was ported from C++ to Rust,
+logically the `C` was changed to an `R` to make it "RhaiScript", or just "Rhai".
+
+### On the origin of the temporary Rhai logo
+
+One of Rhai's maintainers, Stephen Chung, was thinking about a logo when he accidentally
+came across a copy of _Catcher in the Rye_ in a restaurant. The rest was history.
+
+It is temporary until it becomes official, that is...
diff --git a/doc/src/about/license.md b/doc/src/about/license.md
index a1f24339..8465ec4c 100644
--- a/doc/src/about/license.md
+++ b/doc/src/about/license.md
@@ -3,13 +3,11 @@ Licensing
{{#include ../links.md}}
-Rhai is licensed under either:
+Rhai is licensed under either of the following, at your choice:
* [Apache License, Version 2.0]({{repoHome}}/LICENSE-APACHE.txt), or
-* [MIT license]({{repoHome}}/LICENSE-MIT.txt)
-
-at your choice.
+* [MIT license]({{repoHome}}/LICENSE-MIT.txt).
Unless explicitly stated otherwise, any contribution intentionally submitted for inclusion in this crate,
as defined in the Apache-2.0 license, shall be dual-licensed as above,
diff --git a/doc/src/about/non-design.md b/doc/src/about/non-design.md
index 7f40614e..720a7c12 100644
--- a/doc/src/about/non-design.md
+++ b/doc/src/about/non-design.md
@@ -14,7 +14,7 @@ It doesn't attempt to be a new language. For example:
There is, however, a built-in [object map] type which is adequate for most uses.
It is possible to simulate [object-oriented programming (OOP)][OOP] by storing [function pointers]
- in [object map] properties, turning them into _methods_.
+ or [closures] in [object map] properties, turning them into _methods_.
* No first-class functions - Code your functions in Rust instead, and register them with Rhai.
@@ -22,22 +22,32 @@ It doesn't attempt to be a new language. For example:
* No garbage collection - this should be expected, so...
-* No closures - do your closure magic in Rust instead; [turn a Rhai scripted function into a Rust closure]({{rootUrl}}/engine/call-fn.md).
+* No first-class closures - do your closure magic in Rust instead: [turn a Rhai scripted function into a Rust closure]({{rootUrl}}/engine/call-fn.md).
- But you can [curry][currying] a [function pointer] with arguments to simulate it somewhat.
+ There is, however, support for simulated [closures] via [currying] a [function pointer] with
+ captured shared variables.
-* No byte-codes/JIT - Rhai has an AST-walking interpreter which will not win any speed races. The purpose of Rhai is not
- to be extremely _fast_, but to make it as easy as possible to integrate with native Rust applications.
+* No byte-codes/JIT - Rhai has an AST-walking interpreter which will not win any speed races.
+ The purpose of Rhai is not to be extremely _fast_, but to make it as easy as possible to
+ integrate with native Rust applications.
+
+* No formal language grammar - Rhai uses a hand-coded lexer, a hand-coded top-down recursive-descent parser
+ for statements and a Pratt parser for expressions.
+
+ This lack of formalism allows the parser itself to be exposed as a service in order to support
+ [disabling keywords/operators][disable keywords and operators], adding [custom operators],
+ and defining [custom syntax].
Do Not Write The Next 4D VR Game in Rhai
---------------------------------------
-Due to this intended usage, Rhai deliberately keeps the language simple and small by omitting advanced language features
-such as classes, inheritance, first-class functions, closures, concurrency, byte-codes, JIT etc.
+Due to this intended usage, Rhai deliberately keeps the language simple and small by omitting
+advanced language features such as classes, inheritance, first-class functions, closures,
+concurrency, byte-codes VM, JIT etc.
-Avoid the temptation to write full-fledge application logic entirely in Rhai - that use case is best fulfilled by
-more complete languages such as JavaScript or Lua.
+Avoid the temptation to write full-fledge application logic entirely in Rhai -
+that use case is best fulfilled by more complete languages such as JavaScript or Lua.
Thin Dynamic Wrapper Layer Over Rust Code
@@ -47,7 +57,8 @@ In actual practice, it is usually best to expose a Rust API into Rhai for script
All the core functionalities should be written in Rust, with Rhai being the dynamic _control_ layer.
-This is similar to some dynamic languages where most of the core functionalities reside in a C/C++ standard library.
+This is similar to some dynamic languages where most of the core functionalities reside in a C/C++
+standard library.
Another similar scenario is a web front-end driving back-end services written in a systems language.
In this case, JavaScript takes the role of Rhai while the back-end language, well... it can actually also be Rust.
diff --git a/doc/src/about/related.md b/doc/src/about/related.md
index defc29e4..8174676b 100644
--- a/doc/src/about/related.md
+++ b/doc/src/about/related.md
@@ -5,7 +5,7 @@ Related Resources
Other online documentation resources for Rhai:
-* [`crates.io`](https://crates.io/crates/rhai/) - Rhai crate
+* [`crates.io`](https://crates.io/crates/rhai) - Rhai crate
* [`DOCS.RS`](https://docs.rs/rhai) - Rhai API documentation
@@ -15,6 +15,6 @@ Other online documentation resources for Rhai:
Other cool projects to check out:
-* [ChaiScript](http://chaiscript.com/) - A strong inspiration for Rhai. An embedded scripting language for C++ that I helped created many moons ago, now being led by my cousin.
+* [ChaiScript](http://chaiscript.com) - A strong inspiration for Rhai. An embedded scripting language for C++.
* Check out the list of [scripting languages for Rust](https://github.com/rust-unofficial/awesome-rust#scripting) on [awesome-rust](https://github.com/rust-unofficial/awesome-rust)
diff --git a/doc/src/about/targets.md b/doc/src/about/targets.md
index 70124e61..a68430a0 100644
--- a/doc/src/about/targets.md
+++ b/doc/src/about/targets.md
@@ -10,3 +10,9 @@ The following targets and builds are support by Rhai:
* WebAssembly ([WASM])
* [`no-std`]
+
+
+Minimum Rust Version
+--------------------
+
+The minimum version of Rust required to compile Rhai is `1.45.0`.
diff --git a/doc/src/advanced.md b/doc/src/advanced.md
index 0b9e170e..482ae621 100644
--- a/doc/src/advanced.md
+++ b/doc/src/advanced.md
@@ -13,8 +13,6 @@ This section covers advanced features such as:
* [Script optimization].
-* [Domain-Specific Languages][DSL].
-
* Low-level [function registration API]({{rootUrl}}/rust/register-raw.md)
-* The dreaded (or beloved for those with twisted tastes) [`eval`] statement.
+* [Domain-Specific Languages][DSL].
diff --git a/rhai_logo.png b/doc/src/images/rhai_logo.png
similarity index 100%
rename from rhai_logo.png
rename to doc/src/images/rhai_logo.png
diff --git a/doc/src/language/fn-capture.md b/doc/src/language/fn-capture.md
index 08052826..58ce811a 100644
--- a/doc/src/language/fn-capture.md
+++ b/doc/src/language/fn-capture.md
@@ -49,8 +49,8 @@ f.call!(41); // <- syntax error: capturing is not allowed in method-c
No Mutations
------------
-Variables in the calling scope are captured as copies.
-Changes to them do not reflect back to the calling scope.
+Variables in the calling scope are captured as cloned copies.
+Changes to them do **not** reflect back to the calling scope.
Rhai functions remain _pure_ in the sense that they can never mutate their environment.
diff --git a/doc/src/language/fn-namespaces.md b/doc/src/language/fn-namespaces.md
index e6844f9a..11ce1107 100644
--- a/doc/src/language/fn-namespaces.md
+++ b/doc/src/language/fn-namespaces.md
@@ -15,10 +15,10 @@ forming a new, combined, group of functions.
In general, there are two types of _namespaces_ where functions are looked up:
-| Namespace | Source | Lookup method | How Many |
-| --------- | ---------------------------------------------------------------------- | --------------------------------- | :----------------------: |
-| Global | `Engine::register_XXX` API, [`AST`] being evaluated, [packages] loaded | simple function name | one |
-| Module | [`Module`] | namespace-qualified function name | as many as [`import`]-ed |
+| Namespace | Source | Lookup method | Sub-modules? | Variables? |
+| --------- | ------------------------------------------------------------------------------------- | ------------------------------ | :----------: | :--------: |
+| Global | 1) `Engine::register_XXX` API
2) [`AST`] being evaluated
3) [packages] loaded | simple function name | ignored | ignored |
+| Module | [`Module`] | module-qualified function name | yes | yes |
Global Namespace
diff --git a/doc/src/language/fn-ptr.md b/doc/src/language/fn-ptr.md
index 8c294a83..e377e7e6 100644
--- a/doc/src/language/fn-ptr.md
+++ b/doc/src/language/fn-ptr.md
@@ -15,9 +15,10 @@ Built-in methods
The following standard methods (mostly defined in the [`BasicFnPackage`][packages] but excluded if
using a [raw `Engine`]) operate on [strings]:
-| Function | Parameter(s) | Description |
-| -------------------------- | ------------ | --------------------------------------------------------------------- |
-| `name` method and property | _none_ | returns the name of the function encapsulated by the function pointer |
+| Function | Parameter(s) | Description |
+| -------------------------- | ------------ | ---------------------------------------------------------------------------- |
+| `name` method and property | _none_ | returns the name of the function encapsulated by the function pointer |
+| `call` | _arguments_ | calls the function matching the function pointer's name with the _arguments_ |
Examples
@@ -143,7 +144,9 @@ to a function call while binding the object in the method call to the `this` poi
To achieve this, pass the `FnPtr` value as the _first_ argument to `call`:
```rust
-fn add(x) { this += x; } // define function which uses 'this'
+fn add(x) { // define function which uses 'this'
+ this += x;
+}
let func = Fn("add"); // function pointer to 'add'
diff --git a/doc/src/language/for.md b/doc/src/language/for.md
index 493d8759..c60372a8 100644
--- a/doc/src/language/for.md
+++ b/doc/src/language/for.md
@@ -12,8 +12,13 @@ Like C, `continue` can be used to skip to the next iteration, by-passing all fol
To loop through a number sequence (with or without steps), use the `range` function to
return a numeric iterator.
+
+Iterate Through Strings
+-----------------------
+
+Iterating through a [string] yields characters.
+
```rust
-// Iterate through string, yielding characters
let s = "hello, world!";
for ch in s {
@@ -23,8 +28,15 @@ for ch in s {
if x == '@' { break; } // break out of for loop
}
+```
-// Iterate through array
+
+Iterate Through Arrays
+----------------------
+
+Iterating through an [array] yields cloned _copies_ of each element.
+
+```rust
let array = [1, 3, 5, 7, 9, 42];
for x in array {
@@ -34,8 +46,17 @@ for x in array {
if x == 42 { break; } // break out of for loop
}
+```
-// The 'range' function allows iterating from first to last-1
+
+Iterate Through Numeric Ranges
+-----------------------------
+
+The `range` function allows iterating through a range of numbers
+(not including the last number).
+
+```rust
+// Iterate starting from 0 and stopping at 49.
for x in range(0, 50) {
if x > 10 { continue; } // skip to the next iteration
@@ -44,7 +65,7 @@ for x in range(0, 50) {
if x == 42 { break; } // break out of for loop
}
-// The 'range' function also takes a step
+// The 'range' function also takes a step.
for x in range(0, 50, 3) { // step by 3
if x > 10 { continue; } // skip to the next iteration
@@ -52,8 +73,18 @@ for x in range(0, 50, 3) { // step by 3
if x == 42 { break; } // break out of for loop
}
+```
-// Iterate through object map
+
+Iterate Through Object Maps
+--------------------------
+
+Two functions, `keys` and `values`, return [arrays] containing cloned _copies_
+of all property names and values of an [object map], respectively.
+
+These [arrays] can be iterated.
+
+```rust
let map = #{a:1, b:3, c:5, d:7, e:9};
// Property names are returned in unsorted, random order
diff --git a/doc/src/language/functions.md b/doc/src/language/functions.md
index 3bd15cd0..5b9498a6 100644
--- a/doc/src/language/functions.md
+++ b/doc/src/language/functions.md
@@ -42,19 +42,6 @@ add2(42) == 44;
```
-No Access to External Scope
---------------------------
-
-Functions are not _closures_. They do not capture the calling environment and can only access their own parameters.
-They cannot access variables external to the function itself.
-
-```rust
-let x = 42;
-
-fn foo() { x } // <- syntax error: variable 'x' doesn't exist
-```
-
-
Global Definitions Only
----------------------
@@ -77,24 +64,52 @@ fn do_addition(x) {
```
-Use Before Definition
---------------------
+No Access to External Scope
+--------------------------
+
+Functions are not _closures_. They do not capture the calling environment
+and can only access their own parameters.
+They cannot access variables external to the function itself.
+
+```rust
+let x = 42;
+
+fn foo() { x } // <- syntax error: variable 'x' doesn't exist
+```
+
+
+But Can Call Other Functions
+---------------------------
+
+All functions in the same [`AST`] can call each other.
+
+```rust
+fn foo(x) { x + 1 } // function defined in the global namespace
+
+fn bar(x) { foo(x) } // OK! function 'foo' can be called
+```
+
+
+Use Before Definition Allowed
+----------------------------
Unlike C/C++, functions in Rhai can be defined _anywhere_ at global level.
+
A function does not need to be defined prior to being used in a script;
a statement in the script can freely call a function defined afterwards.
This is similar to Rust and many other modern languages, such as JavaScript's `function` keyword.
-Arguments Passed by Value
-------------------------
+Arguments are Passed by Value
+----------------------------
-Functions defined in script always take [`Dynamic`] parameters (i.e. the parameter can be of any type).
+Functions defined in script always take [`Dynamic`] parameters (i.e. they can be of any types).
Therefore, functions with the same name and same _number_ of parameters are equivalent.
-It is important to remember that all arguments are passed by _value_, so all Rhai script-defined functions
-are _pure_ (i.e. they never modify their arguments).
+All arguments are passed by _value_, so all Rhai script-defined functions are _pure_
+(i.e. they never modify their arguments).
+
Any update to an argument will **not** be reflected back to the caller.
```rust
@@ -113,8 +128,8 @@ x == 500; // 'x' is NOT changed!
`this` - Simulating an Object Method
-----------------------------------
-Functions can also be called in method-call style. When this is the case, the keyword '`this`'
-binds to the object in the method call and can be changed.
+Script-defined functions can also be called in method-call style.
+When this happens, the keyword '`this`' binds to the object in the method call and can be changed.
```rust
fn change() { // not that the object does not need a parameter
diff --git a/doc/src/language/method.md b/doc/src/language/method.md
index 01633350..6ca91a99 100644
--- a/doc/src/language/method.md
+++ b/doc/src/language/method.md
@@ -39,8 +39,8 @@ array[0].update(); // <- call in method-call style will update 'a'
**IMPORTANT: Rhai does NOT support normal references (i.e. `&T`) as parameters.**
-Number of Parameters
---------------------
+Number of Parameters in Methods
+------------------------------
Native Rust methods registered with an [`Engine`] take _one additional parameter_ more than
an equivalent method coded in script, where the object is accessed via the `this` pointer instead.
@@ -53,15 +53,43 @@ The following table illustrates the differences:
| Rhai script | _N_ | `this` (of type `&mut T`) | `Fn(x: U, y: V)` |
-`&mut` is Efficient, Except for `ImmutableString`
------------------------------------------------
+`&mut` is Efficient, Except for `&mut ImmutableString`
+----------------------------------------------------
Using a `&mut` first parameter is highly encouraged when using types that are expensive to clone,
even when the intention is not to mutate that argument, because it avoids cloning that argument value.
-For example, the `len` method of an [array] has the signature: `Fn(&mut Array) -> INT`.
-The array itself is not modified in any way, but using a `&mut` parameter avoids a cloning that would
-otherwise have happened if the signature were `Fn(Array) -> INT`.
+Even when a function is never intended to be a method - for example an operator,
+it is still sometimes beneficial to make it method-like (i.e. with a first `&mut` parameter)
+if the first parameter is not modified.
+
+For types that are expensive to clone (remember, all function calls are passed cloned
+copies of argument values), this may result in a significant performance boost.
For primary types that are cheap to clone (e.g. those that implement `Copy`), including `ImmutableString`,
this is not necessary.
+
+```rust
+// This is a type that is very expensive to clone.
+#[derive(Debug, Clone)]
+struct VeryComplexType { ... }
+
+// Calculate some value by adding 'VeryComplexType' with an integer number.
+fn do_add(obj: &VeryComplexType, offset: i64) -> i64 {
+ ...
+}
+
+engine
+ .register_type::()
+ .register_fn("+", add_pure /* or add_method*/);
+
+// Very expensive to call, as the 'VeryComplexType' is cloned before each call.
+fn add_pure(obj: VeryComplexType, offset: i64) -> i64 {
+ do_add(obj, offset)
+}
+
+// Efficient to call, as only a reference to the 'VeryComplexType' is passed.
+fn add_method(obj: &mut VeryComplexType, offset: i64) -> i64 {
+ do_add(obj, offset)
+}
+```
diff --git a/doc/src/language/strings-chars.md b/doc/src/language/strings-chars.md
index a402d485..e9f5e074 100644
--- a/doc/src/language/strings-chars.md
+++ b/doc/src/language/strings-chars.md
@@ -29,7 +29,15 @@ Modifying an `ImmutableString` causes it first to be cloned, and then the modifi
`ImmutableString` should be used in place of `String` for function parameters because using
`String` is very inefficient (the `String` argument is cloned during every call).
-A alternative is to use `&str` which maps straight to `ImmutableString`.
+A alternative is to use `&str` which de-sugars to `ImmutableString`.
+
+```rust
+fn slow(s: String) -> i64 { ... } // string is cloned each call
+
+fn fast1(s: ImmutableString) -> i64 { ... } // cloning 'ImmutableString' is cheap
+
+fn fast2(s: &str) -> i64 { ... } // de-sugars to above
+```
String and Character Literals
diff --git a/doc/src/language/throw.md b/doc/src/language/throw.md
index 97b74182..0b6c479e 100644
--- a/doc/src/language/throw.md
+++ b/doc/src/language/throw.md
@@ -16,8 +16,9 @@ if some_bad_condition_has_happened {
throw; // defaults to empty exception text: ""
```
-Exceptions thrown via `throw` in the script can be captured by matching `Err(Box)`
-with the exception text captured by the first parameter.
+Exceptions thrown via `throw` in the script can be captured in Rust by matching
+`Err(Box)` with the exception text
+captured by `reason`.
```rust
let result = engine.eval::(r#"
diff --git a/doc/src/patterns/config.md b/doc/src/patterns/config.md
index 3017bb1d..6af3ae10 100644
--- a/doc/src/patterns/config.md
+++ b/doc/src/patterns/config.md
@@ -46,15 +46,22 @@ struct Config {
### Make Shared Object
```rust
-let config: Rc> = Rc::new(RefCell::new(Default::default()));
+pub type SharedConfig = Rc>;
+```
+
+Note: Use `Arc>` or `Arc>` when using the [`sync`] feature because the function
+must then be `Send + Sync`.
+
+```rust
+let config: SharedConfig = Rc::new(RefCell::new(Default::default()));
```
### Register Config API
The trick to building a Config API is to clone the shared configuration object and
-move it into each function registration as a closure.
+move it into each function registration via a closure.
-It is not possible to use a [plugin module] to achieve this, so each function must
+Therefore, it is not possible to use a [plugin module] to achieve this, and each function must
be registered one after another.
```rust
diff --git a/doc/src/patterns/control.md b/doc/src/patterns/control.md
index c3624442..8743d260 100644
--- a/doc/src/patterns/control.md
+++ b/doc/src/patterns/control.md
@@ -35,7 +35,7 @@ but only through exposing an abstract API primarily made up of functions.
Use this when the API is relatively simple and clean, and the number of functions is small enough.
-For a complex API involving lots of functions, or an API that is object-based,
+For a complex API involving lots of functions, or an API that has a clear object structure,
use the [Singleton Command Object]({{rootUrl}}/patterns/singleton.md) pattern instead.
@@ -59,15 +59,22 @@ impl EnergizerBunny {
### Wrap API in Shared Object
```rust
-let bunny: Rc> = Rc::new(RefCell::(EnergizerBunny::new()));
+pub type SharedBunny = Rc>;
+```
+
+Note: Use `Arc>` or `Arc>` when using the [`sync`] feature because the function
+must then be `Send + Sync`.
+
+```rust
+let bunny: SharedBunny = Rc::new(RefCell::(EnergizerBunny::new()));
```
### Register Control API
The trick to building a Control API is to clone the shared API object and
-move it into each function registration as a closure.
+move it into each function registration via a closure.
-It is not possible to use a [plugin module] to achieve this, so each function must
+Therefore, it is not possible to use a [plugin module] to achieve this, and each function must
be registered one after another.
```rust
diff --git a/doc/src/patterns/singleton.md b/doc/src/patterns/singleton.md
index fa7c9d75..877180df 100644
--- a/doc/src/patterns/singleton.md
+++ b/doc/src/patterns/singleton.md
@@ -41,7 +41,7 @@ wrapping the system in a shared, interior-mutated object.
This is the other way which involves directly exposing the data structures of the external system
as a name singleton object in the scripting space.
-Use this when the API is complex and clearly object-based.
+Use this when the API is complex but has a clear object structure.
For a relatively simple API that is action-based and not object-based,
use the [Control Layer]({{rootUrl}}/patterns/control.md) pattern instead.
@@ -68,13 +68,16 @@ impl EnergizerBunny {
### Wrap Command Object Type as Shared
```rust
-let SharedBunnyType = Rc>;
+pub type SharedBunny = Rc>;
```
+Note: Use `Arc>` or `Arc>` when using the [`sync`] feature because the function
+must then be `Send + Sync`.
+
### Register the Custom Type
```rust
-engine.register_type_with_name::("EnergizerBunny");
+engine.register_type_with_name::("EnergizerBunny");
```
### Develop a Plugin with Methods and Getters/Setters
@@ -82,18 +85,18 @@ engine.register_type_with_name::("EnergizerBunny");
The easiest way to develop a complete set of API for a [custom type] is via a [plugin module].
```rust
-use rhai::plugins::*;
+use rhai::plugin::*;
#[export_module]
pub mod bunny_api {
pub const MAX_SPEED: i64 = 100;
#[rhai_fn(get = "power")]
- pub fn get_power(bunny: &mut SharedBunnyType) -> bool {
+ pub fn get_power(bunny: &mut SharedBunny) -> bool {
bunny.borrow().is_going()
}
#[rhai_fn(set = "power")]
- pub fn set_power(bunny: &mut SharedBunnyType, on: bool) {
+ pub fn set_power(bunny: &mut SharedBunny, on: bool) {
if on {
if bunny.borrow().is_going() {
println!("Still going...");
@@ -109,7 +112,7 @@ pub mod bunny_api {
}
}
#[rhai_fn(get = "speed")]
- pub fn get_speed(bunny: &mut SharedBunnyType) -> i64 {
+ pub fn get_speed(bunny: &mut SharedBunny) -> i64 {
if bunny.borrow().is_going() {
bunny.borrow().get_speed()
} else {
@@ -117,7 +120,7 @@ pub mod bunny_api {
}
}
#[rhai_fn(set = "speed", return_raw)]
- pub fn set_speed(bunny: &mut SharedBunnyType, speed: i64)
+ pub fn set_speed(bunny: &mut SharedBunny, speed: i64)
-> Result>
{
if speed <= 0 {
@@ -131,12 +134,12 @@ pub mod bunny_api {
Ok(().into())
}
}
- pub fn turn_left(bunny: &mut SharedBunnyType) {
+ pub fn turn_left(bunny: &mut SharedBunny) {
if bunny.borrow().is_going() {
bunny.borrow_mut().turn(true);
}
}
- pub fn turn_right(bunny: &mut SharedBunnyType) {
+ pub fn turn_right(bunny: &mut SharedBunny) {
if bunny.borrow().is_going() {
bunny.borrow_mut().turn(false);
}
@@ -149,7 +152,7 @@ engine.load_package(exported_module!(bunny_api));
### Push Constant Command Object into Custom Scope
```rust
-let bunny: SharedBunnyType = Rc::new(RefCell::(EnergizerBunny::new()));
+let bunny: SharedBunny = Rc::new(RefCell::(EnergizerBunny::new()));
let mut scope = Scope::new();
diff --git a/doc/src/plugins/function.md b/doc/src/plugins/function.md
index 388c9b84..396f53e1 100644
--- a/doc/src/plugins/function.md
+++ b/doc/src/plugins/function.md
@@ -29,7 +29,7 @@ To register the plugin function, simply call `register_exported_fn!`. The name
any text string, so it is possible to register _overloaded_ functions as well as operators.
```rust
-use rhai::plugins::*; // import macros
+use rhai::plugin::*; // import macros
#[export_fn]
fn increment(num: &mut i64) {
@@ -55,7 +55,7 @@ A syntax error is generated if the function with `#[rhai_fn(return_raw)]` does n
have the appropriate return type.
```rust
-use rhai::plugins::*; // import macros
+use rhai::plugin::*; // a "prelude" import for macros
#[export_fn]
#[rhai_fn(return_raw)]
diff --git a/doc/src/plugins/index.md b/doc/src/plugins/index.md
index 04fb1d35..1e3f3cc9 100644
--- a/doc/src/plugins/index.md
+++ b/doc/src/plugins/index.md
@@ -9,5 +9,5 @@ functionality.
Instead of using the large `Engine::register_XXX` API or the parallel `Module::set_fn_XXX` API,
a _plugin_ simplifies the work of creating and registering new functionality in an [`Engine`].
-Plugins are processed via a set of procedural macros under the `rhai::plugins` module. These
+Plugins are processed via a set of procedural macros under the `rhai::plugin` module. These
allow registering Rust functions directly in the Engine, or adding Rust modules as packages.
diff --git a/doc/src/plugins/module.md b/doc/src/plugins/module.md
index 97e2ffa6..a083fb08 100644
--- a/doc/src/plugins/module.md
+++ b/doc/src/plugins/module.md
@@ -4,6 +4,20 @@ Export a Rust Module to Rhai
{{#include ../links.md}}
+Prelude
+-------
+
+When using the plugins system, the entire `rhai::plugin` module must be imported as a prelude
+because code generated will these imports.
+
+```rust
+use rhai::plugin::*;
+```
+
+
+`#[export_module]` and `exported_module!`
+----------------------------------------
+
When applied to a Rust module, the `#[export_module]` attribute generates the necessary
code and metadata to allow Rhai access to its public (i.e. marked `pub`) functions, constants
and sub-modules.
@@ -14,18 +28,11 @@ and is custom fit to each exported item.
This Rust module can then either be loaded into an [`Engine`] as a normal [module] or
registered as a [custom package]. This is done by using the `exported_module!` macro.
-
-`#[export_module]` and `exported_module!`
-----------------------------------------
-
-Apply `#[export_module]` onto a Rust module to register automatically construct a Rhai [module],
-which can then be loaded into an [`Engine`].
-
All `pub` functions become registered functions, all `pub` constants become [module] constant variables,
and all sub-modules become Rhai sub-modules.
```rust
-use rhai::plugins::*; // a "prelude" import for macros
+use rhai::plugin::*; // a "prelude" import for macros
#[export_module]
mod my_module {
@@ -117,7 +124,7 @@ Operators (which require function names that are not valid for Rust) can also be
Registering the same function name with the same parameter types will cause a parsing error.
```rust
-use rhai::plugins::*; // a "prelude" import for macros
+use rhai::plugin::*; // a "prelude" import for macros
#[export_module]
mod my_module {
@@ -147,7 +154,7 @@ Functions can be marked as [getters/setters] and [indexers] for [custom types] v
attribute, which is applied on a function level.
```rust
-use rhai::plugins::*; // a "prelude" import for macros
+use rhai::plugin::*; // a "prelude" import for macros
#[export_module]
mod my_module {
@@ -188,7 +195,7 @@ This is especially useful for the `name = "..."`, `get = "..."` and `set = "..."
to give multiple alternative names to the same function.
```rust
-use rhai::plugins::*; // a "prelude" import for macros
+use rhai::plugin::*; // a "prelude" import for macros
#[export_module]
mod my_module {
@@ -221,7 +228,7 @@ A syntax error is generated if the function with `#[rhai_fn(return_raw)]` does n
have the appropriate return type.
```rust
-use rhai::plugins::*; // a "prelude" import for macros
+use rhai::plugin::*; // a "prelude" import for macros
#[export_module]
mod my_module {
diff --git a/doc/src/rust/disable-custom.md b/doc/src/rust/disable-custom.md
index e5ad8a82..912482e5 100644
--- a/doc/src/rust/disable-custom.md
+++ b/doc/src/rust/disable-custom.md
@@ -3,8 +3,16 @@ Disable Custom Types
{{#include ../links.md}}
+
+`no_object` Feature
+-------------------
+
The custom types API `register_type`, `register_type_with_name`, `register_get`, `register_get_result`,
`register_set`, `register_set_result` and `register_get_set` are not available under [`no_object`].
+
+`no_index` Feature
+------------------
+
The indexers API `register_indexer_get`, `register_indexer_get_result`, `register_indexer_set`,
`register_indexer_set_result`, and `register_indexer_get_set` are also not available under [`no_index`].
diff --git a/doc/src/rust/getters-setters.md b/doc/src/rust/getters-setters.md
index bb07989d..586070af 100644
--- a/doc/src/rust/getters-setters.md
+++ b/doc/src/rust/getters-setters.md
@@ -11,7 +11,7 @@ Getters and setters are disabled when the [`no_object`] feature is used.
| `Engine` API | Description | Return Value of Function |
| --------------------- | ------------------------------------------------- | :-----------------------------------: |
-| `register_get` | register a getter | _any_ |
+| `register_get` | register a getter | _any_ `T: Clone` |
| `register_set` | register a setter | _none_ |
| `register_get_set` | short-hand to register both a getter and a setter | _none_ |
| `register_get_result` | register a getter | `Result>` |
diff --git a/doc/src/rust/indexers.md b/doc/src/rust/indexers.md
index ca880cff..2f76277f 100644
--- a/doc/src/rust/indexers.md
+++ b/doc/src/rust/indexers.md
@@ -15,7 +15,7 @@ Indexers are disabled when the [`no_index`] feature is used.
| `Engine` API | Description | Return Value of Function |
| ----------------------------- | -------------------------------------------------------- | :-----------------------------------: |
-| `register_indexer_get` | register an index getter | _any_ |
+| `register_indexer_get` | register an index getter | _any_ `T: Clone` |
| `register_indexer_set` | register an index setter | _none_ |
| `register_indexer_get_set` | short-hand to register both an index getter and a setter | _none_ |
| `register_indexer_get_result` | register an index getter | `Result>` |
diff --git a/doc/src/rust/operators.md b/doc/src/rust/operators.md
index e4ce9b65..83175bf8 100644
--- a/doc/src/rust/operators.md
+++ b/doc/src/rust/operators.md
@@ -6,16 +6,23 @@ Operator Overloading
In Rhai, a lot of functionalities are actually implemented as functions, including basic operations
such as arithmetic calculations.
-For example, in the expression "`a + b`", the `+` operator is _not_ built in, but calls a function named "`+`" instead!
+For example, in the expression "`a + b`", the `+` operator calls a function named "`+`"!
```rust
let x = a + b;
+
let x = +(a, b); // <- the above is equivalent to this function call
```
Similarly, comparison operators including `==`, `!=` etc. are all implemented as functions,
-with the stark exception of `&&` and `||`. Because they [_short-circuit_]({{rootUrl}}/language/logic.md#boolean-operators),
-`&&` and `||` are handled specially and _not_ via a function; as a result, overriding them has no effect at all.
+with the stark exception of `&&` and `||`.
+
+
+`&&` and `||` Cannot Be Overloaded
+---------------------------------
+
+Because they [_short-circuit_]({{rootUrl}}/language/logic.md#boolean-operators), `&&` and `||` are
+handled specially and _not_ via a function; as a result, overriding them has no effect at all.
Overload Operator via Rust Function
diff --git a/doc/src/rust/packages/create.md b/doc/src/rust/packages/create.md
index 698be745..04911dd4 100644
--- a/doc/src/rust/packages/create.md
+++ b/doc/src/rust/packages/create.md
@@ -60,7 +60,7 @@ 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 `rhai::plugins::combine_with_exported_module!`
+By far the easiest way to create a custom module is to call `rhai::plugin::combine_with_exported_module!`
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.
@@ -113,8 +113,8 @@ def_package!(rhai:MyPackage:"My own personal super package", module, {
//
// The sub-module 'my_sub_module' is flattened and its functions registered at the top level.
//
- // The text string name in the middle parameter can be anything and is reserved for future use;
- // it is recommended to be an ID string that uniquely identifies the module.
+ // The text string name in the second parameter can be anything and is reserved for future use;
+ // it is recommended to be an ID string that uniquely identifies the plugin module.
//
// The constant variable, 'MY_NUMBER', is ignored.
//
diff --git a/doc/src/rust/packages/plugin.md b/doc/src/rust/packages/plugin.md
index 42bc9519..509aff32 100644
--- a/doc/src/rust/packages/plugin.md
+++ b/doc/src/rust/packages/plugin.md
@@ -3,7 +3,8 @@ Load a Plugin Module as a Package
{{#include ../../links.md}}
-[Plugin modules] can be loaded as a package just like a normal [module].
+[Plugin modules] can be loaded as a package just like a normal [module]
+via the `exported_module!` macro.
```rust
use rhai::Engine;
diff --git a/doc/src/rust/register-raw.md b/doc/src/rust/register-raw.md
index b77ebab5..2897138f 100644
--- a/doc/src/rust/register-raw.md
+++ b/doc/src/rust/register-raw.md
@@ -35,13 +35,12 @@ engine.register_raw_fn(
// Therefore, get a '&mut' reference to the first argument _last_.
// Alternatively, use `args.split_first_mut()` etc. to split the slice first.
- let y: i64 = *args[1].read_lock::() // get a reference to the second argument
- .unwrap(); // then copying it because it is a primary type
+ let y = *args[1].read_lock::().unwrap(); // get a reference to the second argument
+ // then copy it because it is a primary type
- let y: i64 = std::mem::take(args[1]).cast::(); // alternatively, directly 'consume' it
+ let y = std::mem::take(args[1]).cast::(); // alternatively, directly 'consume' it
- let x: &mut i64 = args[0].write_lock::() // get a '&mut' reference to the
- .unwrap(); // first argument
+ let x = args[0].write_lock::().unwrap(); // get a '&mut' reference to the first argument
*x += y; // perform the action
@@ -51,7 +50,7 @@ engine.register_raw_fn(
// The above is the same as (in fact, internally they are equivalent):
-engine.register_fn("increment_by", |x: &mut i64, y: i64| x += y);
+engine.register_fn("increment_by", |x: &mut i64, y: i64| *x += y);
```
@@ -153,7 +152,8 @@ is a _shared value_ created by [capturing][automatic currying] variables from [c
Shared values are implemented as `Rc>` (`Arc>` under [`sync`]).
If the value is _not_ a shared value, or if running under [`no_closure`] where there is
-no [capturing][automatic currying], this API de-sugars to a simple `downcast_ref` and `downcast_mut`.
+no [capturing][automatic currying], this API de-sugars to a simple `Dynamic::downcast_ref` and
+`Dynamic::downcast_mut`.
If the value is a shared value, then it is first locked and the returned lock guard
then allows access to the underlying value in the specified type.
@@ -171,9 +171,9 @@ to partition the slice:
let (first, rest) = args.split_first_mut().unwrap();
// Mutable reference to the first parameter
-let this_ptr: &mut A = &mut *first.write_lock::().unwrap();
+let this_ptr = &mut *first.write_lock::().unwrap();
// Immutable reference to the second value parameter
// This can be mutable but there is no point because the parameter is passed by value
-let value_ref: &B = &*rest[0].read_lock::().unwrap();
+let value_ref = &*rest[0].read_lock::().unwrap();
```
diff --git a/doc/src/rust/traits.md b/doc/src/rust/traits.md
index 4d0d8391..a9b1a297 100644
--- a/doc/src/rust/traits.md
+++ b/doc/src/rust/traits.md
@@ -5,9 +5,10 @@ Traits
A number of traits, under the `rhai::` module namespace, provide additional functionalities.
-| Trait | Description | Methods |
-| ------------------ | ---------------------------------------------------------------------------------------- | --------------------------------------- |
-| `RegisterFn` | trait for registering functions | `register_fn` |
-| `RegisterResultFn` | trait for registering fallible functions returning `Result>` | `register_result_fn` |
-| `Func` | trait for creating Rust closures from script | `create_from_ast`, `create_from_script` |
-| `ModuleResolver` | trait implemented by module resolution services | `resolve` |
+| Trait | Description | Methods |
+| ------------------------ | ------------------------------------------------------------------ | --------------------------------------------------------------------- |
+| `RegisterFn` | trait for registering functions | `register_fn` |
+| `RegisterResultFn` | trait for registering [fallible functions] | `register_result_fn` |
+| `Func` | trait for creating Rust closures from script | `create_from_ast`, `create_from_script` |
+| `ModuleResolver` | trait implemented by [module resolution][module resolver] services | `resolve` |
+| `plugin::PluginFunction` | trait implemented by [plugin] functions | `call`, `is_method_call`, `is_variadic`, `clone_boxed`, `input_types` |