Make API chainable.

This commit is contained in:
Stephen Chung
2020-07-12 11:46:53 +08:00
parent 2a8d63fd5f
commit 8449f8c55e
22 changed files with 223 additions and 143 deletions

View File

@@ -17,12 +17,12 @@ use rhai::{Engine, RegisterFn};
let mut engine = Engine::new();
// Register a custom operator called 'foo' and give it
// a precedence of 160 (i.e. between +|- and *|/)
engine.register_custom_operator("foo", 160).unwrap();
// Register the implementation of the customer operator as a function
engine.register_fn("foo", |x: i64, y: i64| (x * y) - (x + y));
// Register a custom operator named 'foo' and give it a precedence of 160
// (i.e. between +|- and *|/)
// Also register the implementation of the customer operator as a function
engine
.register_custom_operator("foo", 160).unwrap()
.register_fn("foo", |x: i64, y: i64| (x * y) - (x + y));
// The custom operator can be used in expressions
let result = engine.eval_expression::<i64>("1 + 2 * 3 foo 4 - 5 / 6")?;
@@ -71,9 +71,9 @@ All custom operators must be _binary_ (i.e. they take two operands).
_Unary_ custom operators are not supported.
```rust
engine.register_custom_operator("foo", 160).unwrap();
engine.register_fn("foo", |x: i64| x * x);
engine
.register_custom_operator("foo", 160).unwrap()
.register_fn("foo", |x: i64| x * x);
engine.eval::<i64>("1 + 2 * 3 foo 4 - 5 / 6")?; // error: function 'foo (i64, i64)' not found
```

View File

@@ -13,8 +13,9 @@ use rhai::Engine;
let mut engine = Engine::new();
engine.disable_symbol("if"); // disable the 'if' keyword
engine.disable_symbol("+="); // disable the '+=' operator
engine
.disable_symbol("if") // disable the 'if' keyword
.disable_symbol("+="); // disable the '+=' operator
// The following all return parse errors.

View File

