Revise docs.
This commit is contained in:
parent
f05cd1fdf3
commit
b70fd35f4a
@ -27,12 +27,11 @@ Standard features
|
||||
* Easily [call a script-defined function](https://schungx.github.io/rhai/engine/call-fn.html) from Rust.
|
||||
* Fairly low compile-time overhead.
|
||||
* Fairly efficient evaluation (1 million iterations in 0.3 sec on a single core, 2.3 GHz Linux VM).
|
||||
* Relatively little `unsafe` code (yes there are some for performance reasons, and most `unsafe` code is limited to
|
||||
one single source file, all with names starting with `"unsafe_"`).
|
||||
* Relatively little `unsafe` code (yes there are some for performance reasons).
|
||||
* Re-entrant scripting engine can be made `Send + Sync` (via the `sync` feature).
|
||||
* [Function overloading](https://schungx.github.io/rhai/language/overload.html).
|
||||
* [Operator overloading](https://schungx.github.io/rhai/rust/operators.html).
|
||||
* Dynamic dispatch via [function pointers](https://schungx.github.io/rhai/language/fn-ptr.html).
|
||||
* Dynamic dispatch via [function pointers](https://schungx.github.io/rhai/language/fn-ptr.html) with additional support for [currying](https://schungx.github.io/rhai/language/fn-curry.html).
|
||||
* Some support for [object-oriented programming (OOP)](https://schungx.github.io/rhai/language/oop.html).
|
||||
* Organize code base with dynamically-loadable [modules](https://schungx.github.io/rhai/language/modules.html).
|
||||
* Serialization/deserialization support via [serde](https://crates.io/crates/serde) (requires the `serde` feature).
|
||||
|
@ -35,23 +35,20 @@ Dynamic
|
||||
|
||||
* Organize code base with dynamically-loadable [modules].
|
||||
|
||||
* Dynamic dispatch via [function pointers].
|
||||
* Dynamic dispatch via [function pointers] with additional support for [currying].
|
||||
|
||||
* Some support for [object-oriented programming (OOP)][OOP].
|
||||
|
||||
* Serialization/deserialization support via [`serde`].
|
||||
|
||||
Safe
|
||||
----
|
||||
|
||||
* Relatively little `unsafe` code (yes there are some for performance reasons, and most `unsafe` code is limited to
|
||||
one single source file, all with names starting with `"unsafe_"`).
|
||||
* Relatively little `unsafe` code (yes there are some for performance reasons).
|
||||
|
||||
* Sand-boxed - the scripting [`Engine`], if declared immutable, cannot mutate the containing environment unless explicitly permitted (e.g. via a `RefCell`).
|
||||
|
||||
Rugged
|
||||
------
|
||||
|
||||
* Sand-boxed - the scripting [`Engine`], if declared immutable, cannot mutate the containing environment unless explicitly permitted (e.g. via a `RefCell`).
|
||||
|
||||
* Protected against malicious attacks (such as [stack-overflow][maximum call stack depth], [over-sized data][maximum length of strings], and [runaway scripts][maximum number of operations] etc.) that may come from untrusted third-party user-land scripts.
|
||||
|
||||
* Track script evaluation [progress] and manually terminate a script run.
|
||||
@ -61,6 +58,8 @@ Flexible
|
||||
|
||||
* Re-entrant scripting [`Engine`] can be made `Send + Sync` (via the [`sync`] feature).
|
||||
|
||||
* Serialization/deserialization support via [`serde`](https://crates.io/crates/serde).
|
||||
|
||||
* Support for [minimal builds] by excluding unneeded language [features].
|
||||
|
||||
* Supports [most build targets](targets.md) including `no-std` and [WASM].
|
||||
|
@ -69,17 +69,22 @@ The only practical way to ensure that a function is a correct one is to use [mod
|
||||
i.e. define the function in a separate module and then [`import`] it:
|
||||
|
||||
```rust
|
||||
message.rhai:
|
||||
----------------
|
||||
| message.rhai |
|
||||
----------------
|
||||
|
||||
fn message() { "Hello!" }
|
||||
fn message() { "Hello!" }
|
||||
|
||||
script.rhai:
|
||||
|
||||
fn say_hello() {
|
||||
---------------
|
||||
| script.rhai |
|
||||
---------------
|
||||
|
||||
fn say_hello() {
|
||||
import "message" as msg;
|
||||
print(msg::message());
|
||||
}
|
||||
say_hello();
|
||||
}
|
||||
say_hello();
|
||||
```
|
||||
|
||||
|
||||
@ -94,18 +99,23 @@ defined _within the script_. When called later, those functions will be searche
|
||||
current global namespace and may not be found.
|
||||
|
||||
```rust
|
||||
greeting.rhai:
|
||||
-----------------
|
||||
| greeting.rhai |
|
||||
-----------------
|
||||
|
||||
fn message() { "Hello!" };
|
||||
fn message() { "Hello!" };
|
||||
|
||||
fn say_hello() { print(message()); }
|
||||
fn say_hello() { print(message()); }
|
||||
|
||||
say_hello(); // 'message' is looked up in the global namespace
|
||||
say_hello(); // 'message' is looked up in the global namespace
|
||||
|
||||
script.rhai:
|
||||
|
||||
import "greeting" as g;
|
||||
g::say_hello(); // <- error: function not found - 'message'
|
||||
---------------
|
||||
| script.rhai |
|
||||
---------------
|
||||
|
||||
import "greeting" as g;
|
||||
g::say_hello(); // <- error: function not found - 'message'
|
||||
```
|
||||
|
||||
In the example above, although the module `greeting.rhai` loads fine (`"Hello!"` is printed),
|
||||
@ -118,24 +128,29 @@ as possible and avoid cross-calling them from each other. A [function pointer]
|
||||
to call another function within a module-defined function:
|
||||
|
||||
```rust
|
||||
greeting.rhai:
|
||||
-----------------
|
||||
| greeting.rhai |
|
||||
-----------------
|
||||
|
||||
fn message() { "Hello!" };
|
||||
fn message() { "Hello!" };
|
||||
|
||||
fn say_hello(msg_func) { // 'msg_func' is a function pointer
|
||||
fn say_hello(msg_func) { // 'msg_func' is a function pointer
|
||||
print(msg_func.call()); // call via the function pointer
|
||||
}
|
||||
}
|
||||
|
||||
say_hello(); // 'message' is looked up in the global namespace
|
||||
say_hello(); // 'message' is looked up in the global namespace
|
||||
|
||||
script.rhai:
|
||||
|
||||
import "greeting" as g;
|
||||
---------------
|
||||
| script.rhai |
|
||||
---------------
|
||||
|
||||
fn my_msg() {
|
||||
import "greeting" as g;
|
||||
|
||||
fn my_msg() {
|
||||
import "greeting" as g; // <- must import again here...
|
||||
g::message() // <- ... otherwise will not find module 'g'
|
||||
}
|
||||
}
|
||||
|
||||
g::say_hello(Fn("my_msg")); // prints 'Hello!'
|
||||
g::say_hello(Fn("my_msg")); // prints 'Hello!'
|
||||
```
|
||||
|
@ -37,12 +37,30 @@ array[0].update(); // <- call in method-call style will update 'a'
|
||||
```
|
||||
|
||||
|
||||
`&mut` is Efficient
|
||||
------------------
|
||||
Number of Parameters
|
||||
--------------------
|
||||
|
||||
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.
|
||||
|
||||
The following table illustrates the differences:
|
||||
|
||||
| Function type | Parameters | Object reference | Function signature |
|
||||
| :-----------: | :--------: | :--------------------: | :-----------------------------------------------------: |
|
||||
| Native Rust | _n_ + 1 | First `&mut` parameter | `fn method<T, U, V>`<br/>`(obj: &mut T, x: U, y: V) {}` |
|
||||
| Rhai script | _n_ | `this` | `fn method(x, y) {}` |
|
||||
|
||||
|
||||
`&mut` is Efficient (Except for `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`.
|
||||
|
||||
For primary types that are cheap to clone (e.g. those that implement `Copy`),
|
||||
including `ImmutableString`, this is not necessary.
|
||||
|
||||
|
@ -63,7 +63,9 @@ cause a stack overflow in the [`Engine`], unless stopped by setting a limit for
|
||||
For instance, importing itself always causes an infinite recursion:
|
||||
|
||||
```rust
|
||||
// This file is 'hello.rhai'
|
||||
--------------
|
||||
| hello.rhai |
|
||||
--------------
|
||||
|
||||
import "hello" as foo; // import itself - infinite recursion!
|
||||
|
||||
@ -73,11 +75,18 @@ foo::do_something();
|
||||
Modules cross-referencing also cause infinite recursion:
|
||||
|
||||
```rust
|
||||
// This file is 'hello.rhai' - references 'world.rhai'
|
||||
--------------
|
||||
| hello.rhai |
|
||||
--------------
|
||||
|
||||
import "world" as foo;
|
||||
foo::do_something();
|
||||
|
||||
// This file is 'world.rhai' - references 'hello.rhai'
|
||||
|
||||
--------------
|
||||
| world.rhai |
|
||||
--------------
|
||||
|
||||
import "hello" as bar;
|
||||
bar::do_something_else();
|
||||
```
|
||||
|
@ -9,15 +9,15 @@ and _number_ of parameters, but not parameter _types_ since all parameters are t
|
||||
New definitions _overwrite_ previous definitions of the same name and number of parameters.
|
||||
|
||||
```rust
|
||||
fn foo(x,y,z) { print("Three!!! " + x + "," + y + "," + z) }
|
||||
fn foo(x,y,z) { print("Three!!! " + x + "," + y + "," + z); }
|
||||
|
||||
fn foo(x) { print("One! " + x) }
|
||||
fn foo(x) { print("One! " + x); }
|
||||
|
||||
fn foo(x,y) { print("Two! " + x + "," + y) }
|
||||
fn foo(x,y) { print("Two! " + x + "," + y); }
|
||||
|
||||
fn foo() { print("None.") }
|
||||
fn foo() { print("None."); }
|
||||
|
||||
fn foo(x) { print("HA! NEW ONE! " + x) } // overwrites previous definition
|
||||
fn foo(x) { print("HA! NEW ONE! " + x); } // overwrites previous definition
|
||||
|
||||
foo(1,2,3); // prints "Three!!! 1,2,3"
|
||||
|
||||
|
@ -24,7 +24,7 @@ more control over what a script can (or cannot) do.
|
||||
| `no_function` | Disable script-defined [functions]. |
|
||||
| `no_module` | Disable loading external [modules]. |
|
||||
| `no_std` | Build for `no-std`. Notice that additional dependencies will be pulled in to replace `std` features. |
|
||||
| `serde` | Enable serialization/deserialization via [`serde`]. Notice that the [`serde`](https://crates.io/crates/serde) crate will be pulled in together with its dependencies. |
|
||||
| `serde` | Enable serialization/deserialization via `serde`. Notice that the [`serde`](https://crates.io/crates/serde) crate will be pulled in together with its dependencies. |
|
||||
| `internals` | Expose internal data structures (e.g. [`AST`] nodes). Beware that Rhai internals are volatile and may change from version to version. |
|
||||
|
||||
|
||||
|
@ -432,7 +432,7 @@ impl Module {
|
||||
/// let mut module = Module::new();
|
||||
/// let hash = module.set_raw_fn("double_or_not",
|
||||
/// // Pass parameter types via a slice with TypeId's
|
||||
/// &[std::any::TypeId::of::<i64>(), std::any::TypeId::of::<bool>() ],
|
||||
/// &[std::any::TypeId::of::<i64>(), std::any::TypeId::of::<bool>()],
|
||||
/// // Fixed closure signature
|
||||
/// |engine, lib, args| {
|
||||
/// // 'args' is guaranteed to be the right length and of the correct types
|
||||
|
Loading…
Reference in New Issue
Block a user