From e6667a3996ab70e8b82ddd5844cd953e1184a0d5 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 12 Oct 2020 23:17:22 +0800 Subject: [PATCH] Revise docs. --- RELEASES.md | 7 +++++-- doc/src/about/features.md | 9 +++++---- doc/src/about/non-design.md | 8 ++++---- doc/src/engine/var.md | 28 ++++++++++++++++++++++++---- doc/src/language/arrays.md | 2 +- doc/src/patterns/dynamic-const.md | 4 ++-- doc/src/rust/print-custom.md | 2 +- doc/src/rust/register-raw.md | 8 ++++---- 8 files changed, 46 insertions(+), 22 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index c7ce117c..c3762002 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4,6 +4,8 @@ Rhai Release Notes Version 0.20.0 ============== +This version adds a variable resolver with the ability to short-circuit variable access. + Breaking changes ---------------- @@ -17,6 +19,7 @@ Breaking changes * `rhai::ser` and `rhai::de` namespaces are merged into `rhai::serde`. * New reserved symbols: `++`, `--`, `..`, `...`. * Callback signature for custom syntax implementation function is changed to allow for more flexibility. +* Default call stack depth for `debug` builds is reduced to 12 (from 16). New features ------------ @@ -24,15 +27,15 @@ New features * New `Engine::on_var` to register a _variable resolver_. * `const` statements can now take any expression (or none at all) instead of only constant values. * `OptimizationLevel::Simple` now eagerly evaluates built-in binary operators of primary types (if not overloaded). -* Added `is_def_var()` to detect if variable is defined, and `is_def_fn()` to detect if script function is defined. +* `is_def_var()` to detect if variable is defined, and `is_def_fn()` to detect if script function is defined. * `Dynamic::from(&str)` now constructs a `Dynamic` with a copy of the string as value. * `AST::combine` and `AST::combine_filtered` allows combining two `AST`'s without creating a new one. +* `map`, `filter` and `reduce` functions for arrays. Enhancements ------------ * Many one-liners and few-liners are now marked `#[inline]` or `[inline(always)]`, just in case it helps when LTO is not turned on. -* Default call stack depth for `debug` builds is reduced to 12 (from 16). Version 0.19.0 diff --git a/doc/src/about/features.md b/doc/src/about/features.md index 2cef773b..84a9e233 100644 --- a/doc/src/about/features.md +++ b/doc/src/about/features.md @@ -17,6 +17,8 @@ Easy * Very few additional dependencies - right now only [`smallvec`](https://crates.io/crates/smallvec/) plus crates for procedural macros; for [`no-std`] and `WASM` builds, a number of additional dependencies are pulled in to provide for missing functionalities. +* [Plugins] system powered by procedural macros simplifies custom API development. + Fast ---- @@ -41,6 +43,8 @@ Dynamic * Some support for [object-oriented programming (OOP)][OOP]. +* Hook into variables access via [variable resolver]. + Safe ---- @@ -66,9 +70,6 @@ Flexible * Supports [most build targets](targets.md) including `no-std` and [WASM]. -* [Plugins] system powered by procedural macros simplifies custom API development. - * Surgically [disable keywords and operators] to restrict the language. -* Use as a [DSL] by [disabling keywords/operators][disable keywords and operators], [custom operators] - and extending the language with [custom syntax]. +* Use as a [DSL] by defining [custom operators] and/or extending the language with [custom syntax]. diff --git a/doc/src/about/non-design.md b/doc/src/about/non-design.md index 720a7c12..897efbfa 100644 --- a/doc/src/about/non-design.md +++ b/doc/src/about/non-design.md @@ -10,7 +10,7 @@ It doesn't attempt to be a new language. For example: * No traits... so it is also not Rust. Do your Rusty stuff in Rust. -* No structures/records - define your types in Rust instead; Rhai can seamlessly work with _any Rust type_. +* No structures/records/tuples - define your types in Rust instead; Rhai can seamlessly work with _any Rust type_. There is, however, a built-in [object map] type which is adequate for most uses. It is possible to simulate [object-oriented programming (OOP)][OOP] by storing [function pointers] @@ -32,7 +32,7 @@ It doesn't attempt to be a new language. For example: integrate with native Rust applications. * No formal language grammar - Rhai uses a hand-coded lexer, a hand-coded top-down recursive-descent parser - for statements and a Pratt parser for expressions. + 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], @@ -43,8 +43,8 @@ Do Not Write The Next 4D VR Game in Rhai --------------------------------------- Due to this intended usage, Rhai deliberately keeps the language simple and small by omitting -advanced language features such as classes, inheritance, first-class functions, closures, -concurrency, byte-codes VM, JIT etc. +advanced language features such as classes, inheritance, interfaces, generics, +first-class functions/closures, pattern matching, concurrency, byte-codes VM, JIT etc. Avoid the temptation to write full-fledge application logic entirely in Rhai - that use case is best fulfilled by more complete languages such as JavaScript or Lua. diff --git a/doc/src/engine/var.md b/doc/src/engine/var.md index bcd75069..a6cc0cf3 100644 --- a/doc/src/engine/var.md +++ b/doc/src/engine/var.md @@ -10,7 +10,7 @@ searches the [`Scope`] that is passed into the `Engine::eval` call. There is a built-in facility for advanced users to _hook_ into the variable resolution service and to override its default behavior. -To do so, provide a closure to the [`Engine`] via the [`Engine::on_var`] method: +To do so, provide a closure to the [`Engine`] via the `Engine::on_var` method: ```rust let mut engine = Engine::new(); @@ -45,6 +45,18 @@ a variable resolver. Then these variables can be assigned to and their updated v the script is evaluated. +Benefits of Using a Variable Resolver +------------------------------------ + +1. Avoid having to maintain a custom [`Scope`] with all variables regardless of need (because a script may not use them all). + +2. _Short-circuit_ variable access, essentially overriding standard behavior. + +3. _Lazy-load_ variables when they are accessed, not up-front. This benefits when the number of variables is very large, when they are timing-dependent, or when they are expensive to load. + +4. Rename system variables on a script-by-script basis without having to construct different [`Scope`]'s. + + Function Signature ------------------ @@ -61,12 +73,20 @@ where: If `index` is zero, then there is no pre-calculated offset position and a search through the current [`Scope`] must be performed. -* `scope : &Scope` - reference to the current [`Scope`] containing all variables up to the current evaluation position. +* `scope: &Scope` - reference to the current [`Scope`] containing all variables up to the current evaluation position. * `context: &EvalContext` - reference to the current evaluation _context_, which exposes the following fields: * `context.engine(): &Engine` - reference to the current [`Engine`]. * `context.namespace(): &Module` - reference to the current _global namespace_ (as a [module]) containing all script-defined functions. * `context.call_level(): usize` - the current nesting level of function calls. -The return value is `Result, Box>` where `Ok(None)` indicates that the normal -variable resolution process should continue. +### Return Value + +The return value is `Result, Box>` where: + +* `Ok(None)` - normal variable resolution process should continue, meaning to continue searching through the [`Scope`]. + +* `Ok(Some(Dynamic))` - wrapped [`Dynamic`] is taken as the value of the variable, which is treated as a constant. + +* `Err(Box)` - error is reflected back to the [`Engine`]. + Normally this is `EvalAltResult::ErrorVariableNotFound` to indicate that the variable does not exist, but it can be any error. diff --git a/doc/src/language/arrays.md b/doc/src/language/arrays.md index ed3ca97c..5fc3c4fc 100644 --- a/doc/src/language/arrays.md +++ b/doc/src/language/arrays.md @@ -40,7 +40,7 @@ The following methods (mostly defined in the [`BasicArrayPackage`][packages] but | `insert` | 1) element to insert
2) position (beginning if <= 0, end if >= length) | inserts an element at a certain index | | `pop` | _none_ | removes the last element and returns it ([`()`] if empty) | | `shift` | _none_ | removes the first element and returns it ([`()`] if empty) | -| `remove` | index | removes an element at a particular index and returns it, or returns [`()`] if the index is not valid | +| `remove` | index | removes an element at a particular index and returns it ([`()`] if the index is not valid) | | `reverse` | _none_ | reverses the array | | `len` method and property | _none_ | returns the number of elements | | `pad` | 1) target length
2) element to pad | pads the array with an element to at least a specified length | diff --git a/doc/src/patterns/dynamic-const.md b/doc/src/patterns/dynamic-const.md index b370e099..e3fe7c06 100644 --- a/doc/src/patterns/dynamic-const.md +++ b/doc/src/patterns/dynamic-const.md @@ -35,8 +35,8 @@ Implementation let mut engine = Engine::new(); // Create shared data provider. -// Assume that Provider::get(&str) -> Option gets a system constant. -let provider: Arc = get_data_provider(); +// Assume that SystemValuesProvider::get(&str) -> Option gets a value. +let provider = Arc::new(SystemValuesProvider::new()); // Clone the shared provider let db = provider.clone(); diff --git a/doc/src/rust/print-custom.md b/doc/src/rust/print-custom.md index 2ea6f1e8..028a3519 100644 --- a/doc/src/rust/print-custom.md +++ b/doc/src/rust/print-custom.md @@ -5,7 +5,7 @@ Printing for Custom Types 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`): +is `T: Display + Debug`): | Function | Signature | Typical implementation | Usage | | ----------- | ---------------------------------------------- | ---------------------------- | -------------------------------------------------------------------- | diff --git a/doc/src/rust/register-raw.md b/doc/src/rust/register-raw.md index 2897138f..2231320e 100644 --- a/doc/src/rust/register-raw.md +++ b/doc/src/rust/register-raw.md @@ -63,14 +63,14 @@ The function signature passed to `Engine::register_raw_fn` takes the following f where: -* `T : Variant + Clone` - return type of the function. +* `T: Variant + Clone` - return type of the function. -* `engine : &Engine` - the current [`Engine`], with all configurations and settings. +* `engine: &Engine` - the current [`Engine`], with all configurations and settings. -* `lib : &Module` - the current global library of script-defined functions, as a [`Module`]. +* `lib: &Module` - the current global library of script-defined functions, as a [`Module`]. This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`]. -* `args : &mut [&mut Dynamic]` - a slice containing `&mut` references to [`Dynamic`] values. +* `args: &mut [&mut Dynamic]` - a slice containing `&mut` references to [`Dynamic`] values. The slice is guaranteed to contain enough arguments _of the correct types_. Remember, in Rhai, all arguments _except_ the _first_ one are always passed by _value_ (i.e. cloned).