diff --git a/README.md b/README.md
index ac9a79a1..7d55bdbe 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Supported targets and builds
Features
--------
-* Easy-to-use language similar to JS+Rust with dynamic typing.
+* Easy-to-use language similar to JavaScript+Rust with dynamic typing.
* Tight integration with native Rust [functions](https://schungx.github.io/rhai/rust/functions.html) and [types]([#custom-types-and-methods](https://schungx.github.io/rhai/rust/custom.html)), including [getters/setters](https://schungx.github.io/rhai/rust/getters-setters.html), [methods](https://schungx.github.io/rhai/rust/custom.html) and [indexers](https://schungx.github.io/rhai/rust/indexers.html).
* Freely pass Rust variables/constants into a script via an external [`Scope`](https://schungx.github.io/rhai/rust/scope.html).
* Easily [call a script-defined function](https://schungx.github.io/rhai/engine/call-fn.html) from Rust.
diff --git a/doc/src/about/features.md b/doc/src/about/features.md
index 16910c63..bce5bd69 100644
--- a/doc/src/about/features.md
+++ b/doc/src/about/features.md
@@ -6,7 +6,7 @@ Features
Easy
----
-* Easy-to-use language similar to JS+Rust with dynamic typing.
+* Easy-to-use language similar to JavaScript+Rust with dynamic typing.
* Tight integration with native Rust [functions]({{rootUrl}}/rust/functions.md) and [types]({{rootUrl}}/rust/custom.md), including [getters/setters]({{rootUrl}}/rust/getters-setters.md), [methods]({{rootUrl}}/rust/custom.md) and [indexers]({{rootUrl}}/rust/indexers.md).
diff --git a/doc/src/about/non-design.md b/doc/src/about/non-design.md
index 2b07946e..22b70f7d 100644
--- a/doc/src/about/non-design.md
+++ b/doc/src/about/non-design.md
@@ -26,7 +26,7 @@ Due to this intended usage, Rhai deliberately keeps the language simple and smal
such as classes, inheritance, first-class functions, closures, concurrency, byte-codes, JIT etc.
Avoid the temptation to write full-fledge program logic entirely in Rhai - that use case is best fulfilled by
-more complete languages such as JS or Lua.
+more complete languages such as JavaScript or Lua.
Therefore, in actual practice, it is usually best to expose a Rust API into Rhai for scripts to call.
All your core functionalities should be in Rust.
diff --git a/doc/src/appendix/literals.md b/doc/src/appendix/literals.md
index 1f14b9fb..a308e951 100644
--- a/doc/src/appendix/literals.md
+++ b/doc/src/appendix/literals.md
@@ -3,14 +3,14 @@ Literals Syntax
{{#include ../links.md}}
-| Type | Literal syntax |
-| :--------------------------------: | :---------------------------------------: |
-| `INT` | `42`, `-123`, `0` |
-| `FLOAT` | `42.0`, `-123.456`, `0.0` |
-| [String] | `"... \x?? \u???? \U???????? ..."` |
-| Character | `"... \x?? \u???? \U???????? ..."` |
-| [`Array`] | `[ ???, ???, ??? ]` |
-| [Object map] | `#{ a: ???, b: ???, c: ???, "def": ??? }` |
-| Boolean true | `true` |
-| Boolean false | `false` |
-| `Nothing`/`null`/`nil`/`void`/Unit | `()` |
+| Type | Literal syntax |
+| :--------------------------------: | :------------------------------------------------------------------------------: |
+| `INT` | `42`, `-123`, `0`,
`0x????..` (hex), `0b????..` (binary), `0o????..` (octal) |
+| `FLOAT` | `42.0`, `-123.456`, `0.0` |
+| [String] | `"... \x?? \u???? \U???????? ..."` |
+| Character | `"... \x?? \u???? \U???????? ..."` |
+| [`Array`] | `[ ???, ???, ??? ]` |
+| [Object map] | `#{ a: ???, b: ???, c: ???, "def": ??? }` |
+| Boolean true | `true` |
+| Boolean false | `false` |
+| `Nothing`/`null`/`nil`/`void`/Unit | `()` |
diff --git a/doc/src/appendix/operators.md b/doc/src/appendix/operators.md
index 4a1f4a2f..56782b95 100644
--- a/doc/src/appendix/operators.md
+++ b/doc/src/appendix/operators.md
@@ -3,28 +3,28 @@ Operators
{{#include ../links.md}}
-| Operator | Description | Binary? |
-| :---------------: | ---------------------------- | :-----: |
-| `+` | Add | Yes |
-| `-` | Subtract, Minus | Yes/No |
-| `*` | Multiply | Yes |
-| `/` | Divide | Yes |
-| `%` | Modulo | Yes |
-| `~` | Power | Yes |
-| `>>` | Right bit-shift | Yes |
-| `<<` | Left bit-shift | Yes |
-| `&` | Bit-wise AND, Boolean AND | Yes |
-| \|
| Bit-wise OR, Boolean OR | Yes |
-| `^` | Bit-wise XOR | Yes |
-| `==` | Equals to | Yes |
-| `~=` | Not equals to | Yes |
-| `>` | Greater than | Yes |
-| `>=` | Greater than or equals to | Yes |
-| `<` | Less than | Yes |
-| `<=` | Less than or equals to | Yes |
-| `>=` | Greater than or equals to | Yes |
-| `&&` | Boolean AND (short-circuits) | Yes |
-| \|\|
| Boolean OR (short-circuits) | Yes |
-| `~` | Boolean NOT | No |
-| `[` .. `]` | Indexing | Yes |
-| `.` | Property access, Method call | Yes |
+| Operator | Description | Binary? |
+| :---------------: | ------------------------------ | :-----: |
+| `+` | Add | Yes |
+| `-` | Subtract, Minus | Yes/No |
+| `*` | Multiply | Yes |
+| `/` | Divide | Yes |
+| `%` | Modulo | Yes |
+| `~` | Power | Yes |
+| `>>` | Right bit-shift | Yes |
+| `<<` | Left bit-shift | Yes |
+| `&` | Bit-wise _And_, Boolean _And_ | Yes |
+| \|
| Bit-wise _Or_, Boolean _Or_ | Yes |
+| `^` | Bit-wise _Xor_ | Yes |
+| `==` | Equals to | Yes |
+| `~=` | Not equals to | Yes |
+| `>` | Greater than | Yes |
+| `>=` | Greater than or equals to | Yes |
+| `<` | Less than | Yes |
+| `<=` | Less than or equals to | Yes |
+| `>=` | Greater than or equals to | Yes |
+| `&&` | Boolean _And_ (short-circuits) | Yes |
+| \|\|
| Boolean _Or_ (short-circuits) | Yes |
+| `!` | Boolean _Not_ | No |
+| `[` .. `]` | Indexing | Yes |
+| `.` | Property access, Method call | Yes |
diff --git a/doc/src/language/arrays.md b/doc/src/language/arrays.md
index 5730d862..89870f5f 100644
--- a/doc/src/language/arrays.md
+++ b/doc/src/language/arrays.md
@@ -38,6 +38,7 @@ The following methods (mostly defined in the [`BasicArrayPackage`]({{rootUrl}}/r
| `clear` | _none_ | empties the array |
| `truncate` | target length | cuts off the array at exactly a specified length (discarding all subsequent elements) |
+
Examples
--------
diff --git a/doc/src/language/eval.md b/doc/src/language/eval.md
index f7f9965b..babb9242 100644
--- a/doc/src/language/eval.md
+++ b/doc/src/language/eval.md
@@ -17,7 +17,7 @@ let script = "let y = x;"; // build a script
script += "y += foo(y);";
script += "x + y";
-let result = eval(script); // <- look, JS, we can also do this!
+let result = eval(script); // <- look, JavaScript, we can also do this!
print("Answer: " + result); // prints 42
diff --git a/doc/src/language/functions.md b/doc/src/language/functions.md
index 30604a53..47a6c717 100644
--- a/doc/src/language/functions.md
+++ b/doc/src/language/functions.md
@@ -105,4 +105,4 @@ 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 JS's `function` keyword.
+This is similar to Rust and many other modern languages, such as JavaScript's `function` keyword.
diff --git a/doc/src/language/modules/imp-resolver.md b/doc/src/language/modules/imp-resolver.md
index a36f930b..9634f633 100644
--- a/doc/src/language/modules/imp-resolver.md
+++ b/doc/src/language/modules/imp-resolver.md
@@ -43,18 +43,14 @@ impl ModuleResolver for MyModuleResolver {
}
}
-fn main() -> Result<(), Box> {
- let mut engine = Engine::new();
+let mut engine = Engine::new();
- // Set the custom module resolver into the 'Engine'.
- engine.set_module_resolver(Some(MyModuleResolver {}));
+// 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(())
-}
+engine.consume(r#"
+ import "hello" as foo; // this 'import' statement will call
+ // 'MyModuleResolver::resolve' with "hello" as path
+ foo:bar();
+"#)?;
```
diff --git a/doc/src/language/num-op.md b/doc/src/language/num-op.md
index a7bd524d..fa96f1e9 100644
--- a/doc/src/language/num-op.md
+++ b/doc/src/language/num-op.md
@@ -22,19 +22,19 @@ number = -5 - +5;
Binary Operators
----------------
-| Operator | Description | Integers only |
-| -------- | ---------------------------------------------------- | :-----------: |
-| `+` | Plus | |
-| `-` | Minus | |
-| `*` | Multiply | |
-| `/` | Divide (integer division if acting on integer types) | |
-| `%` | Modulo (remainder) | |
-| `~` | Power | |
-| `&` | Binary _And_ bit-mask | Yes |
-| `|` | Binary _Or_ bit-mask | Yes |
-| `^` | Binary _Xor_ bit-mask | Yes |
-| `<<` | Left bit-shift | Yes |
-| `>>` | Right bit-shift | Yes |
+| Operator | Description | Integers only |
+| --------------- | ---------------------------------------------------- | :-----------: |
+| `+` | Plus | |
+| `-` | Minus | |
+| `*` | Multiply | |
+| `/` | Divide (integer division if acting on integer types) | |
+| `%` | Modulo (remainder) | |
+| `~` | Power | |
+| `&` | Bit-wise _And_ | Yes |
+| \|
| Bit-wise _Or_ | Yes |
+| `^` | Bit-wise _Xor_ | Yes |
+| `<<` | Left bit-shift | Yes |
+| `>>` | Right bit-shift | Yes |
```rust
let x = (1 + 2) * (6 - 4) / 2; // arithmetic, with parentheses
diff --git a/doc/src/language/object-maps.md b/doc/src/language/object-maps.md
index 16d6b6f0..dc1adc45 100644
--- a/doc/src/language/object-maps.md
+++ b/doc/src/language/object-maps.md
@@ -61,7 +61,7 @@ Examples
let y = #{ // object map literal with 3 properties
a: 1,
bar: "hello",
- "baz!$@": 123.456, // like JS, you can use any string as property names...
+ "baz!$@": 123.456, // like JavaScript, you can use any string as property names...
"": false, // even the empty string!
a: 42 // <- syntax error: duplicated property name
diff --git a/doc/src/language/values-and-types.md b/doc/src/language/values-and-types.md
index 2aef02c3..b3e55cb4 100644
--- a/doc/src/language/values-and-types.md
+++ b/doc/src/language/values-and-types.md
@@ -14,7 +14,7 @@ The following primitive types are supported natively:
| **Immutable Unicode string** | `rhai::ImmutableString` (implemented as `Rc` or `Arc`) | `"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_ |
+| **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. |
diff --git a/doc/src/links.md b/doc/src/links.md
index ba4e57af..e59a8d45 100644
--- a/doc/src/links.md
+++ b/doc/src/links.md
@@ -69,6 +69,7 @@
[`Module`]: {{rootUrl}}/language/modules/index.md
[module]: {{rootUrl}}/language/modules/index.md
[modules]: {{rootUrl}}/language/modules/index.md
+[module resolver]: {{rootUrl}}/language/modules/imp-resolver.md
[`export`]: {{rootUrl}}/language/modules/export.md
[`import`]: {{rootUrl}}/language/modules/import.md
diff --git a/doc/src/rust/builtin-packages.md b/doc/src/rust/builtin-packages.md
deleted file mode 100644
index f77cc900..00000000
--- a/doc/src/rust/builtin-packages.md
+++ /dev/null
@@ -1 +0,0 @@
-# Built-in Packages
diff --git a/doc/src/rust/custom.md b/doc/src/rust/custom.md
index cd3998b6..da9af45d 100644
--- a/doc/src/rust/custom.md
+++ b/doc/src/rust/custom.md
@@ -26,21 +26,16 @@ impl TestStruct {
}
}
-fn main() -> Result<(), Box>
-{
- let engine = Engine::new();
+let mut engine = Engine::new();
- engine.register_type::();
+engine.register_type::();
- engine.register_fn("update", TestStruct::update);
- engine.register_fn("new_ts", TestStruct::new);
+engine.register_fn("update", TestStruct::update);
+engine.register_fn("new_ts", TestStruct::new);
- let result = engine.eval::("let x = new_ts(); x.update(); x")?;
+let result = engine.eval::("let x = new_ts(); x.update(); x")?;
- println!("result: {}", result.field); // prints 42
-
- Ok(())
-}
+println!("result: {}", result.field); // prints 42
```
Register a Custom Type
@@ -66,7 +61,7 @@ impl TestStruct {
}
}
-let engine = Engine::new();
+let mut engine = Engine::new();
engine.register_type::();
```
@@ -102,8 +97,9 @@ println!("result: {}", result.field); // prints 42
Method-Call Style vs. Function-Call Style
----------------------------------------
-In fact, any function with a first argument that is a `&mut` reference can be used as method calls because
-internally they are the same thing: methods on a type is implemented as a functions taking a `&mut` first argument.
+In fact, any function with a first argument that is a `&mut` reference can be used
+as method calls because internally they are the same thing: methods on a type is
+implemented as a functions taking a `&mut` first argument.
```rust
fn foo(ts: &mut TestStruct) -> i64 {
@@ -119,8 +115,8 @@ let result = engine.eval::(
println!("result: {}", result); // prints 1
```
-Under [`no_object`], however, the _method_ style of function calls (i.e. calling a function as an object-method)
-is no longer supported.
+Under [`no_object`], however, the _method_ style of function calls
+(i.e. calling a function as an object-method) is no longer supported.
```rust
// Below is a syntax error under 'no_object' because 'clear' cannot be called in method style.
diff --git a/doc/src/rust/fallible.md b/doc/src/rust/fallible.md
index 6c20bf94..16c16826 100644
--- a/doc/src/rust/fallible.md
+++ b/doc/src/rust/fallible.md
@@ -8,11 +8,6 @@ If a function is _fallible_ (i.e. it returns a `Result<_, Error>`), it can be re
The function must return `Result>`.
-`Box` implements `From<&str>` and `From` etc.
-and the error text gets converted into `Box`.
-
-The error values are `Box`-ed in order to reduce memory footprint of the error path, which should be hit rarely.
-
```rust
use rhai::{Engine, EvalAltResult, Position};
use rhai::RegisterResultFn; // use 'RegisterResultFn' trait for 'register_result_fn'
@@ -27,15 +22,20 @@ fn safe_divide(x: i64, y: i64) -> Result> {
}
}
-fn main()
-{
- let engine = Engine::new();
+let mut engine = Engine::new();
- // Fallible functions that return Result values must use register_result_fn()
- engine.register_result_fn("divide", safe_divide);
+// Fallible functions that return Result values must use register_result_fn()
+engine.register_result_fn("divide", safe_divide);
- if let Err(error) = engine.eval::("divide(40, 0)") {
- println!("Error: {:?}", *error); // prints ErrorRuntime("Division by zero detected!", (1, 1)")
- }
+if let Err(error) = engine.eval::("divide(40, 0)") {
+ println!("Error: {:?}", *error); // prints ErrorRuntime("Division by zero detected!", (1, 1)")
}
```
+
+Create a `Box`
+----------------------------
+
+`Box` implements `From<&str>` and `From` etc.
+and the error text gets converted into `Box`.
+
+The error values are `Box`-ed in order to reduce memory footprint of the error path, which should be hit rarely.
diff --git a/doc/src/rust/functions.md b/doc/src/rust/functions.md
index de60646f..aca6fe8e 100644
--- a/doc/src/rust/functions.md
+++ b/doc/src/rust/functions.md
@@ -29,30 +29,25 @@ fn get_any_value() -> Result> {
Ok((42_i64).into()) // standard types can use 'into()'
}
-fn main() -> Result<(), Box>
-{
- let engine = Engine::new();
+let mut engine = Engine::new();
- engine.register_fn("add", add_len);
- engine.register_fn("add_str", add_len_str);
+engine.register_fn("add", add_len);
+engine.register_fn("add_str", add_len_str);
- let result = engine.eval::(r#"add(40, "xx")"#)?;
+let result = engine.eval::(r#"add(40, "xx")"#)?;
- println!("Answer: {}", result); // prints 42
+println!("Answer: {}", result); // prints 42
- let result = engine.eval::(r#"add_str(40, "xx")"#)?;
+let result = engine.eval::(r#"add_str(40, "xx")"#)?;
- println!("Answer: {}", result); // prints 42
+println!("Answer: {}", result); // prints 42
- // Functions that return Dynamic values must use register_result_fn()
- engine.register_result_fn("get_any_value", get_any_value);
+// Functions that return Dynamic values must use register_result_fn()
+engine.register_result_fn("get_any_value", get_any_value);
- let result = engine.eval::("get_any_value()")?;
+let result = engine.eval::("get_any_value()")?;
- println!("Answer: {}", result); // prints 42
-
- Ok(())
-}
+println!("Answer: {}", result); // prints 42
```
To create a [`Dynamic`] value, use the `Dynamic::from` method.
diff --git a/doc/src/rust/generic.md b/doc/src/rust/generic.md
index 84527951..c68bf562 100644
--- a/doc/src/rust/generic.md
+++ b/doc/src/rust/generic.md
@@ -17,14 +17,11 @@ fn show_it(x: &mut T) {
println!("put up a good show: {}!", x)
}
-fn main()
-{
- let engine = Engine::new();
+let mut engine = Engine::new();
- engine.register_fn("print", show_it::);
- engine.register_fn("print", show_it::);
- engine.register_fn("print", show_it::);
-}
+engine.register_fn("print", show_it::);
+engine.register_fn("print", show_it::);
+engine.register_fn("print", show_it::);
```
The above example shows how to register multiple functions
diff --git a/doc/src/rust/getters-setters.md b/doc/src/rust/getters-setters.md
index 18cf868e..92c659b9 100644
--- a/doc/src/rust/getters-setters.md
+++ b/doc/src/rust/getters-setters.md
@@ -28,7 +28,7 @@ impl TestStruct {
}
}
-let engine = Engine::new();
+let mut engine = Engine::new();
engine.register_type::();
diff --git a/doc/src/rust/indexers.md b/doc/src/rust/indexers.md
index 9c85e9a5..800c43b8 100644
--- a/doc/src/rust/indexers.md
+++ b/doc/src/rust/indexers.md
@@ -9,6 +9,9 @@ A custom type with an indexer function defined can use the bracket '`[]`' notati
Indexers are disabled when the [`no_index`] feature is used.
+For efficiency reasons, indexers **cannot** be used to overload (i.e. override) built-in indexing operations for
+[arrays] and [object maps].
+
```rust
#[derive(Clone)]
struct TestStruct {
@@ -28,7 +31,7 @@ impl TestStruct {
}
}
-let engine = Engine::new();
+let mut engine = Engine::new();
engine.register_type::();
@@ -42,6 +45,3 @@ let result = engine.eval::("let a = new_ts(); a[2] = 42; a[2]")?;
println!("Answer: {}", result); // prints 42
```
-
-For efficiency reasons, indexers **cannot** be used to overload (i.e. override) built-in indexing operations for
-[arrays] and [object maps].
diff --git a/doc/src/rust/operators.md b/doc/src/rust/operators.md
index b91b1cdc..8374bfb4 100644
--- a/doc/src/rust/operators.md
+++ b/doc/src/rust/operators.md
@@ -17,6 +17,10 @@ Similarly, comparison operators including `==`, `!=` etc. are all implemented as
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.
+
+Overload Operator via Rust Function
+----------------------------------
+
Operator functions cannot be defined as a script function (because operators syntax are not valid function names).
However, operator functions _can_ be registered to the [`Engine`] via the methods
@@ -48,6 +52,10 @@ engine.register_fn("+", mixed_add); // register '+' operator for
let result: i64 = engine.eval("1 + 1.0"); // prints 2.0 (normally an error)
```
+
+Considerations
+--------------
+
Normally, use operator overloading for [custom types] only.
Be very careful when overriding built-in operators because script authors expect standard operators to behave in a
diff --git a/doc/src/rust/print-custom.md b/doc/src/rust/print-custom.md
index 53996fe0..7205e1c3 100644
--- a/doc/src/rust/print-custom.md
+++ b/doc/src/rust/print-custom.md
@@ -3,8 +3,9 @@ Printing for Custom Types
{{#include ../links.md}}
-To use custom types for [`print`] and [`debug`], or convert its value into a [string], it is necessary that the following
-functions be registered (assuming the custom type is `T : Display + Debug`):
+To use custom types for [`print`] and [`debug`], or convert its value into a [string],
+it is necessary that the following functions be registered (assuming the custom type
+is `T : Display + Debug`):
| Function | Signature | Typical implementation | Usage |
| ----------- | ------------------------------------------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------- |
diff --git a/doc/src/rust/scope.md b/doc/src/rust/scope.md
index d5ad8fa5..a33e4b4c 100644
--- a/doc/src/rust/scope.md
+++ b/doc/src/rust/scope.md
@@ -20,40 +20,35 @@ then the same state is threaded through multiple invocations:
```rust
use rhai::{Engine, Scope, EvalAltResult};
-fn main() -> Result<(), Box>
-{
- let engine = Engine::new();
+let engine = Engine::new();
- // First create the state
- let mut scope = Scope::new();
+// First create the state
+let mut scope = Scope::new();
- // Then push (i.e. add) some initialized variables into the state.
- // Remember the system number types in Rhai are i64 (i32 if 'only_i32') ond f64.
- // Better stick to them or it gets hard working with the script.
- scope.push("y", 42_i64);
- scope.push("z", 999_i64);
+// Then push (i.e. add) some initialized variables into the state.
+// Remember the system number types in Rhai are i64 (i32 if 'only_i32') ond f64.
+// Better stick to them or it gets hard working with the script.
+scope.push("y", 42_i64);
+scope.push("z", 999_i64);
- // 'set_value' adds a variable when one doesn't exist
- scope.set_value("s", "hello, world!".to_string()); // remember to use 'String', not '&str'
+// 'set_value' adds a variable when one doesn't exist
+scope.set_value("s", "hello, world!".to_string()); // remember to use 'String', not '&str'
- // First invocation
- engine.eval_with_scope::<()>(&mut scope, r"
- let x = 4 + 5 - y + z + s.len;
- y = 1;
- ")?;
+// First invocation
+engine.eval_with_scope::<()>(&mut scope, r"
+ let x = 4 + 5 - y + z + s.len;
+ y = 1;
+")?;
- // Second invocation using the same state
- let result = engine.eval_with_scope::(&mut scope, "x")?;
+// Second invocation using the same state
+let result = engine.eval_with_scope::(&mut scope, "x")?;
- println!("result: {}", result); // prints 979
+println!("result: {}", result); // prints 979
- // Variable y is changed in the script - read it with 'get_value'
- assert_eq!(scope.get_value::("y").expect("variable y should exist"), 1);
+// Variable y is changed in the script - read it with 'get_value'
+assert_eq!(scope.get_value::("y").expect("variable y should exist"), 1);
- // We can modify scope variables directly with 'set_value'
- scope.set_value("y", 42_i64);
- assert_eq!(scope.get_value::("y").expect("variable y should exist"), 42);
-
- Ok(())
-}
+// We can modify scope variables directly with 'set_value'
+scope.set_value("y", 42_i64);
+assert_eq!(scope.get_value::("y").expect("variable y should exist"), 42);
```
diff --git a/doc/src/safety/index.md b/doc/src/safety/index.md
index d49768e4..2a06c1f4 100644
--- a/doc/src/safety/index.md
+++ b/doc/src/safety/index.md
@@ -8,28 +8,28 @@ resources used by a script so that it does not consume more resources that it is
The most important resources to watch out for are:
-* **Memory**: A malicous script may continuously grow a [string], an [array] or [object map] until all memory is consumed.
+* **Memory**: A malicious script may continuously grow a [string], an [array] or [object map] until all memory is consumed.
It may also create a large [array] or [object map] literal that exhausts all memory during parsing.
-* **CPU**: A malicous script may run an infinite tight loop that consumes all CPU cycles.
+* **CPU**: A malicious script may run an infinite tight loop that consumes all CPU cycles.
-* **Time**: A malicous script may run indefinitely, thereby blocking the calling system which is waiting for a result.
+* **Time**: A malicious script may run indefinitely, thereby blocking the calling system which is waiting for a result.
-* **Stack**: A malicous script may attempt an infinite recursive call that exhausts the call stack.
+* **Stack**: A malicious script may attempt an infinite recursive call that exhausts the call stack.
Alternatively, it may create a degenerated deep expression with so many levels that the parser exhausts the call stack
when parsing the expression; or even deeply-nested statement blocks, if nested deep enough.
Another way to cause a stack overflow is to load a [self-referencing module]({{rootUrl}}/language/modules/import.md).
-* **Overflows**: A malicous script may deliberately cause numeric over-flows and/or under-flows, divide by zero, and/or
+* **Overflows**: A malicious script may deliberately cause numeric over-flows and/or under-flows, divide by zero, and/or
create bad floating-point representations, in order to crash the system.
-* **Files**: A malicous script may continuously [`import`] an external module within an infinite loop,
+* **Files**: A malicious script may continuously [`import`] an external module within an infinite loop,
thereby putting heavy load on the file-system (or even the network if the file is not local).
Even when modules are not created from files, they still typically consume a lot of resources to load.
-* **Data**: A malicous script may attempt to read from and/or write to data that it does not own. If this happens,
+* **Data**: A malicious script may attempt to read from and/or write to data that it does not own. If this happens,
it is a severe security breach and may put the entire system at risk.
diff --git a/doc/src/start/builds/minimal.md b/doc/src/start/builds/minimal.md
index 57ad59c7..a76075e6 100644
--- a/doc/src/start/builds/minimal.md
+++ b/doc/src/start/builds/minimal.md
@@ -17,6 +17,16 @@ opt-level = "z" # optimize for size
```
+Use `i32` Only
+--------------
+
+For embedded systems that must optimize for code size, the architecture is commonly 32-bit.
+Use [`only_i32`] to prune away large sections of code implementing functions for other numeric types
+(including `i64`).
+
+If, for some reason, 64-bit long integers must be supported, use [`only_i64`] instead of [`only_i32`].
+
+
Opt-Out of Features
------------------
@@ -28,13 +38,17 @@ Omitting arrays ([`no_index`]) yields the most code-size savings, followed by fl
([`no_float`]), checked arithmetic/script resource limits ([`unchecked`]) and finally object maps and custom types ([`no_object`]).
Where the usage scenario does not call for loading externally-defined modules, use [`no_module`] to save some bytes.
-Disable script-defined functions ([`no_function`]) only when the feature is not needed because code size savings is minimal.
+Disable script-defined functions ([`no_function`]) when the feature is not needed.
+Both of these have little code size savings.
Use a Raw [`Engine`]
-------------------
[`Engine::new_raw`](#raw-engine) creates a _raw_ engine.
-A _raw_ engine supports, out of the box, only a very [restricted set](#built-in-operators) of basic arithmetic and logical operators.
+A _raw_ engine supports, out of the box, only a very [restricted set]({{rootUrl}}/engine/raw.md#built-in-operators)
+of basic arithmetic and logical operators.
+
Selectively include other necessary functionalities by loading specific [packages] to minimize the footprint.
+
Packages are sharable (even across threads via the [`sync`] feature), so they only have to be created once.
diff --git a/doc/src/start/builds/performance.md b/doc/src/start/builds/performance.md
index 65099707..5db1edc1 100644
--- a/doc/src/start/builds/performance.md
+++ b/doc/src/start/builds/performance.md
@@ -7,14 +7,17 @@ Use Only One Integer Type
------------------------
Some features are for performance. For example, using [`only_i32`] or [`only_i64`] disables all other integer types (such as `u16`).
+
If only a single integer type is needed in scripts - most of the time this is the case - it is best to avoid registering
-lots of functions related to other integer types that will never be used. As a result, performance should improve.
+lots of functions related to other integer types that will never be used. As a result, [`Engine`] creation will be faster
+because fewer functions need to be loaded.
Use Only 32-Bit Numbers
----------------------
If only 32-bit integers are needed - again, most of the time this is the case - using [`only_i32`] disables also `i64`.
+
On 64-bit targets this may not gain much, but on some 32-bit targets this improves performance due to 64-bit arithmetic
requiring more CPU cycles to complete.
@@ -24,4 +27,5 @@ Minimize Size of [`Dynamic`]
Turning on [`no_float`], and [`only_i32`] makes the key [`Dynamic`] data type only 8 bytes small on 32-bit targets
while normally it can be up to 16 bytes (e.g. on x86/x64 CPU's) in order to hold an `i64` or `f64`.
+
Making [`Dynamic`] small helps performance due to better cache efficiency.
diff --git a/doc/src/start/builds/wasm.md b/doc/src/start/builds/wasm.md
index ca2b0dbb..858e4d6e 100644
--- a/doc/src/start/builds/wasm.md
+++ b/doc/src/start/builds/wasm.md
@@ -14,8 +14,40 @@ But anyhow, do it because you _can_!
When building for WASM, certain features will not be available, such as the script file API's and loading modules
from external script files.
-Also look into [minimal builds] to reduce generated WASM size. As of this version, a typical, full-featured
-Rhai scripting engine compiles to a single WASM file less than 200KB gzipped. When excluding features that are
-marginal in WASM environment, the gzipped payload can be further shrunk to 160KB.
+
+Size
+----
+
+Also look into [minimal builds] to reduce generated WASM size.
+
+As of this version, a typical, full-featured Rhai scripting engine compiles to a single WASM file
+less than 200KB gzipped.
+
+When excluding features that are marginal in WASM environment, the gzipped payload can be
+further shrunk to 160KB.
+
+
+Speed
+-----
In benchmark tests, a WASM build runs scripts roughly 1.7-2.2x slower than a native optimized release build.
+
+
+Common Features
+---------------
+
+Some Rhai functionalities are not necessary in a WASM environment, so the following features
+are typically used for a WASM build:
+
+| Feature | Description |
+| :-----------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [`unchecked`] | When a WASM module panics, it doesn't crash the entire web app; however this also disables [maximum number of operations] and [progress] tracking so a script can still run indefinitely - the web app must terminate it itself. |
+| [`only_i32`] | JavaScript has only one `number` type and we're only supporting `wasm32` here (so far). |
+| [`no_module`] | A WASM module cannot load modules from the file system, so usually this is not needed, but the savings are minimal; alternatively, a custom [module resolver] can be provided that loads other Rhai scripts. |
+
+The following features are typically _not_ used because they don't make sense in a WASM build:
+
+| Feature | Why unnecessary |
+| :--------: | ------------------------------- |
+| [`sync`] | WASM is single-threaded. |
+| [`no_std`] | `std` lib works fine with WASM. |
diff --git a/doc/src/start/examples/rust.md b/doc/src/start/examples/rust.md
index d7a28271..1803c49b 100644
--- a/doc/src/start/examples/rust.md
+++ b/doc/src/start/examples/rust.md
@@ -5,17 +5,17 @@ Rust Examples
A number of examples can be found in the `examples` folder:
-| Example | Description |
-| ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
-| [`arrays_and_structs`](https://github.com/jonathandturner/rhai/tree/master/examples/arrays_and_structs.rs) | shows how to register a custom Rust type and using [arrays] on it |
-| [`custom_types_and_methods`](https://github.com/jonathandturner/rhai/tree/master/examples/custom_types_and_methods.rs) | shows how to register a custom Rust type and methods for it |
-| [`hello`](https://github.com/jonathandturner/rhai/tree/master/examples/hello.rs) | simple example that evaluates an expression and prints the result |
-| [`no_std`](https://github.com/jonathandturner/rhai/tree/master/examples/no_std.rs) | example to test out `no-std` builds |
-| [`reuse_scope`](https://github.com/jonathandturner/rhai/tree/master/examples/reuse_scope.rs) | evaluates two pieces of code in separate runs, but using a common [`Scope`] |
-| [`rhai_runner`](https://github.com/jonathandturner/rhai/tree/master/examples/rhai_runner.rs) | runs each filename passed to it as a Rhai script |
-| [`simple_fn`](https://github.com/jonathandturner/rhai/tree/master/examples/simple_fn.rs) | shows how to register a simple function |
-| [`strings`](https://github.com/jonathandturner/rhai/tree/master/examples/strings.rs) | shows different ways to register functions taking string arguments |
-| [`repl`](https://github.com/jonathandturner/rhai/tree/master/examples/repl.rs) | a simple REPL, interactively evaluate statements from stdin |
+| Example | Description |
+| ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
+| [`arrays_and_structs`](https://github.com/jonathandturner/rhai/tree/master/examples/arrays_and_structs.rs) | Shows how to register a custom Rust type and using [arrays] on it. |
+| [`custom_types_and_methods`](https://github.com/jonathandturner/rhai/tree/master/examples/custom_types_and_methods.rs) | Shows how to register a custom Rust type and methods for it. |
+| [`hello`](https://github.com/jonathandturner/rhai/tree/master/examples/hello.rs) | Simple example that evaluates an expression and prints the result. |
+| [`no_std`](https://github.com/jonathandturner/rhai/tree/master/examples/no_std.rs) | Example to test out `no-std` builds. |
+| [`reuse_scope`](https://github.com/jonathandturner/rhai/tree/master/examples/reuse_scope.rs) | Evaluates two pieces of code in separate runs, but using a common [`Scope`]. |
+| [`rhai_runner`](https://github.com/jonathandturner/rhai/tree/master/examples/rhai_runner.rs) | Runs each filename passed to it as a Rhai script. |
+| [`simple_fn`](https://github.com/jonathandturner/rhai/tree/master/examples/simple_fn.rs) | Shows how to register a simple function. |
+| [`strings`](https://github.com/jonathandturner/rhai/tree/master/examples/strings.rs) | Shows different ways to register functions taking string arguments. |
+| [`repl`](https://github.com/jonathandturner/rhai/tree/master/examples/repl.rs) | A simple REPL, interactively evaluate statements from stdin. |
The `repl` example is a particularly good one as it allows one to interactively try out Rhai's
language features in a standard REPL (**R**ead-**E**val-**P**rint **L**oop).
diff --git a/doc/src/start/examples/scripts.md b/doc/src/start/examples/scripts.md
index 50cfba4e..a4c8584c 100644
--- a/doc/src/start/examples/scripts.md
+++ b/doc/src/start/examples/scripts.md
@@ -10,21 +10,21 @@ There are also a number of examples scripts that showcase Rhai's features, all i
| Script | Description |
| -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
-| [`array.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/array.rhai) | [arrays] in Rhai |
-| [`assignment.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/assignment.rhai) | variable declarations |
-| [`comments.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/comments.rhai) | just comments |
+| [`array.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/array.rhai) | [Arrays] |
+| [`assignment.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/assignment.rhai) | Variable declarations |
+| [`comments.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/comments.rhai) | Just comments |
| [`for1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/for1.rhai) | [`for`](#for-loop) loops |
| [`for2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/for2.rhai) | [`for`](#for-loop) loops on [arrays] |
-| [`function_decl1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl1.rhai) | a [function] without parameters |
-| [`function_decl2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl2.rhai) | a [function] with two parameters |
-| [`function_decl3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl3.rhai) | a [function] with many parameters |
+| [`function_decl1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl1.rhai) | A [function] without parameters |
+| [`function_decl2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl2.rhai) | A [function] with two parameters |
+| [`function_decl3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl3.rhai) | A [function] with many parameters |
| [`if1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/if1.rhai) | [`if`](#if-statement) example |
-| [`loop.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/loop.rhai) | count-down [`loop`](#infinite-loop) in Rhai, emulating a `do` .. `while` loop |
-| [`op1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op1.rhai) | just simple addition |
-| [`op2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op2.rhai) | simple addition and multiplication |
-| [`op3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op3.rhai) | change evaluation order with parenthesis |
-| [`string.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/string.rhai) | [string] operations |
-| [`strings_map.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/strings_map.rhai) | [string] and [object map] operations |
+| [`loop.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/loop.rhai) | Count-down [`loop`](#infinite-loop) in Rhai, emulating a `do` .. `while` loop |
+| [`op1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op1.rhai) | Just simple addition |
+| [`op2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op2.rhai) | Simple addition and multiplication |
+| [`op3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op3.rhai) | Change evaluation order with parenthesis |
+| [`string.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/string.rhai) | [String] operations |
+| [`strings_map.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/strings_map.rhai) | [String] and [object map] operations |
| [`while.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/while.rhai) | [`while`](#while-loop) loop |
@@ -33,12 +33,12 @@ Benchmark Scripts
The following scripts are for benchmarking the speed of Rhai:
-| Scripts | Description |
-| ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- |
-| [`speed_test.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/speed_test.rhai) | a simple program to measure the speed of Rhai's interpreter (1 million iterations) |
-| [`primes.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/primes.rhai) | use Sieve of Eratosthenes to find all primes smaller than a limit |
-| [`fibonacci.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/fibonacci.rhai) | calculate the n-th Fibonacci number using a really dumb algorithm |
-| [`mat_mul.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/mat_mul.rhai) | matrix multiplication test to measure the speed of multi-dimensional array access |
+| Scripts | Description |
+| ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
+| [`speed_test.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/speed_test.rhai) | A simple program to measure the speed of Rhai's interpreter (1 million iterations). |
+| [`primes.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/primes.rhai) | Use Sieve of Eratosthenes to find all primes smaller than a limit. |
+| [`fibonacci.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/fibonacci.rhai) | Calculate the n-th Fibonacci number using a really dumb algorithm. |
+| [`mat_mul.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/mat_mul.rhai) | Matrix multiplication test to measure the speed of multi-dimensional array access. |
Running Example Scripts
diff --git a/doc/src/start/features.md b/doc/src/start/features.md
index 1f67fb28..57a8a44a 100644
--- a/doc/src/start/features.md
+++ b/doc/src/start/features.md
@@ -11,19 +11,19 @@ Notice that this deviates from Rust norm where features are _additive_.
Excluding unneeded functionalities can result in smaller, faster builds as well as
more control over what a script can (or cannot) do.
-| Feature | Description |
-| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `unchecked` | Disable arithmetic checking (such as over-flows and division by zero), call stack depth limit, operations count limit and modules loading limit. Beware that a bad script may panic the entire system! |
-| `sync` | Restrict all values types to those that are `Send + Sync`. Under this feature, all Rhai types, including [`Engine`], [`Scope`] and `AST`, are all `Send + Sync`. |
-| `no_optimize` | Disable the script optimizer. |
-| `no_float` | Disable floating-point numbers and math. |
-| `only_i32` | Set the system integer type to `i32` and disable all other integer types. `INT` is set to `i32`. |
-| `only_i64` | Set the system integer type to `i64` and disable all other integer types. `INT` is set to `i64`. |
-| `no_index` | Disable [arrays] and indexing features. |
-| `no_object` | Disable support for custom types and [object maps]. |
-| `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. |
+| Feature | Description |
+| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `unchecked` | Disable arithmetic checking (such as over-flows and division by zero), call stack depth limit, operations count limit and modules loading limit.
Beware that a bad script may panic the entire system! |
+| `sync` | Restrict all values types to those that are `Send + Sync`. Under this feature, all Rhai types, including [`Engine`], [`Scope`] and `AST`, are all `Send + Sync`. |
+| `no_optimize` | Disable [script optimization]. |
+| `no_float` | Disable floating-point numbers and math. |
+| `only_i32` | Set the system integer type to `i32` and disable all other integer types. `INT` is set to `i32`. |
+| `only_i64` | Set the system integer type to `i64` and disable all other integer types. `INT` is set to `i64`. |
+| `no_index` | Disable [arrays] and indexing features. |
+| `no_object` | Disable support for [custom types] and [object maps]. |
+| `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. |
Example
@@ -32,19 +32,19 @@ Example
The `Cargo.toml` configuration below turns on these six features:
* `sync` (everything `Send + Sync`)
-* `unchecked` (no checked arithmetic - should not be used with untrusted user scripts)
+* `unchecked` (disable all checking - should not be used with untrusted user scripts)
* `only_i32` (only 32-bit signed integers)
* `no_float` (no floating point numbers)
-* `no_module` (no loading external modules)
-* `no_function` (no defining functions)
+* `no_module` (no loading external [modules])
+* `no_function` (no defining [functions])
```toml
[dependencies]
rhai = { version = "{{version}}", features = [ "sync", "unchecked", "only_i32", "no_float", "no_module", "no_function" ] }
```
-The resulting scripting engine supports only the `i32` integer numeral type (and no others like `u32` or `i16`),
-no floating-point, is `Send + Sync` (so it can be safely used across threads), does not support defining functions
-nor loading external modules.
+The resulting scripting engine supports only the `i32` integer numeral type (and no others like `u32`, `i16` or `i64`),
+no floating-point, is `Send + Sync` (so it can be safely used across threads), does not support defining [functions]
+nor loading external [modules].
This configuration is perfect for an expression parser in a 32-bit embedded system without floating-point hardware.
diff --git a/src/lib.rs b/src/lib.rs
index 648a8dce..26cba976 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,7 +2,7 @@
//!
//! Rhai is a tiny, simple and very fast embedded scripting language for Rust
//! that gives you a safe and easy way to add scripting to your applications.
-//! It provides a familiar syntax based on JS and Rust and a simple Rust interface.
+//! It provides a familiar syntax based on JavaScript and Rust and a simple Rust interface.
//! Here is a quick example.
//!
//! First, the contents of `my_script.rhai`:
diff --git a/src/token.rs b/src/token.rs
index d5f84902..5c3d8969 100644
--- a/src/token.rs
+++ b/src/token.rs
@@ -677,12 +677,12 @@ impl<'a> TokenIterator<'a> {
_ => unreachable!(),
});
- while let Some(next_char_in_hex) = self.peek_next() {
- if !valid.contains(&next_char_in_hex) {
+ while let Some(next_char_in_escape_seq) = self.peek_next() {
+ if !valid.contains(&next_char_in_escape_seq) {
break;
}
- result.push(next_char_in_hex);
+ result.push(next_char_in_escape_seq);
self.eat_next();
}
}