From 6f2fecb76b1a3016406ee7813609c4b2474f4d01 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 14 Dec 2020 15:15:05 +0800 Subject: [PATCH] Add type iterator docs. --- RELEASES.md | 1 + doc/src/SUMMARY.md | 1 + doc/src/about/non-design.md | 4 +-- doc/src/about/related.md | 6 +++-- doc/src/language/assignment-op.md | 12 ++++----- doc/src/language/for.md | 2 +- doc/src/language/iterator.md | 45 +++++++++++++++++++++++++++++++ doc/src/language/logic.md | 27 +++++++++++++------ doc/src/language/modules/index.md | 2 +- doc/src/language/try-catch.md | 2 +- doc/src/links.md | 2 ++ doc/src/plugins/module.md | 2 +- doc/src/rust/modules/create.md | 2 +- doc/src/rust/modules/index.md | 2 +- doc/src/start/install.md | 3 ++- src/engine_api.rs | 6 ++--- 16 files changed, 91 insertions(+), 28 deletions(-) create mode 100644 doc/src/language/iterator.md diff --git a/RELEASES.md b/RELEASES.md index fc7cedf4..32b16d16 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -15,6 +15,7 @@ Bug fixes * Constants are no longer propagated by the optimizer if shadowed by a non-constant variable. * Constants passed as the `this` parameter to Rhai functions now throws an error if assigned to. +* Generic type parameter of `Engine::register_iterator` is `IntoIterator` instead of `Iterator`. Breaking changes ---------------- diff --git a/doc/src/SUMMARY.md b/doc/src/SUMMARY.md index 270f6d1b..556a60fb 100644 --- a/doc/src/SUMMARY.md +++ b/doc/src/SUMMARY.md @@ -82,6 +82,7 @@ The Rhai Scripting Language 11. [Do Loop](language/do.md) 12. [Loop Statement](language/loop.md) 13. [For Loop](language/for.md) + 1. [Iterators for Custom Types](language/iterator.md) 14. [Return Values](language/return.md) 15. [Throw Exception on Error](language/throw.md) 16. [Catch Exceptions](language/try-catch.md) diff --git a/doc/src/about/non-design.md b/doc/src/about/non-design.md index a8b06ea8..4f01b14a 100644 --- a/doc/src/about/non-design.md +++ b/doc/src/about/non-design.md @@ -44,8 +44,8 @@ It doesn't attempt to be a new language. For example: * **No formal language grammar** - Rhai uses a hand-coded lexer, a hand-coded top-down recursive-descent parser for statements, and a hand-coded Pratt parser for expressions. - This lack of formalism allows the _parser_ itself to be exposed as a service in order to support - [disabling keywords/operators][disable keywords and operators], adding [custom operators], + This lack of formalism allows the _tokenizer_ and _parser_ themselves to be exposed as services in order + to support [disabling keywords/operators][disable keywords and operators], adding [custom operators], and defining [custom syntax]. diff --git a/doc/src/about/related.md b/doc/src/about/related.md index 596b54e7..9b55003b 100644 --- a/doc/src/about/related.md +++ b/doc/src/about/related.md @@ -4,8 +4,10 @@ Related Resources {{#include ../links.md}} -Other Online Resources for Rhai ------------------------------- +Online Resources for Rhai +------------------------- + +* [GitHub](https://github.com/jonathandturner/rhai) - Home repository * [`crates.io`](https://crates.io/crates/rhai) - Rhai crate diff --git a/doc/src/language/assignment-op.md b/doc/src/language/assignment-op.md index d604dac3..5cfd73c5 100644 --- a/doc/src/language/assignment-op.md +++ b/doc/src/language/assignment-op.md @@ -34,7 +34,10 @@ number ^= 0x00ff; // number = number ^ 0x00ff; The Flexible `+=` ---------------- -The `+=` operator can also be used to build [strings]: +The the `+` and `+=` operators are often [overloaded][function overloading] to perform +build-up operations for different data types. + +For example, it is used to build [strings]: ```rust let my_str = "abc"; @@ -44,7 +47,7 @@ my_str += 12345; my_str == "abcABC12345" ``` -It may also be used to concatenate [arrays]: +to concatenate [arrays]: ```rust let my_array = [1, 2, 3]; @@ -53,7 +56,7 @@ my_array += [4, 5]; my_array == [1, 2, 3, 4, 5]; ``` -or mix two [object maps] together: +and mix two [object maps] together: ```rust let my_obj = #{a:1, b:2}; @@ -61,6 +64,3 @@ my_obj += #{c:3, d:4, e:5}; my_obj.len() == 5; ``` - -In fact, the `+` and `+=` operators are usually [overloaded][function overloading] when -something is to be _added_ to an existing type. diff --git a/doc/src/language/for.md b/doc/src/language/for.md index 4985b7aa..6af5a422 100644 --- a/doc/src/language/for.md +++ b/doc/src/language/for.md @@ -3,7 +3,7 @@ {{#include ../links.md}} -Iterating through a range or an [array], or any type with a registered _type iterator_, +Iterating through a range or an [array], or any type with a registered [type iterator], is provided by the `for` ... `in` loop. Like C, `continue` can be used to skip to the next iteration, by-passing all following statements; diff --git a/doc/src/language/iterator.md b/doc/src/language/iterator.md new file mode 100644 index 00000000..e885efba --- /dev/null +++ b/doc/src/language/iterator.md @@ -0,0 +1,45 @@ +Iterators for Custom Types +========================== + +{{#include ../links.md}} + +If a [custom type] is iterable, the [`for`](for.md) loop can be used to iterate through +its items in sequence. + +In order to use a [`for`](for.md) statement, a _type iterator_ must be registered for +the [custom type] in question. + +`Engine::register_iterator` allows registration of a _type iterator_ for any type +that implements `IntoIterator`: + +```rust +// Custom type +#[derive(Debug, Clone)] +struct TestStruct { ... } + +// Implement 'IntoIterator' trait +impl IntoIterator for TestStruct { + type Item = ...; + type IntoIter = SomeIterType; + + fn into_iter(self) -> Self::IntoIter { + ... + } +} + +engine + .register_type_with_name::("TestStruct") + .register_fn("new_ts", || TestStruct { ... }) + .register_iterator::(); // register type iterator +``` + +With a type iterator registered, the [custom type] can be iterated through: + +```rust +let ts = new_ts(); + +// Use 'for' statement to loop through items in 'ts' +for item in ts { + ... +} +``` diff --git a/doc/src/language/logic.md b/doc/src/language/logic.md index 498cab0d..edb1ae41 100644 --- a/doc/src/language/logic.md +++ b/doc/src/language/logic.md @@ -6,6 +6,15 @@ Logic Operators Comparison Operators ------------------- +| Operator | Description | +| :------: | ------------------------- | +| `==` | equals to | +| `!=` | not equals to | +| `>` | greater than | +| `>=` | greater than or equals to | +| `<` | less than | +| `<=` | less than or equals to | + Comparing most values of the same data type work out-of-the-box for all [standard types] supported by the system. However, if using a [raw `Engine`] without loading any [packages], comparisons can only be made between a limited @@ -43,15 +52,15 @@ ts != 42; // true - types cannot be compared Boolean operators ----------------- -| Operator | Description | -| ----------------- | ------------------------------------- | -| `!` | boolean _Not_ | -| `&&` | boolean _And_ (short-circuits) | -| \|\| | boolean _Or_ (short-circuits) | -| `&` | boolean _And_ (doesn't short-circuit) | -| \| | boolean _Or_ (doesn't short-circuit) | +| Operator | Description | Short-Circuits? | +| :---------------: | ------------- | :-------------: | +| `!` (prefix) | boolean _NOT_ | no | +| `&&` | boolean _AND_ | yes | +| `&` | boolean _AND_ | no | +| \|\| | boolean _OR_ | yes | +| \| | boolean _OR_ | no | -Double boolean operators `&&` and `||` _short-circuit_, meaning that the second operand will not be evaluated +Double boolean operators `&&` and `||` _short-circuit_ - meaning that the second operand will not be evaluated if the first one already proves the condition wrong. Single boolean operators `&` and `|` always evaluate both operands. @@ -65,3 +74,5 @@ a() | b(); // both a() and b() are evaluated a() & b(); // both a() and b() are evaluated ``` + +All boolean operators are [built in][built-in operators] for the `bool` data type. diff --git a/doc/src/language/modules/index.md b/doc/src/language/modules/index.md index 14931c3a..dd8c928a 100644 --- a/doc/src/language/modules/index.md +++ b/doc/src/language/modules/index.md @@ -6,7 +6,7 @@ Modules Rhai allows organizing code (functions, both Rust-based or script-based, and variables) into _modules_. Modules can be disabled via the [`no_module`] feature. -A module is of the type `Module` and holds a collection of functions, variables, type iterators and sub-modules. +A module is of the type `Module` and holds a collection of functions, variables, [type iterators] and sub-modules. It may be created entirely from Rust functions, or it may encapsulate a Rhai script together with the functions and variables defined by that script. diff --git a/doc/src/language/try-catch.md b/doc/src/language/try-catch.md index c28236c5..73d4da2f 100644 --- a/doc/src/language/try-catch.md +++ b/doc/src/language/try-catch.md @@ -91,7 +91,7 @@ Many script-oriented exceptions can be caught via `try` ... `catch`: | [Array]/[string] indexing out-of-bounds | error message [string] | | Indexing with an inappropriate data type | error message [string] | | Error in a dot expression | error message [string] | -| `for` statement without an type iterator | error message [string] | +| `for` statement without a [type iterator] | error message [string] | | Error in an `in` expression | error message [string] | | Data race detected | error message [string] | diff --git a/doc/src/links.md b/doc/src/links.md index a63f1b26..115c8890 100644 --- a/doc/src/links.md +++ b/doc/src/links.md @@ -57,6 +57,8 @@ [custom types]: {{rootUrl}}/rust/custom.md [getters/setters]: {{rootUrl}}/rust/getters-setters.md [indexers]: {{rootUrl}}/rust/indexers.md +[type iterator]: {{rootUrl}}/language/iterator.md +[type iterators]: {{rootUrl}}/language/iterator.md [`instant::Instant`]: https://crates.io/crates/instant diff --git a/doc/src/plugins/module.md b/doc/src/plugins/module.md index a1e2a684..ac0c9f80 100644 --- a/doc/src/plugins/module.md +++ b/doc/src/plugins/module.md @@ -162,7 +162,7 @@ x == 43; ``` All functions (usually _methods_) defined in the module and marked with `#[rhai_fn(global)]`, -as well as all _type iterators_, are automatically exposed to the _global_ namespace, so +as well as all [type iterators], are automatically exposed to the _global_ namespace, so [iteration]({{rootUrl}}/language/for.md), [getters/setters] and [indexers] for [custom types] can work as expected. diff --git a/doc/src/rust/modules/create.md b/doc/src/rust/modules/create.md index 6e1a1479..4c279800 100644 --- a/doc/src/rust/modules/create.md +++ b/doc/src/rust/modules/create.md @@ -75,7 +75,7 @@ engine.eval::("calc::inc(41)")? == 42; // refer to the 'Calc' module `Module::set_fn_XXX_mut` can expose functions (usually _methods_) in the module to the _global_ namespace, so [getters/setters] and [indexers] for [custom types] can work as expected. -Type iterators, because of their special nature, are always exposed to the _global_ namespace. +[Type iterators], because of their special nature, are always exposed to the _global_ namespace. ```rust use rhai::{Engine, Module, FnNamespace}; diff --git a/doc/src/rust/modules/index.md b/doc/src/rust/modules/index.md index 14931c3a..dd8c928a 100644 --- a/doc/src/rust/modules/index.md +++ b/doc/src/rust/modules/index.md @@ -6,7 +6,7 @@ Modules Rhai allows organizing code (functions, both Rust-based or script-based, and variables) into _modules_. Modules can be disabled via the [`no_module`] feature. -A module is of the type `Module` and holds a collection of functions, variables, type iterators and sub-modules. +A module is of the type `Module` and holds a collection of functions, variables, [type iterators] and sub-modules. It may be created entirely from Rust functions, or it may encapsulate a Rhai script together with the functions and variables defined by that script. diff --git a/doc/src/start/install.md b/doc/src/start/install.md index a7dc944f..007f6d63 100644 --- a/doc/src/start/install.md +++ b/doc/src/start/install.md @@ -21,7 +21,8 @@ rhai = "*" ``` Crate versions are released on [`crates.io`](https:/crates.io/crates/rhai/) infrequently, -so to track the latest features, enhancements and bug fixes, pull directly from GitHub: +so to track the latest features, enhancements and bug fixes, pull directly from +[GitHub](https://github.com/jonathandturner/rhai): ```toml [dependencies] diff --git a/src/engine_api.rs b/src/engine_api.rs index 118c4dcc..fe6a9a48 100644 --- a/src/engine_api.rs +++ b/src/engine_api.rs @@ -158,13 +158,13 @@ impl Engine { self.type_names.insert(type_name::().into(), name.into()); self } - /// Register an iterator adapter for an iterable type with the [`Engine`]. + /// Register an type iterator for an iterable type with the [`Engine`]. /// This is an advanced feature. #[inline(always)] pub fn register_iterator(&mut self) -> &mut Self where - T: Variant + Clone + Iterator, - ::Item: Variant + Clone, + T: Variant + Clone + IntoIterator, + ::Item: Variant + Clone, { self.global_namespace.set_iterable::(); self