@@ -9,7 +9,7 @@ Support for custom types can be turned off via the [`no_object`] feature.
```rust
use rhai::{Engine, EvalAltResult};
use rhai::RegisterFn;
use rhai::RegisterFn; // remember 'RegisterFn' is needed
#[derive(Clone)]
struct TestStruct {
@@ -28,14 +28,14 @@ impl TestStruct {
let mut engine = Engine::new();
engine.register_type::<TestStruct>();
engine.register_fn("update", TestStruct::update);
engine.register_fn("new_ts", TestStruct::new);
engine
.register_type::<TestStruct>() // most API's can be chained up
.register_fn("update", TestStruct::update)
.register_fn("new_ts", TestStruct::new);
let result = engine.eval::<TestStruct>("let x = new_ts(); x.update(); x")?;
println!("result: {}", result.field); // prints 42
println!("result: {}", result.field); // prints 42
```
Register a Custom Type
@@ -52,7 +52,7 @@ struct TestStruct {
}
impl TestStruct {
fn update(&mut self) { // methods take &mut as first parameter
fn update(&mut self) { // methods take &mut as first parameter
self.field += 41;
}
@@ -75,8 +75,9 @@ using one of the `Engine::register_XXX` API.
Below, the `update` and `new` methods are registered using `Engine::register_fn`.
```rust
engine.register_fn("update", TestStruct::update); // registers 'update(&mut TestStruct)'
engine.register_fn("new_ts", TestStruct::new); // registers 'new()'
engine
.register_fn("update", TestStruct::update) // registers 'update(&mut TestStruct)'
.register_fn("new_ts", TestStruct::new); // registers 'new()'
```
***Note**: Rhai follows the convention that methods of custom types take a `&mut` first parameter
@@ -107,13 +108,13 @@ fn foo(ts: &mut TestStruct) -> i64 {
ts.field
}
engine.register_fn("foo", foo); // register a Rust native function
engine.register_fn("foo", foo); // register a Rust native function
let result = engine.eval::<i64>(
"let x = new_ts(); x.foo()" // 'foo' can be called like a method on 'x'
"let x = new_ts(); x.foo()" // 'foo' can be called like a method on 'x'
)?;
println!("result: {}", result); // prints 1
println!("result: {}", result); // prints 1
```
Under [`no_object`], however, the _method_ style of function calls
@@ -133,13 +134,17 @@ If `Engine::register_type_with_name` is used to register the custom type
with a special "pretty-print" name, [`type_of()`] will return that name instead.
```rust
engine.register_type::<TestStruct>();
engine.register_fn("new_ts", TestStruct::new);
engine
.register_type::<TestStruct>()
.register_fn("new_ts", TestStruct::new);
let x = new_ts();
x.type_of() == "path::to::module::TestStruct";
engine.register_type_with_name::<TestStruct>("Hello");
engine.register_fn("new_ts", TestStruct::new);
engine
.register_type_with_name::<TestStruct>("Hello")
.register_fn("new_ts", TestStruct::new);
let x = new_ts();
x.type_of() == "Hello";
```

View File

@@ -31,8 +31,9 @@ fn get_any_value() -> Result<Dynamic, Box<EvalAltResult>> {
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)
.register_fn("add_str", add_len_str);
let result = engine.eval::<i64>(r#"add(40, "xx")"#)?;

View File

@@ -19,9 +19,10 @@ fn show_it<T: Display>(x: &mut T) {
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>)
.register_fn("print", show_it::<bool>)
.register_fn("print", show_it::<ImmutableString>);
```
The above example shows how to register multiple functions

View File

@@ -30,10 +30,10 @@ impl TestStruct {
let mut engine = Engine::new();
engine.register_type::<TestStruct>();
engine.register_get_set("xyz", TestStruct::get_field, TestStruct::set_field);
engine.register_fn("new_ts", TestStruct::new);
engine
.register_type::<TestStruct>()
.register_get_set("xyz", TestStruct::get_field, TestStruct::set_field)
.register_fn("new_ts", TestStruct::new);
// Return result can be 'String' - Rhai will automatically convert it from 'ImmutableString'
let result = engine.eval::<String>(r#"let a = new_ts(); a.xyz = "42"; a.xyz"#)?;

View File

@@ -38,8 +38,9 @@ engine.register_type::<TestStruct>();
engine.register_fn("new_ts", TestStruct::new);
// Shorthand: engine.register_indexer_get_set(TestStruct::get_field, TestStruct::set_field);
engine.register_indexer_get(TestStruct::get_field);
engine.register_indexer_set(TestStruct::set_field);
engine
.register_indexer_get(TestStruct::get_field)
.register_indexer_set(TestStruct::set_field);
let result = engine.eval::<i64>("let a = new_ts(); a[2] = 42; a[2]")?;

View File

@@ -15,3 +15,4 @@ A number of other configuration options are available from the `Engine` to fine-
| `set_max_string_size` | [`unchecked`] | Set the maximum length (in UTF-8 bytes) for [strings]. See [maximum length of strings]. |
| `set_max_array_size` | [`unchecked`], [`no_index`] | Set the maximum size for [arrays]. See [maximum size of arrays]. |
| `set_max_map_size` | [`unchecked`], [`no_object`] | Set the maximum number of properties for [object maps]. See [maximum size of object maps]. |
| `disable_symbol` | | Disable a certain keyword or operator. See [disable keywords and operators]. |

View File

@@ -28,11 +28,11 @@ 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);
// 'set_value' adds a variable when one doesn't exist
scope.set_value("s", "hello, world!".to_string()); // remember to use 'String', not '&str'
scope
.push("y", 42_i64)
.push("z", 999_i64)
.set_value("s", "hello, world!".to_string()); //'set_value' adds a variable when one doesn't exist
// remember to use 'String', not '&str'
// First invocation
engine.eval_with_scope::<()>(&mut scope, r"

View File

@@ -11,9 +11,10 @@ fn get_len1(s: String) -> i64 { s.len() as i64 } // <- Rhai will not
fn get_len2(s: &str) -> i64 { s.len() as i64 } // <- Rhai finds this function fine
fn get_len3(s: ImmutableString) -> i64 { s.len() as i64 } // <- the above is equivalent to this
engine.register_fn("len1", get_len1);
engine.register_fn("len2", get_len2);
engine.register_fn("len3", get_len3);
engine
.register_fn("len1", get_len1)
.register_fn("len2", get_len2)
.register_fn("len3", get_len3);
let len = engine.eval::<i64>("x.len1()")?; // error: function 'len1 (&str | ImmutableString)' not found
let len = engine.eval::<i64>("x.len2()")?; // works fine