Update docs.

This commit is contained in:
Stephen Chung 2020-10-19 14:26:15 +08:00
parent d68c951795
commit c8c4ca21ad
18 changed files with 181 additions and 152 deletions

View File

@ -7,10 +7,13 @@ Rhai - Embedded Scripting for Rust
[![crates.io](https://img.shields.io/crates/v/rhai.svg)](https://crates.io/crates/rhai/) [![crates.io](https://img.shields.io/crates/v/rhai.svg)](https://crates.io/crates/rhai/)
[![crates.io](https://img.shields.io/crates/d/rhai)](https://crates.io/crates/rhai/) [![crates.io](https://img.shields.io/crates/d/rhai)](https://crates.io/crates/rhai/)
[![API Docs](https://docs.rs/rhai/badge.svg)](https://docs.rs/rhai/) [![API Docs](https://docs.rs/rhai/badge.svg)](https://docs.rs/rhai/)
[![chat](https://img.shields.io/discord/767611025456889857.svg?logo=discord)](https://discord.gg/yZMKAQ)
[![Reddit](https://img.shields.io/reddit/subreddit-subscribers/Rhai)](https://www.reddit.com/r/Rhai)
Rhai is an embedded scripting language and evaluation engine for Rust that gives a safe and easy way Rhai is an embedded scripting language and evaluation engine for Rust that gives a safe and easy way
to add scripting to any application. to add scripting to any application.
Supported targets and builds Supported targets and builds
--------------------------- ---------------------------
@ -19,6 +22,7 @@ Supported targets and builds
* `no-std` * `no-std`
* Minimum Rust version 1.45 * Minimum Rust version 1.45
Standard features Standard features
----------------- -----------------
@ -41,13 +45,15 @@ Standard features
* Serialization/deserialization support via [serde](https://crates.io/crates/serde) (requires the `serde` feature). * Serialization/deserialization support via [serde](https://crates.io/crates/serde) (requires the `serde` feature).
* Support for [minimal builds](https://schungx.github.io/rhai/start/builds/minimal.html) by excluding unneeded language [features](https://schungx.github.io/rhai/start/features.html). * Support for [minimal builds](https://schungx.github.io/rhai/start/builds/minimal.html) by excluding unneeded language [features](https://schungx.github.io/rhai/start/features.html).
Protection against attacks
-------------------------- Protected against attacks
-------------------------
* Sand-boxed - the scripting engine, if declared immutable, cannot mutate the containing environment unless [explicitly permitted](https://schungx.github.io/rhai/patterns/control.html). * 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.
For those who actually want their own language For those who actually want their own language
--------------------------------------------- ---------------------------------------------
@ -56,6 +62,7 @@ For those who actually want their own language
* Define [custom operators](https://schungx.github.io/rhai/engine/custom-op.html). * Define [custom operators](https://schungx.github.io/rhai/engine/custom-op.html).
* Extend the language with [custom syntax](https://schungx.github.io/rhai/engine/custom-syntax.html). * Extend the language with [custom syntax](https://schungx.github.io/rhai/engine/custom-syntax.html).
Documentation Documentation
------------- -------------
@ -65,12 +72,14 @@ To build _The Book_, first install [`mdbook`](https://github.com/rust-lang/mdBoo
and [`mdbook-tera`](https://github.com/avitex/mdbook-tera) (for templating). and [`mdbook-tera`](https://github.com/avitex/mdbook-tera) (for templating).
Running `mdbook build` builds it. Running `mdbook build` builds it.
Playground Playground
---------- ----------
An [Online Playground](https://alvinhochun.github.io/rhai-demo/) is available with syntax-highlighting editor. An [Online Playground](https://alvinhochun.github.io/rhai-demo/) is available with syntax-highlighting editor.
Scripts can be evaluated directly from the editor. Scripts can be evaluated directly from the editor.
License License
------- -------

View File

@ -36,8 +36,8 @@ The Rhai Scripting Language
4. [Register a Fallible Rust Function](rust/fallible.md) 4. [Register a Fallible Rust Function](rust/fallible.md)
6. [Override a Built-in Function](rust/override.md) 6. [Override a Built-in Function](rust/override.md)
7. [Operator Overloading](rust/operators.md) 7. [Operator Overloading](rust/operators.md)
8. [Register a Custom Type and its Methods](rust/custom.md) 8. [Register any Rust Type and its Methods](rust/custom.md)
1. [Getters and Setters](rust/getters-setters.md) 1. [Property Getters and Setters](rust/getters-setters.md)
2. [Indexers](rust/indexers.md) 2. [Indexers](rust/indexers.md)
3. [Disable Custom Types](rust/disable-custom.md) 3. [Disable Custom Types](rust/disable-custom.md)
4. [Printing Custom Types](rust/print-custom.md) 4. [Printing Custom Types](rust/print-custom.md)

View File

@ -3,7 +3,9 @@ Related Resources
{{#include ../links.md}} {{#include ../links.md}}
Other online documentation resources for Rhai:
Other Online Resources for Rhai
------------------------------
* [`crates.io`](https://crates.io/crates/rhai) - Rhai crate * [`crates.io`](https://crates.io/crates/rhai) - Rhai crate
@ -13,7 +15,13 @@ Other online documentation resources for Rhai:
* [Online Playground][playground] - Run scripts directly from editor * [Online Playground][playground] - Run scripts directly from editor
Other cool projects to check out: * [Discord Chat](https://discord.gg/yZMKAQ) - Rhai channel
* [Reddit](https://www.reddit.com/r/Rhai) - Rhai community
Other Cool Projects
-------------------
* [ChaiScript](http://chaiscript.com) - A strong inspiration for Rhai. An embedded scripting language for C++. * [ChaiScript](http://chaiscript.com) - A strong inspiration for Rhai. An embedded scripting language for C++.

BIN
doc/src/images/rhai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -8,7 +8,7 @@ Prelude
------- -------
When using the plugins system, the entire `rhai::plugin` module must be imported as a prelude When using the plugins system, the entire `rhai::plugin` module must be imported as a prelude
because code generated will these imports. because code generated will need these imports.
```rust ```rust
use rhai::plugin::*; use rhai::plugin::*;

View File

@ -1,12 +1,47 @@
Register a Custom Type and its Methods Register any Rust Type and its Methods
===================================== =====================================
{{#include ../links.md}} {{#include ../links.md}}
Rhai works seamlessly with _any_ complex Rust type. The type can be registered with the `Engine`, as below.
Free Typing
-----------
Rhai works seamlessly with _any_ Rust type. The type can be _anything_; it does not
have any prerequisites other than being `Clone`. It does not need to implement
any other trait or use any custom `#[derive]`.
This allows Rhai to be integrated into an existing code base with as little plumbing
as possible, usually silently and seamlessly. External types that are not defined
within the same crate (and thus cannot implement special Rhai traits or
use special `#[derive]`) can also be used easily with Rhai.
The reason why it is termed a _custom_ type throughout this documentation is that
Rhai natively supports a number of data types with fast, internal treatment (see
the list of [standard types]). Any type outside of this list is considered _custom_.
Any type not supported natively by Rhai is stored as a Rust _trait object_, with no
restrictions other than being `Clone` (plus `Send + Sync` under the [`sync`] feature).
It runs slightly slower than natively-supported types as it does not have built-in,
optimized implementations for commonly-used functions, but for all other purposes has
no difference.
Support for custom types can be turned off via the [`no_object`] feature. Support for custom types can be turned off via the [`no_object`] feature.
Register a Custom Type and its Methods
-------------------------------------
Any custom type must implement the `Clone` trait as this allows the [`Engine`] to pass by value.
If the [`sync`] feature is used, it must also be `Send + Sync`.
Notice that the custom type needs to be _registered_ using `Engine::register_type`
or `Engine::register_type_with_name`.
To use native methods on custom types in Rhai scripts, it is common to register an API
for the type using one of the `Engine::register_XXX` functions.
```rust ```rust
use rhai::{Engine, EvalAltResult}; use rhai::{Engine, EvalAltResult};
use rhai::RegisterFn; // remember 'RegisterFn' is needed use rhai::RegisterFn; // remember 'RegisterFn' is needed
@ -17,108 +52,67 @@ struct TestStruct {
} }
impl TestStruct { impl TestStruct {
fn update(&mut self) { fn new() -> Self {
self.field += 41; Self { field: 1 }
} }
fn new() -> Self { fn update(&mut self, x: i64) { // methods take &mut as first parameter
TestStruct { field: 1 } self.field += x;
} }
} }
let mut engine = Engine::new(); let mut engine = Engine::new();
// Most Engine API's can be chained up.
engine engine
.register_type::<TestStruct>() // most API's can be chained up .register_type::<TestStruct>() // register custom type
.register_fn("update", TestStruct::update) .register_fn("new_ts", TestStruct::new)
.register_fn("new_ts", TestStruct::new); .register_fn("update", TestStruct::update);
let result = engine.eval::<TestStruct>("let x = new_ts(); x.update(); x")?; // Cast result back to custom type.
let result = engine.eval::<TestStruct>(
r"
let x = new_ts(); // calls 'TestStruct::new'
x.update(41); // calls 'TestStruct::update'
x // 'x' holds a 'TestStruct'
"
)?;
println!("result: {}", result.field); // prints 42 println!("result: {}", result.field); // prints 42
``` ```
Rhai follows the convention that methods of custom types take a `&mut` first parameter
to that type, so that invoking methods can always update it.
Register a Custom Type All other parameters in Rhai are passed by value (i.e. clones).
---------------------
A custom type must implement `Clone` as this allows the [`Engine`] to pass by value.
Notice that the custom type needs to be _registered_ using `Engine::register_type`
or `Engine::register_type_with_name`.
```rust
#[derive(Clone)]
struct TestStruct {
field: i64
}
impl TestStruct {
fn update(&mut self) { // methods take &mut as first parameter
self.field += 41;
}
fn new() -> Self {
TestStruct { field: 1 }
}
}
let mut engine = Engine::new();
engine.register_type::<TestStruct>();
```
Methods on the Custom Type
-------------------------
To use native custom types, methods and functions in Rhai scripts, simply register them
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)'
.register_fn("new_ts", TestStruct::new); // registers 'new()'
```
***Note**: Rhai follows the convention that methods of custom types take a `&mut` first parameter
so that invoking methods can update the types. All other parameters in Rhai are passed by value (i.e. clones).*
**IMPORTANT: Rhai does NOT support normal references (i.e. `&T`) as parameters.** **IMPORTANT: Rhai does NOT support normal references (i.e. `&T`) as parameters.**
Use the Custom Type in Scripts
-----------------------------
The custom type is then ready for use in scripts. Scripts can see the functions and methods registered earlier.
Get the evaluation result back out just as before, this time casting to the custom type:
```rust
let result = engine.eval::<TestStruct>("let x = new_ts(); x.update(); x")?;
println!("result: {}", result.field); // prints 42
```
Method-Call Style vs. Function-Call Style Method-Call Style vs. Function-Call Style
---------------------------------------- ----------------------------------------
Any function with a first argument that is a `&mut` reference can be used 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 as method calls because internally they are the same thing: methods on a type is
implemented as a functions taking a `&mut` first argument. implemented as a functions taking a `&mut` first argument.
This design is similar to Rust. This design is similar to Rust.
```rust ```rust
fn foo(ts: &mut TestStruct) -> i64 { impl TestStruct {
ts.field fn foo(&mut self) -> i64 {
self.field
}
} }
engine.register_fn("foo", foo); // register a Rust native function engine.register_fn("foo", TestStruct::foo);
let result = engine.eval::<i64>( let result = engine.eval::<i64>(
"let x = new_ts(); x.foo()" // 'foo' can be called like a method on 'x' r"
let x = new_ts();
foo(x); // normal call to 'foo'
x.foo() // 'foo' can also be called like a method on 'x'
"
)?; )?;
println!("result: {}", result); // prints 1 println!("result: {}", result); // prints 1
@ -128,8 +122,9 @@ Under [`no_object`], however, the _method_ style of function calls
(i.e. calling a function as an object-method) is no longer supported. (i.e. calling a function as an object-method) is no longer supported.
```rust ```rust
// Below is a syntax error under 'no_object' because 'clear' cannot be called in method style. // Below is a syntax error under 'no_object'.
let result = engine.eval::<()>("let x = [1, 2, 3]; x.clear()")?; let result = engine.eval("let x = [1, 2, 3]; x.clear();")?;
// ^ cannot call in method style under 'no_object'
``` ```
@ -143,18 +138,16 @@ with a special "pretty-print" name, [`type_of()`] will return that name instead.
```rust ```rust
engine engine
.register_type::<TestStruct>() .register_type::<TestStruct1>()
.register_fn("new_ts", TestStruct::new); .register_fn("new_ts1", TestStruct1::new)
.register_type_with_name::<TestStruct2>("MyType")
.register_fn("new_ts2", TestStruct2::new);
let x = new_ts(); let ts1_type = engine.eval::<String>(r#"let x = new_ts1(); x.type_of()"#)?;
x.type_of() == "path::to::module::TestStruct"; let ts2_type = engine.eval::<String>(r#"let x = new_ts2(); x.type_of()"#)?;
engine println!("{}", ts1_type); // prints 'path::to::TestStruct'
.register_type_with_name::<TestStruct>("Hello") println!("{}", ts1_type); // prints 'MyType'
.register_fn("new_ts", TestStruct::new);
let x = new_ts();
x.type_of() == "Hello";
``` ```
@ -190,7 +183,9 @@ the `==` operator must be registered for the custom type:
```rust ```rust
// Assume 'TestStruct' implements `PartialEq` // Assume 'TestStruct' implements `PartialEq`
engine.register_fn("==", |item1: &mut TestStruct, item2: TestStruct| item1 == item2); engine.register_fn("==",
|item1: &mut TestStruct, item2: TestStruct| item1 == &item2
);
// Then this works in Rhai: // Then this works in Rhai:
let item = new_ts(); // construct a new 'TestStruct' let item = new_ts(); // construct a new 'TestStruct'

View File

@ -1,29 +1,32 @@
Custom Type Getters and Setters Custom Type Property Getters and Setters
============================== =======================================
{{#include ../links.md}} {{#include ../links.md}}
A custom type can also expose members by registering `get` and/or `set` functions. A [custom type] can also expose properties by registering `get` and/or `set` functions.
Getters and setters each take a `&mut` reference to the first parameter. Getters and setters each take a `&mut` reference to the first parameter.
Getters and setters are disabled when the [`no_object`] feature is used. Getters and setters are disabled when the [`no_object`] feature is used.
| `Engine` API | Description | Return Value of Function | | `Engine` API | Function signature(s)<br/>(`T: Clone` = custom type,<br/>`V: Clone` = data type) | Can mutate `T`? |
| --------------------- | ------------------------------------------------- | :-----------------------------------: | | --------------------- | -------------------------------------------------------------------------------- | :----------------------------: |
| `register_get` | register a getter | _any_ `T: Clone` | | `register_get` | `Fn(&mut T) -> V` | yes, but not advised |
| `register_set` | register a setter | _none_ | | `register_set` | `Fn(&mut T, V)` | yes |
| `register_get_set` | short-hand to register both a getter and a setter | _none_ | | `register_get_set` | getter: `Fn(&mut T) -> V`</br>setter: `Fn(&mut T, V)` | yes, but not advised in getter |
| `register_get_result` | register a getter | `Result<Dynamic, Box<EvalAltResult>>` | | `register_get_result` | `Fn(&mut T) -> Result<Dynamic, Box<EvalAltResult>>` | yes, but not advised |
| `register_set_result` | register a setter | `Result<(), Box<EvalAltResult>>` | | `register_set_result` | `Fn(&mut T, V) -> Result<(), Box<EvalAltResult>>` | yes |
By convention, property getters are not supposed to mutate the [custom type], although there is nothing
that prevents this mutation.
Cannot Override Object Maps Cannot Override Object Maps
-------------------------- --------------------------
Getters and setters are only intended for [custom types]. Property getters and setters are mainly intended for [custom types].
Any getter or setter function registered for [object maps] is simply ignored because Any getter or setter function registered for [object maps] is simply _ignored_ because
the get/set calls will be interpreted as properties on the [object maps]. the get/set calls will be interpreted as properties on the [object maps].
@ -47,7 +50,7 @@ impl TestStruct {
} }
fn new() -> Self { fn new() -> Self {
TestStruct { field: "hello" } Self { field: "hello" }
} }
} }

View File

@ -3,23 +3,30 @@ Custom Type Indexers
{{#include ../links.md}} {{#include ../links.md}}
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_ `]` > _object_ `[` _index_ `]`
Like getters and setters, indexers take a `&mut` reference to the first parameter. Like property [getters/setters], indexers take a `&mut` reference to the first parameter.
They also take an additional parameter of any type that serves as the _index_ within brackets.
Indexers are disabled when the [`no_index`] feature is used. Indexers are disabled when the [`no_index`] feature is used.
| `Engine` API | Description | Return Value of Function | | `Engine` API | Function signature(s)<br/>(`T: Clone` = custom type,<br/>`X: Clone` = index type,<br/>`V: Clone` = data type) | Can mutate `T`? |
| ----------------------------- | -------------------------------------------------------- | :-----------------------------------: | | ----------------------------- | ------------------------------------------------------------------------------------------------------------- | :----------------------------: |
| `register_indexer_get` | register an index getter | _any_ `T: Clone` | | `register_indexer_get` | `Fn(&mut T, X) -> V` | yes, but not advised |
| `register_indexer_set` | register an index setter | _none_ | | `register_indexer_set` | `Fn(&mut T, X, V)` | yes |
| `register_indexer_get_set` | short-hand to register both an index getter and a setter | _none_ | | `register_indexer_get_set` | getter: `Fn(&mut T, X) -> V`<br/>setter: `Fn(&mut T, X, V)` | yes, but not advised in getter |
| `register_indexer_get_result` | register an index getter | `Result<Dynamic, Box<EvalAltResult>>` | | `register_indexer_get_result` | `Fn(&mut T, X) -> Result<Dynamic, Box<EvalAltResult>>` | yes, but not advised |
| `register_indexer_set_result` | register an index setter | `Result<(), Box<EvalAltResult>>` | | `register_indexer_set_result` | `Fn(&mut T, X, V) -> Result<(), Box<EvalAltResult>>` | yes |
By convention, index getters are not supposed to mutate the [custom type], although there is nothing
that prevents this mutation.
**IMPORTANT: Rhai does NOT support normal references (i.e. `&T`) as parameters.**
Cannot Override Arrays, Object Maps and Strings Cannot Override Arrays, Object Maps and Strings
@ -42,15 +49,15 @@ struct TestStruct {
impl TestStruct { impl TestStruct {
// Remember &mut must be used even for getters // Remember &mut must be used even for getters
fn get_field(&mut self, index: i64) -> i64 { fn get_field(&mut self, index: String) -> i64 {
self.fields[index as usize] self.fields[index.len()]
} }
fn set_field(&mut self, index: i64, value: i64) { fn set_field(&mut self, index: String, value: i64) {
self.fields[index as usize] = value self.fields[index.len()] = value
} }
fn new() -> Self { fn new() -> Self {
TestStruct { fields: vec![1, 2, 3, 4, 5] } Self { fields: vec![1, 2, 3, 4, 5] }
} }
} }
@ -63,9 +70,13 @@ engine
.register_indexer_get(TestStruct::get_field) .register_indexer_get(TestStruct::get_field)
.register_indexer_set(TestStruct::set_field); .register_indexer_set(TestStruct::set_field);
let result = engine.eval::<i64>("let a = new_ts(); a[2] = 42; a[2]")?; let result = engine.eval::<i64>(
r#"
let a = new_ts();
a["xyz"] = 42; // these indexers use strings
a["xyz"] // as the index type
"#
)?;
println!("Answer: {}", result); // prints 42 println!("Answer: {}", result); // prints 42
``` ```
**IMPORTANT: Rhai does NOT support normal references (i.e. `&T`) as parameters.**

View File

@ -65,7 +65,7 @@ The function signature passed to `Engine::register_raw_fn` takes the following f
where: where:
* `T: Variant + Clone` - return type of the function. * `T: Clone` - return type of the function.
* `context: NativeCallContext` - the current _native call context_, which exposes the following: * `context: NativeCallContext` - the current _native call context_, which exposes the following:

View File

@ -11,7 +11,7 @@ impl TestStruct {
} }
fn new() -> Self { fn new() -> Self {
TestStruct { x: 1 } Self { x: 1 }
} }
} }

View File

@ -11,7 +11,7 @@ impl TestStruct {
} }
fn new() -> Self { fn new() -> Self {
TestStruct { x: 1 } Self { x: 1 }
} }
} }

View File

@ -88,7 +88,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { field: 1 } } /// fn new() -> Self { Self { field: 1 } }
/// fn update(&mut self, offset: i64) { self.field += offset; } /// fn update(&mut self, offset: i64) { self.field += offset; }
/// } /// }
/// ///
@ -130,7 +130,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { field: 1 } } /// fn new() -> Self { Self { field: 1 } }
/// } /// }
/// ///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> { /// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
@ -200,7 +200,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { field: 1 } } /// fn new() -> Self { Self { field: 1 } }
/// // Even a getter must start with `&mut self` and not `&self`. /// // Even a getter must start with `&mut self` and not `&self`.
/// fn get_field(&mut self) -> i64 { self.field } /// fn get_field(&mut self) -> i64 { self.field }
/// } /// }
@ -252,7 +252,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { field: 1 } } /// fn new() -> Self { Self { field: 1 } }
/// // Even a getter must start with `&mut self` and not `&self`. /// // Even a getter must start with `&mut self` and not `&self`.
/// fn get_field(&mut self) -> Result<Dynamic, Box<EvalAltResult>> { /// fn get_field(&mut self) -> Result<Dynamic, Box<EvalAltResult>> {
/// Ok(self.field.into()) /// Ok(self.field.into())
@ -295,7 +295,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { field: 1 } } /// fn new() -> Self { Self { field: 1 } }
/// fn set_field(&mut self, new_val: i64) { self.field = new_val; } /// fn set_field(&mut self, new_val: i64) { self.field = new_val; }
/// } /// }
/// ///
@ -348,7 +348,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { field: 1 } } /// fn new() -> Self { Self { field: 1 } }
/// fn set_field(&mut self, new_val: i64) -> Result<(), Box<EvalAltResult>> { /// fn set_field(&mut self, new_val: i64) -> Result<(), Box<EvalAltResult>> {
/// self.field = new_val; /// self.field = new_val;
/// Ok(()) /// Ok(())
@ -386,8 +386,7 @@ impl Engine {
U: Variant + Clone, U: Variant + Clone,
{ {
self.register_result_fn(&make_setter(name), move |obj: &mut T, value: U| { self.register_result_fn(&make_setter(name), move |obj: &mut T, value: U| {
callback(obj, value)?; callback(obj, value).map(Into::into)
Ok(().into())
}) })
} }
@ -405,7 +404,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { field: 1 } } /// fn new() -> Self { Self { field: 1 } }
/// // Even a getter must start with `&mut self` and not `&self`. /// // Even a getter must start with `&mut self` and not `&self`.
/// fn get_field(&mut self) -> i64 { self.field } /// fn get_field(&mut self) -> i64 { self.field }
/// fn set_field(&mut self, new_val: i64) { self.field = new_val; } /// fn set_field(&mut self, new_val: i64) { self.field = new_val; }
@ -462,7 +461,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
/// // Even a getter must start with `&mut self` and not `&self`. /// // Even a getter must start with `&mut self` and not `&self`.
/// fn get_field(&mut self, index: i64) -> i64 { self.fields[index as usize] } /// fn get_field(&mut self, index: i64) -> i64 { self.fields[index as usize] }
/// } /// }
@ -534,7 +533,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
/// // Even a getter must start with `&mut self` and not `&self`. /// // Even a getter must start with `&mut self` and not `&self`.
/// fn get_field(&mut self, index: i64) -> Result<Dynamic, Box<EvalAltResult>> { /// fn get_field(&mut self, index: i64) -> Result<Dynamic, Box<EvalAltResult>> {
/// Ok(self.fields[index as usize].into()) /// Ok(self.fields[index as usize].into())
@ -600,7 +599,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
/// fn set_field(&mut self, index: i64, value: i64) { self.fields[index as usize] = value; } /// fn set_field(&mut self, index: i64, value: i64) { self.fields[index as usize] = value; }
/// } /// }
/// ///
@ -672,7 +671,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
/// fn set_field(&mut self, index: i64, value: i64) -> Result<(), Box<EvalAltResult>> { /// fn set_field(&mut self, index: i64, value: i64) -> Result<(), Box<EvalAltResult>> {
/// self.fields[index as usize] = value; /// self.fields[index as usize] = value;
/// Ok(()) /// Ok(())
@ -724,8 +723,7 @@ impl Engine {
} }
self.register_result_fn(FN_IDX_SET, move |obj: &mut T, index: X, value: U| { self.register_result_fn(FN_IDX_SET, move |obj: &mut T, index: X, value: U| {
callback(obj, index, value)?; callback(obj, index, value).map(Into::into)
Ok(().into())
}) })
} }
@ -745,7 +743,7 @@ impl Engine {
/// } /// }
/// ///
/// impl TestStruct { /// impl TestStruct {
/// fn new() -> Self { TestStruct { fields: vec![1, 2, 3, 4, 5] } } /// fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
/// // Even a getter must start with `&mut self` and not `&self`. /// // Even a getter must start with `&mut self` and not `&self`.
/// fn get_field(&mut self, index: i64) -> i64 { self.fields[index as usize] } /// fn get_field(&mut self, index: i64) -> i64 { self.fields[index as usize] }
/// fn set_field(&mut self, index: i64, value: i64) { self.fields[index as usize] = value; } /// fn set_field(&mut self, index: i64, value: i64) { self.fields[index as usize] = value; }

View File

@ -934,7 +934,9 @@ impl Engine {
level, level,
) )
.map_err(|err| match *err { .map_err(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(_, _) => { EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
if fn_sig.ends_with("]=") =>
{
EvalAltResult::ErrorIndexingType( EvalAltResult::ErrorIndexingType(
self.map_type_name(val_type_name).into(), self.map_type_name(val_type_name).into(),
Position::none(), Position::none(),
@ -1381,9 +1383,12 @@ impl Engine {
) )
.map(|(v, _)| v.into()) .map(|(v, _)| v.into())
.map_err(|err| match *err { .map_err(|err| match *err {
EvalAltResult::ErrorFunctionNotFound(_, _) => Box::new( EvalAltResult::ErrorFunctionNotFound(fn_sig, _) if fn_sig.ends_with("]") => {
EvalAltResult::ErrorIndexingType(type_name.into(), Position::none()), Box::new(EvalAltResult::ErrorIndexingType(
), type_name.into(),
Position::none(),
))
}
_ => err, _ => err,
}) })
} }

View File

@ -84,7 +84,7 @@ fn test_array_with_structs() -> Result<(), Box<EvalAltResult>> {
} }
fn new() -> Self { fn new() -> Self {
TestStruct { x: 1 } Self { x: 1 }
} }
} }

View File

@ -51,7 +51,7 @@ fn test_struct_with_float() -> Result<(), Box<EvalAltResult>> {
} }
fn new() -> Self { fn new() -> Self {
TestStruct { x: 1.0 } Self { x: 1.0 }
} }
} }

View File

@ -25,7 +25,7 @@ fn test_get_set() -> Result<(), Box<EvalAltResult>> {
} }
fn new() -> Self { fn new() -> Self {
TestStruct { Self {
x: 1, x: 1,
y: 0, y: 0,
array: vec![1, 2, 3, 4, 5], array: vec![1, 2, 3, 4, 5],

View File

@ -15,7 +15,7 @@ fn test_method_call() -> Result<(), Box<EvalAltResult>> {
} }
fn new() -> Self { fn new() -> Self {
TestStruct { x: 1 } Self { x: 1 }
} }
} }

View File

@ -20,7 +20,7 @@ fn test_mismatched_op_custom_type() {
impl TestStruct { impl TestStruct {
fn new() -> Self { fn new() -> Self {
TestStruct { x: 1 } Self { x: 1 }
} }
} }