Refine docs.
This commit is contained in:
parent
0b21d80641
commit
c86a979601
@ -41,7 +41,7 @@ Standard features
|
|||||||
Protection against attacks
|
Protection against attacks
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
* Sand-boxed - the scripting engine, if declared immutable, cannot mutate the containing environment unless explicitly permitted (e.g. via a `RefCell`).
|
* Sand-boxed - the scripting engine, if declared immutable, cannot mutate the containing environment unless [explicitly permitted](https://schungx.github.io/rhai/patterns/control.html).
|
||||||
* Rugged - protected against malicious attacks (such as [stack-overflow](https://schungx.github.io/rhai/safety/max-call-stack.html), [over-sized data](https://schungx.github.io/rhai/safety/max-string-size.html), and [runaway scripts](https://schungx.github.io/rhai/safety/max-operations.html) etc.) that may come from untrusted third-party user-land scripts.
|
* Rugged - protected against malicious attacks (such as [stack-overflow](https://schungx.github.io/rhai/safety/max-call-stack.html), [over-sized data](https://schungx.github.io/rhai/safety/max-string-size.html), and [runaway scripts](https://schungx.github.io/rhai/safety/max-operations.html) etc.) that may come from untrusted third-party user-land scripts.
|
||||||
* Track script evaluation [progress](https://schungx.github.io/rhai/safety/progress.html) and manually terminate a script run.
|
* Track script evaluation [progress](https://schungx.github.io/rhai/safety/progress.html) and manually terminate a script run.
|
||||||
|
|
||||||
|
@ -101,10 +101,10 @@ The Rhai Scripting Language
|
|||||||
9. [Maximum Statement Depth](safety/max-stmt-depth.md)
|
9. [Maximum Statement Depth](safety/max-stmt-depth.md)
|
||||||
7. [Advanced Topics](advanced.md)
|
7. [Advanced Topics](advanced.md)
|
||||||
1. [Advanced Patterns](patterns/index.md)
|
1. [Advanced Patterns](patterns/index.md)
|
||||||
1. [Loadable Configuration](patterns/config.md)
|
1. [Object-Oriented Programming (OOP)](patterns/oop.md)
|
||||||
2. [Control Layer](patterns/control.md)
|
2. [Loadable Configuration](patterns/config.md)
|
||||||
3. [Singleton Command](patterns/singleton.md)
|
3. [Control Layer](patterns/control.md)
|
||||||
4. [Object-Oriented Programming (OOP)](patterns/oop.md)
|
4. [Singleton Command](patterns/singleton.md)
|
||||||
2. [Capture Scope for Function Call](language/fn-capture.md)
|
2. [Capture Scope for Function Call](language/fn-capture.md)
|
||||||
3. [Serialization/Deserialization of `Dynamic` with `serde`](rust/serde.md)
|
3. [Serialization/Deserialization of `Dynamic` with `serde`](rust/serde.md)
|
||||||
4. [Script Optimization](engine/optimize/index.md)
|
4. [Script Optimization](engine/optimize/index.md)
|
||||||
|
@ -46,7 +46,7 @@ Safe
|
|||||||
|
|
||||||
* Relatively little `unsafe` code (yes there are some for performance reasons).
|
* 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`).
|
* Sand-boxed - the scripting [`Engine`], if declared immutable, cannot mutate the containing environment unless [explicitly permitted]({{rootUrl}}/patterns/control.md).
|
||||||
|
|
||||||
Rugged
|
Rugged
|
||||||
------
|
------
|
||||||
|
@ -3,9 +3,15 @@ Arrays
|
|||||||
|
|
||||||
{{#include ../links.md}}
|
{{#include ../links.md}}
|
||||||
|
|
||||||
Arrays are first-class citizens in Rhai. Like C, arrays are accessed with zero-based, non-negative integer indices.
|
Arrays are first-class citizens in Rhai. Like C, arrays are accessed with zero-based, non-negative integer indices:
|
||||||
|
|
||||||
Array literals are built within square brackets '`[`' ... '`]`' and separated by commas '`,`'.
|
> _array_ `[` _index_ `]`
|
||||||
|
|
||||||
|
Array literals are built within square brackets '`[`' ... '`]`' and separated by commas '`,`':
|
||||||
|
|
||||||
|
> `[` _value_ `,` _value_ `,` `...` `,` _value_ `]`
|
||||||
|
>
|
||||||
|
> `[` _value_ `,` _value_ `,` `...` `,` _value_ `,` `]` `// trailing comma is OK`
|
||||||
|
|
||||||
All elements stored in an array are [`Dynamic`], and the array can freely grow or shrink with elements added or removed.
|
All elements stored in an array are [`Dynamic`], and the array can freely grow or shrink with elements added or removed.
|
||||||
|
|
||||||
|
@ -19,21 +19,36 @@ Object Map Literals
|
|||||||
------------------
|
------------------
|
||||||
|
|
||||||
Object map literals are built within braces '`#{`' ... '`}`' (_name_ `:` _value_ syntax similar to Rust)
|
Object map literals are built within braces '`#{`' ... '`}`' (_name_ `:` _value_ syntax similar to Rust)
|
||||||
and separated by commas '`,`'. The property _name_ can be a simple variable name following the same
|
and separated by commas '`,`':
|
||||||
|
|
||||||
|
> `#{` _property_ `:` _value_ `,` `...` `,` _property_ `:` _value_ `}`
|
||||||
|
>
|
||||||
|
> `#{` _property_ `:` _value_ `,` `...` `,` _property_ `:` _value_ `,` `}` `// trailing comma is OK`
|
||||||
|
|
||||||
|
The property _name_ can be a simple variable name following the same
|
||||||
naming rules as [variables], or an arbitrary [string] literal.
|
naming rules as [variables], or an arbitrary [string] literal.
|
||||||
|
|
||||||
|
|
||||||
Access Properties
|
Access Properties
|
||||||
----------------
|
-----------------
|
||||||
|
|
||||||
Property values can be accessed via the _dot_ notation (_object_ `.` _property_)
|
### Dot Notation
|
||||||
or _index_ notation (_object_ `[` _property_ `]`).
|
|
||||||
|
|
||||||
The dot notation allows only property names that follow the same naming rules as [variables].
|
The _dot notation_ allows only property names that follow the same naming rules as [variables].
|
||||||
|
|
||||||
The index notation allows setting/getting properties of arbitrary names (even the empty [string]).
|
> _object_ `.` _property_
|
||||||
|
|
||||||
**Important:** Trying to read a non-existent property returns [`()`] instead of causing an error.
|
### Index Notation
|
||||||
|
|
||||||
|
The _index notation_ allows setting/getting properties of arbitrary names (even the empty [string]).
|
||||||
|
|
||||||
|
> _object_ `[` _property_ `]`
|
||||||
|
|
||||||
|
### Non-Existence
|
||||||
|
|
||||||
|
Trying to read a non-existing property returns [`()`] instead of causing an error.
|
||||||
|
|
||||||
|
This is similar to JavaScript where accessing a non-existing property returns `undefined`.
|
||||||
|
|
||||||
|
|
||||||
Built-in Functions
|
Built-in Functions
|
||||||
@ -89,7 +104,7 @@ let foo = #{ a:1, b:2, c:3 }["a"];
|
|||||||
foo == 1;
|
foo == 1;
|
||||||
|
|
||||||
fn abc() {
|
fn abc() {
|
||||||
#{ a:1, b:2, c:3 } // a function returning an object map
|
##{ a:1, b:2, c:3 } // a function returning an object map
|
||||||
}
|
}
|
||||||
|
|
||||||
let foo = abc().b;
|
let foo = abc().b;
|
||||||
|
@ -76,6 +76,8 @@
|
|||||||
|
|
||||||
[function]: {{rootUrl}}/language/functions.md
|
[function]: {{rootUrl}}/language/functions.md
|
||||||
[functions]: {{rootUrl}}/language/functions.md
|
[functions]: {{rootUrl}}/language/functions.md
|
||||||
|
[function overloading]: {{rootUrl}}/rust/functions.md#function-overloading
|
||||||
|
[fallible functions]: {{rootUrl}}/rust/fallible.md
|
||||||
[function pointer]: {{rootUrl}}/language/fn-ptr.md
|
[function pointer]: {{rootUrl}}/language/fn-ptr.md
|
||||||
[function pointers]: {{rootUrl}}/language/fn-ptr.md
|
[function pointers]: {{rootUrl}}/language/fn-ptr.md
|
||||||
[currying]: {{rootUrl}}/language/fn-curry.md
|
[currying]: {{rootUrl}}/language/fn-curry.md
|
||||||
@ -100,6 +102,7 @@
|
|||||||
[OOP]: {{rootUrl}}/patterns/oop.md
|
[OOP]: {{rootUrl}}/patterns/oop.md
|
||||||
[DSL]: {{rootUrl}}/engine/dsl.md
|
[DSL]: {{rootUrl}}/engine/dsl.md
|
||||||
|
|
||||||
|
[sand-boxed]: {{rootUrl}}/safety/sandbox.md
|
||||||
[maximum statement depth]: {{rootUrl}}/safety/max-stmt-depth.md
|
[maximum statement depth]: {{rootUrl}}/safety/max-stmt-depth.md
|
||||||
[maximum call stack depth]: {{rootUrl}}/safety/max-call-stack.md
|
[maximum call stack depth]: {{rootUrl}}/safety/max-call-stack.md
|
||||||
[maximum number of operations]: {{rootUrl}}/safety/max-operations.md
|
[maximum number of operations]: {{rootUrl}}/safety/max-operations.md
|
||||||
|
@ -9,11 +9,11 @@ Usage Scenario
|
|||||||
|
|
||||||
* A system where settings and configurations are complex and logic-driven.
|
* A system where settings and configurations are complex and logic-driven.
|
||||||
|
|
||||||
* Where it is not possible to configure said system via standard configuration file formats such as `TOML` or `YAML`.
|
* Where said system is too complex to configure via standard configuration file formats such as `JSON`, `TOML` or `YAML`.
|
||||||
|
|
||||||
* The system configuration is complex enough that it requires a full programming language. Essentially _configuration by code_.
|
* The system is complex enough to require a full programming language to configure. Essentially _configuration by code_.
|
||||||
|
|
||||||
* Yet the configurations must be flexible, late-bound and dynamically loadable, just like a configuration file.
|
* Yet the configuration must be flexible, late-bound and dynamically loadable, just like a configuration file.
|
||||||
|
|
||||||
|
|
||||||
Key Concepts
|
Key Concepts
|
||||||
@ -23,6 +23,8 @@ Key Concepts
|
|||||||
|
|
||||||
* Expose the configuration API. Use separate scripts to configure that API. Dynamically load scripts via the `import` statement.
|
* Expose the configuration API. Use separate scripts to configure that API. Dynamically load scripts via the `import` statement.
|
||||||
|
|
||||||
|
* Leverage [function overloading] to simplify the API design.
|
||||||
|
|
||||||
* Since Rhai is _sand-boxed_, it cannot mutate the environment. To modify the external configuration object via an API, it must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
* Since Rhai is _sand-boxed_, it cannot mutate the environment. To modify the external configuration object via an API, it must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,12 +19,26 @@ Key Concepts
|
|||||||
|
|
||||||
* Expose a Control API.
|
* Expose a Control API.
|
||||||
|
|
||||||
* Since Rhai is _sand-boxed_, it cannot mutate the environment. To perform external actions via an API, the actual system must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
* Leverage [function overloading] to simplify the API design.
|
||||||
|
|
||||||
|
* Since Rhai is _[sand-boxed]_, it cannot mutate the environment. To perform external actions via an API, the actual system must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
There are two broad ways for Rhai to control an external system, both of which involve
|
||||||
|
wrapping the system in a shared, interior-mutated object.
|
||||||
|
|
||||||
|
This is one way which does not involve exposing the data structures of the external system,
|
||||||
|
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,
|
||||||
|
use the [Singleton Command Object]({{rootUrl}}/patterns/singleton.md) pattern instead.
|
||||||
|
|
||||||
|
|
||||||
### Functional API
|
### Functional API
|
||||||
|
|
||||||
Assume that a system provides the following functional API:
|
Assume that a system provides the following functional API:
|
||||||
|
@ -4,6 +4,4 @@ Advanced Patterns
|
|||||||
{{#include ../links.md}}
|
{{#include ../links.md}}
|
||||||
|
|
||||||
|
|
||||||
Use Rhai in different scenarios other than simply evaluating a user script.
|
Leverage the full power and flexibility of Rhai in advanced scenarios.
|
||||||
|
|
||||||
These patterns are useful when Rhai needs to affect/control the external environment.
|
|
||||||
|
@ -18,17 +18,17 @@ Rhai's [object maps] has [special support for OOP]({{rootUrl}}/language/object-m
|
|||||||
| [Object map] properties that hold [function pointers] | methods |
|
| [Object map] properties that hold [function pointers] | methods |
|
||||||
|
|
||||||
When a property of an [object map] is called like a method function, and if it happens to hold
|
When a property of an [object map] is called like a method function, and if it happens to hold
|
||||||
a valid [function pointer] (perhaps defined via an [anonymous function]), then the call will be
|
a valid [function pointer] (perhaps defined via an [anonymous function] or more commonly as a [closure]),
|
||||||
dispatched to the actual function with `this` binding to the [object map] itself.
|
then the call will be dispatched to the actual function with `this` binding to the [object map] itself.
|
||||||
|
|
||||||
|
|
||||||
Use Anonymous Functions to Define Methods
|
Use Anonymous Functions to Define Methods
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
[Anonymous functions] defined as values for [object map] properties take on a syntactic shape
|
[Anonymous functions] or [closures] defined as values for [object map] properties take on
|
||||||
that resembles very closely that of class methods in an OOP language.
|
a syntactic shape that resembles very closely that of class methods in an OOP language.
|
||||||
|
|
||||||
Anonymous functions can also _capture_ variables from the defining environment, which is a very
|
Closures also _[capture][automatic currying]_ variables from the defining environment, which is a very
|
||||||
common OOP pattern. Capturing is accomplished via a feature called _[automatic currying]_ and
|
common OOP pattern. Capturing is accomplished via a feature called _[automatic currying]_ and
|
||||||
can be turned off via the [`no_closure`] feature.
|
can be turned off via the [`no_closure`] feature.
|
||||||
|
|
||||||
@ -40,9 +40,8 @@ Examples
|
|||||||
let factor = 1;
|
let factor = 1;
|
||||||
|
|
||||||
// Define the object
|
// Define the object
|
||||||
let obj =
|
let obj = #{
|
||||||
#{
|
data: 0, // object field
|
||||||
data: 0,
|
|
||||||
increment: |x| this.data += x, // 'this' binds to 'obj'
|
increment: |x| this.data += x, // 'this' binds to 'obj'
|
||||||
update: |x| this.data = x * factor, // 'this' binds to 'obj', 'factor' is captured
|
update: |x| this.data = x * factor, // 'this' binds to 'obj', 'factor' is captured
|
||||||
action: || print(this.data) // 'this' binds to 'obj'
|
action: || print(this.data) // 'this' binds to 'obj'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Singleton Command Objects
|
Singleton Command Object
|
||||||
========================
|
=======================
|
||||||
|
|
||||||
{{#include ../links.md}}
|
{{#include ../links.md}}
|
||||||
|
|
||||||
@ -21,9 +21,11 @@ Usage Scenario
|
|||||||
Key Concepts
|
Key Concepts
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* Expose a Command type with an API.
|
* Expose a Command type with an API. The [`no_object`] feature must not be on.
|
||||||
|
|
||||||
* Since Rhai is _sand-boxed_, it cannot mutate the environment. To perform external actions via an API, the command object type must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
* Leverage [function overloading] to simplify the API design.
|
||||||
|
|
||||||
|
* Since Rhai is _[sand-boxed]_, it cannot mutate the environment. To perform external actions via an API, the command object type must be wrapped in a `RefCell` (or `RwLock`/`Mutex` for [`sync`]) and shared to the [`Engine`].
|
||||||
|
|
||||||
* Load each command object into a custom [`Scope`] as constant variables.
|
* Load each command object into a custom [`Scope`] as constant variables.
|
||||||
|
|
||||||
@ -33,6 +35,18 @@ Key Concepts
|
|||||||
Implementation
|
Implementation
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
There are two broad ways for Rhai to control an external system, both of which involve
|
||||||
|
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.
|
||||||
|
|
||||||
|
For a relatively simple API that is action-based and not object-based,
|
||||||
|
use the [Control Layer]({{rootUrl}}/patterns/control.md) pattern instead.
|
||||||
|
|
||||||
|
|
||||||
### Functional API
|
### Functional API
|
||||||
|
|
||||||
Assume the following command object type:
|
Assume the following command object type:
|
||||||
|
@ -7,7 +7,7 @@ Rhai's scripting engine is very lightweight. It gets most of its abilities from
|
|||||||
|
|
||||||
To call these functions, they need to be _registered_ with the [`Engine`] using `Engine::register_fn`
|
To call these functions, they need to be _registered_ with the [`Engine`] using `Engine::register_fn`
|
||||||
(in the `RegisterFn` trait) and `Engine::register_result_fn` (in the `RegisterResultFn` trait,
|
(in the `RegisterFn` trait) and `Engine::register_result_fn` (in the `RegisterResultFn` trait,
|
||||||
see [fallible functions]({{rootUrl}}/rust/fallible.md)).
|
see [fallible functions]).
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString};
|
use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString};
|
||||||
@ -62,8 +62,12 @@ let x = (42_i64).into(); // 'into()' works for standard t
|
|||||||
let y = Dynamic::from("hello!".to_string()); // remember &str is not supported by Rhai
|
let y = Dynamic::from("hello!".to_string()); // remember &str is not supported by Rhai
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Function Overloading
|
||||||
|
--------------------
|
||||||
|
|
||||||
Functions registered with the [`Engine`] can be _overloaded_ as long as the _signature_ is unique,
|
Functions registered with the [`Engine`] can be _overloaded_ as long as the _signature_ is unique,
|
||||||
i.e. different functions can have the same name as long as their parameters are of different types
|
i.e. different functions can have the same name as long as their parameters are of different types
|
||||||
and/or different number.
|
or different number.
|
||||||
|
|
||||||
New definitions _overwrite_ previous definitions of the same name and same number/types of parameters.
|
New definitions _overwrite_ previous definitions of the same name and same number/types of parameters.
|
||||||
|
@ -5,7 +5,9 @@ Custom Type Indexers
|
|||||||
|
|
||||||
A custom type can also expose an _indexer_ by registering an indexer function.
|
A custom type can also expose an _indexer_ by registering an indexer function.
|
||||||
|
|
||||||
A custom type with an indexer function defined can use the bracket '`[]`' notation to get a property value.
|
A custom type with an indexer function defined can use the bracket notation to get a property value:
|
||||||
|
|
||||||
|
> _object_ `[` _index_ `]`
|
||||||
|
|
||||||
Like getters and setters, indexers take a `&mut` reference to the first parameter.
|
Like getters and setters, indexers take a `&mut` reference to the first parameter.
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ struct MyStruct {
|
|||||||
let engine = Engine::new();
|
let engine = Engine::new();
|
||||||
|
|
||||||
let result: Dynamic = engine.eval(r#"
|
let result: Dynamic = engine.eval(r#"
|
||||||
#{
|
##{
|
||||||
a: 42,
|
a: 42,
|
||||||
b: [ "hello", "world" ],
|
b: [ "hello", "world" ],
|
||||||
c: true,
|
c: true,
|
||||||
|
@ -5,13 +5,31 @@ Sand-Boxing - Block Access to External Data
|
|||||||
|
|
||||||
Rhai is _sand-boxed_ so a script can never read from outside its own environment.
|
Rhai is _sand-boxed_ so a script can never read from outside its own environment.
|
||||||
|
|
||||||
Furthermore, an [`Engine`] created non-`mut` cannot mutate any state outside of itself;
|
Furthermore, an [`Engine`] created non-`mut` cannot mutate any state, including itself
|
||||||
so it is highly recommended that [`Engine`]'s are created immutable as much as possible.
|
(and therefore it is also _re-entrant_).
|
||||||
|
|
||||||
|
It is highly recommended that [`Engine`]'s be created immutable as much as possible.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let mut engine = Engine::new(); // create mutable 'Engine'
|
// Use the fluent API to configure an 'Engine' and then keep an immutable instance.
|
||||||
|
let engine = Engine::new()
|
||||||
|
.register_get("field", get_field)
|
||||||
|
.register_set("field", set_field)
|
||||||
|
.register_fn("do_work", action);
|
||||||
|
|
||||||
engine.register_get("add", add); // configure 'engine'
|
// 'engine' is immutable...
|
||||||
|
|
||||||
let engine = engine; // shadow the variable so that 'engine' is now immutable
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Using Rhai to Control External Environment
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
How does a _sand-boxed_, immutable [`Engine`] control the external environment?
|
||||||
|
This is necessary in order to use Rhai as a _dynamic control layer_ over a Rust core system.
|
||||||
|
|
||||||
|
There are two general patterns, both involving wrapping the external system
|
||||||
|
in a shared, interior-mutated object (e.g. `Rc<RefCell<T>>`):
|
||||||
|
|
||||||
|
* [Control Layer]({{rootUrl}}/patterns/control.md) pattern.
|
||||||
|
|
||||||
|
* [Singleton Command Object]({{rootUrl}}/patterns/singleton.md) pattern.
|
||||||
|
@ -56,7 +56,7 @@ mod example {
|
|||||||
let result: Dynamic = engine
|
let result: Dynamic = engine
|
||||||
.eval(
|
.eval(
|
||||||
r#"
|
r#"
|
||||||
#{
|
##{
|
||||||
a: 42,
|
a: 42,
|
||||||
b: [ "hello", "world" ],
|
b: [ "hello", "world" ],
|
||||||
c: true,
|
c: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user