Refine docs.

This commit is contained in:
Stephen Chung
2020-06-22 22:02:49 +08:00
parent b08f85a8b1
commit a9b168ba99
32 changed files with 260 additions and 221 deletions

View File

@@ -1 +0,0 @@
# Built-in Packages

View File

@@ -26,21 +26,16 @@ impl TestStruct {
}
}
fn main() -> Result<(), Box<EvalAltResult>>
{
let engine = Engine::new();
let mut engine = Engine::new();
engine.register_type::<TestStruct>();
engine.register_type::<TestStruct>();
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::<TestStruct>("let x = new_ts(); x.update(); x")?;
let result = engine.eval::<TestStruct>("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::<TestStruct>();
```
@@ -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::<i64>(
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.

View File

@@ -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<Dynamic, Box<EvalAltResult>>`.
`Box<EvalAltResult>` implements `From<&str>` and `From<String>` etc.
and the error text gets converted into `Box<EvalAltResult::ErrorRuntime>`.
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<Dynamic, Box<EvalAltResult>> {
}
}
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::<i64>("divide(40, 0)") {
println!("Error: {:?}", *error); // prints ErrorRuntime("Division by zero detected!", (1, 1)")
}
if let Err(error) = engine.eval::<i64>("divide(40, 0)") {
println!("Error: {:?}", *error); // prints ErrorRuntime("Division by zero detected!", (1, 1)")
}
```
Create a `Box<EvalAltResult>`
----------------------------
`Box<EvalAltResult>` implements `From<&str>` and `From<String>` etc.
and the error text gets converted into `Box<EvalAltResult::ErrorRuntime>`.
The error values are `Box`-ed in order to reduce memory footprint of the error path, which should be hit rarely.

View File

@@ -29,30 +29,25 @@ fn get_any_value() -> Result<Dynamic, Box<EvalAltResult>> {
Ok((42_i64).into()) // standard types can use 'into()'
}
fn main() -> Result<(), Box<EvalAltResult>>
{
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::<i64>(r#"add(40, "xx")"#)?;
let result = engine.eval::<i64>(r#"add(40, "xx")"#)?;
println!("Answer: {}", result); // prints 42
println!("Answer: {}", result); // prints 42
let result = engine.eval::<i64>(r#"add_str(40, "xx")"#)?;
let result = engine.eval::<i64>(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::<i64>("get_any_value()")?;
let result = engine.eval::<i64>("get_any_value()")?;
println!("Answer: {}", result); // prints 42
Ok(())
}
println!("Answer: {}", result); // prints 42
```
To create a [`Dynamic`] value, use the `Dynamic::from` method.

View File

@@ -17,14 +17,11 @@ fn show_it<T: Display>(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::<i64>);
engine.register_fn("print", show_it::<bool>);
engine.register_fn("print", show_it::<ImmutableString>);
}
engine.register_fn("print", show_it::<i64>);
engine.register_fn("print", show_it::<bool>);
engine.register_fn("print", show_it::<ImmutableString>);
```
The above example shows how to register multiple functions

View File

@@ -28,7 +28,7 @@ impl TestStruct {
}
}
let engine = Engine::new();
let mut engine = Engine::new();
engine.register_type::<TestStruct>();

View File

@@ -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::<TestStruct>();
@@ -42,6 +45,3 @@ let result = engine.eval::<i64>("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].

View File

@@ -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

View File

@@ -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 |
| ----------- | ------------------------------------------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------- |

View File

@@ -20,40 +20,35 @@ then the same state is threaded through multiple invocations:
```rust
use rhai::{Engine, Scope, EvalAltResult};
fn main() -> Result<(), Box<EvalAltResult>>
{
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::<i64>(&mut scope, "x")?;
// Second invocation using the same state
let result = engine.eval_with_scope::<i64>(&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::<i64>("y").expect("variable y should exist"), 1);
// Variable y is changed in the script - read it with 'get_value'
assert_eq!(scope.get_value::<i64>("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::<i64>("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::<i64>("y").expect("variable y should exist"), 42);
```