From 5c02dc49d12709e7c00023492cacc19e2cf62add Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 25 Jul 2020 16:22:20 +0800 Subject: [PATCH 1/7] Delete benchmark.yml --- .github/workflows/benchmark.yml | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 .github/workflows/benchmark.yml diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml deleted file mode 100644 index df310705..00000000 --- a/.github/workflows/benchmark.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Benchmark -on: - push: - branches: - - master - -jobs: - benchmark: - name: Run Rust benchmark - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - run: rustup toolchain update nightly && rustup default nightly - - name: Run benchmark - run: cargo +nightly bench | tee output.txt - - name: Store benchmark result - uses: rhysd/github-action-benchmark@v1 - with: - name: Rust Benchmark - tool: 'cargo' - output-file-path: output.txt - # Use personal access token instead of GITHUB_TOKEN due to https://github.community/t5/GitHub-Actions/Github-action-not-triggering-gh-pages-upon-push/td-p/26869/highlight/false - github-token: ${{ secrets.RHAI }} - auto-push: true - # Show alert with commit comment on detecting possible performance regression - alert-threshold: '200%' - comment-on-alert: true - fail-on-alert: true - alert-comment-cc-users: '@schungx' From c530792d00ebbe93ca9d7cdff63895feb63c3f2e Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 25 Jul 2020 16:36:50 +0800 Subject: [PATCH 2/7] Add repoTree and repoHome macros. --- doc/src/SUMMARY.md | 17 ++++++----- doc/src/about/license.md | 15 ++++++++++ doc/src/context.json | 2 ++ doc/src/start/examples/rust.md | 28 ++++++++--------- doc/src/start/examples/scripts.md | 50 +++++++++++++++---------------- no_std/no_std_test/Cargo.toml | 2 +- 6 files changed, 66 insertions(+), 48 deletions(-) create mode 100644 doc/src/about/license.md diff --git a/doc/src/SUMMARY.md b/doc/src/SUMMARY.md index 4e41d940..b1e5a561 100644 --- a/doc/src/SUMMARY.md +++ b/doc/src/SUMMARY.md @@ -5,8 +5,9 @@ The Rhai Scripting Language 1. [Features](about/features.md) 2. [Supported Targets and Builds](about/targets.md) 3. [What Rhai Isn't](about/non-design.md) - 4. [Related Resources](about/related.md) -3. [Getting Started](start/index.md) + 4. [Licensing](about/license.md) + 5. [Related Resources](about/related.md) +2. [Getting Started](start/index.md) 1. [Online Playground](start/playground.md) 2. [Install the Rhai Crate](start/install.md) 3. [Optional Features](start/features.md) @@ -18,14 +19,14 @@ The Rhai Scripting Language 5. [Examples](start/examples/index.md) 1. [Rust](start/examples/rust.md) 2. [Scripts](start/examples/scripts.md) -4. [Using the `Engine`](engine/index.md) +3. [Using the `Engine`](engine/index.md) 1. [Hello World in Rhai - Evaluate a Script](engine/hello-world.md) 2. [Compile a Script to AST for Repeated Evaluations](engine/compile.md) 3. [Call a Rhai Function from Rust](engine/call-fn.md) 4. [Create a Rust Anonymous Function from a Rhai Function](engine/func.md) 5. [Evaluate Expressions Only](engine/expressions.md) 6. [Raw Engine](engine/raw.md) -5. [Extend Rhai with Rust](rust/index.md) +4. [Extend Rhai with Rust](rust/index.md) 1. [Traits](rust/traits.md) 2. [Register a Rust Function](rust/functions.md) 1. [String Parameters in Rust Functions](rust/strings.md) @@ -43,7 +44,7 @@ The Rhai Scripting Language 4. [Printing Custom Types](rust/print-custom.md) 9. [Scope - Initializing and Maintaining State](rust/scope.md) 10. [Engine Configuration Options](rust/options.md) -6. [Rhai Language Reference](language/index.md) +5. [Rhai Language Reference](language/index.md) 1. [Comments](language/comments.md) 2. [Values and Types](language/values-and-types.md) 1. [Dynamic Values](language/dynamic.md) @@ -85,7 +86,7 @@ The Rhai Scripting Language 4. [Create from AST](language/modules/ast.md) 5. [Module Resolvers](rust/modules/resolvers.md) 1. [Custom Implementation](rust/modules/imp-resolver.md) -7. [Safety and Protection](safety/index.md) +6. [Safety and Protection](safety/index.md) 1. [Checked Arithmetic](safety/checked.md) 2. [Sand-Boxing](safety/sandbox.md) 3. [Maximum Length of Strings](safety/max-string-size.md) @@ -96,7 +97,7 @@ The Rhai Scripting Language 7. [Maximum Number of Modules](safety/max-modules.md) 8. [Maximum Call Stack Depth](safety/max-call-stack.md) 9. [Maximum Statement Depth](safety/max-stmt-depth.md) -8. [Advanced Topics](advanced.md) +7. [Advanced Topics](advanced.md) 1. [Object-Oriented Programming (OOP)](language/oop.md) 2. [Serialization/Deserialization of `Dynamic` with `serde`](rust/serde.md) 3. [Script Optimization](engine/optimize/index.md) @@ -112,7 +113,7 @@ The Rhai Scripting Language 2. [Custom Operators](engine/custom-op.md) 3. [Extending with Custom Syntax](engine/custom-syntax.md) 6. [Eval Statement](language/eval.md) -9. [Appendix](appendix/index.md) +8. [Appendix](appendix/index.md) 1. [Keywords](appendix/keywords.md) 2. [Operators and Symbols](appendix/operators.md) 3. [Literals](appendix/literals.md) diff --git a/doc/src/about/license.md b/doc/src/about/license.md new file mode 100644 index 00000000..a60ac1eb --- /dev/null +++ b/doc/src/about/license.md @@ -0,0 +1,15 @@ +Licensing +========= + +{{#include ../links.md}} + +Rhai is licensed under either: + +* [Apache License, Version 2.0]({{repoHome}}/LICENSE-APACHE.txt), or +* [MIT license]({{repoHome}}/LICENSE-MIT.txt) + +at your option. + +Unless explicitly stated otherwise, any contribution intentionally submitted for inclusion in this crate, +as defined in the Apache-2.0 license, shall be dual-licensed as above, +without any additional terms or conditions. diff --git a/doc/src/context.json b/doc/src/context.json index 025c159b..16f803db 100644 --- a/doc/src/context.json +++ b/doc/src/context.json @@ -1,5 +1,7 @@ { "version": "0.18.0", + "repoHome": "https://github.com/jonathandturner/rhai/blob/master", + "repoTree": "https://github.com/jonathandturner/rhai/tree/master", "rootUrl": "", "rootUrlX": "/rhai", "rootUrlXX": "/rhai/vnext" diff --git a/doc/src/start/examples/rust.md b/doc/src/start/examples/rust.md index 276b3d15..157cffed 100644 --- a/doc/src/start/examples/rust.md +++ b/doc/src/start/examples/rust.md @@ -5,17 +5,17 @@ Rust Examples A number of examples can be found in the `examples` directory: -| Example | Description | -| ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| [`arrays_and_structs`](https://github.com/jonathandturner/rhai/tree/master/examples/arrays_and_structs.rs) | Shows how to register a custom Rust type and using [arrays] on it. | -| [`custom_types_and_methods`](https://github.com/jonathandturner/rhai/tree/master/examples/custom_types_and_methods.rs) | Shows how to register a custom Rust type and methods for it. | -| [`hello`](https://github.com/jonathandturner/rhai/tree/master/examples/hello.rs) | Simple example that evaluates an expression and prints the result. | -| [`reuse_scope`](https://github.com/jonathandturner/rhai/tree/master/examples/reuse_scope.rs) | Evaluates two pieces of code in separate runs, but using a common [`Scope`]. | -| [`rhai_runner`](https://github.com/jonathandturner/rhai/tree/master/examples/rhai_runner.rs) | Runs each filename passed to it as a Rhai script. | -| [`serde`](https://github.com/jonathandturner/rhai/tree/master/examples/serde.rs) | Example to serialize and deserialize Rust types with [`serde`](https://crates.io/crates/serde).
The [`serde`] feature is required to run. | -| [`simple_fn`](https://github.com/jonathandturner/rhai/tree/master/examples/simple_fn.rs) | Shows how to register a simple function. | -| [`strings`](https://github.com/jonathandturner/rhai/tree/master/examples/strings.rs) | Shows different ways to register functions taking string arguments. | -| [`repl`](https://github.com/jonathandturner/rhai/tree/master/examples/repl.rs) | A simple REPL, interactively evaluate statements from stdin. | +| Example | Description | +| ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| [`arrays_and_structs`]({{repoTree}}/examples/arrays_and_structs.rs) | Shows how to register a custom Rust type and using [arrays] on it. | +| [`custom_types_and_methods`]({{repoTree}}/examples/custom_types_and_methods.rs) | Shows how to register a custom Rust type and methods for it. | +| [`hello`]({{repoTree}}/examples/hello.rs) | Simple example that evaluates an expression and prints the result. | +| [`reuse_scope`]({{repoTree}}/examples/reuse_scope.rs) | Evaluates two pieces of code in separate runs, but using a common [`Scope`]. | +| [`rhai_runner`]({{repoTree}}/examples/rhai_runner.rs) | Runs each filename passed to it as a Rhai script. | +| [`serde`]({{repoTree}}/examples/serde.rs) | Example to serialize and deserialize Rust types with [`serde`](https://crates.io/crates/serde).
The [`serde`] feature is required to run. | +| [`simple_fn`]({{repoTree}}/examples/simple_fn.rs) | Shows how to register a simple function. | +| [`strings`]({{repoTree}}/examples/strings.rs) | Shows different ways to register functions taking string arguments. | +| [`repl`]({{repoTree}}/examples/repl.rs) | A simple REPL, interactively evaluate statements from stdin. | The `repl` example is a particularly good one as it allows one to interactively try out Rhai's language features in a standard REPL (**R**ead-**E**val-**P**rint **L**oop). @@ -35,9 +35,9 @@ cargo run --example {example_name} To illustrate `no-std` builds, a number of sample applications are available under the `no_std` directory: -| Sample | Description | Optimization | Allocator | Panics | -| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | :----------: | :-----------------------------------------------: | :----: | -| [`no_std_test`](https://github.com/jonathandturner/rhai/tree/master/no_std/no_std_test) | Bare-bones test application that evaluates a Rhai expression and sets the result as the return value. | Size | [`wee_alloc`](https://crates.io/crates/wee_alloc) | Abort | +| Sample | Description | Optimization | Allocator | Panics | +| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | :----------: | :-----------------------------------------------: | :----: | +| [`no_std_test`]({{repoTree}}/no_std/no_std_test) | Bare-bones test application that evaluates a Rhai expression and sets the result as the return value. | Size | [`wee_alloc`](https://crates.io/crates/wee_alloc) | Abort | `cargo run` cannot be used to run a `no-std` sample. It must first be built: diff --git a/doc/src/start/examples/scripts.md b/doc/src/start/examples/scripts.md index 0875f869..57c38d13 100644 --- a/doc/src/start/examples/scripts.md +++ b/doc/src/start/examples/scripts.md @@ -8,25 +8,25 @@ Language Feature Scripts There are also a number of examples scripts that showcase Rhai's features, all in the `scripts` directory: -| Script | Description | -| -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -| [`array.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/array.rhai) | [Arrays] | -| [`assignment.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/assignment.rhai) | Variable declarations | -| [`comments.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/comments.rhai) | Just comments | -| [`for1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/for1.rhai) | [`for`]({{rootUrl}}/language/for.md) loops | -| [`for2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/for2.rhai) | [`for`]({{rootUrl}}/language/for.md) loops on [arrays] | -| [`function_decl1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl1.rhai) | A [function] without parameters | -| [`function_decl2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl2.rhai) | A [function] with two parameters | -| [`function_decl3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/function_decl3.rhai) | A [function] with many parameters | -| [`if1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/if1.rhai) | [`if`]({{rootUrl}}/language/if.md) example | -| [`loop.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/loop.rhai) | Count-down [`loop`]({{rootUrl}}/language/loop.md) in Rhai, emulating a `do` .. `while` loop | -| [`oop.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/oop.rhai) | Simulate [object-oriented programming (OOP)][OOP] | -| [`op1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op1.rhai) | Just simple addition | -| [`op2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op2.rhai) | Simple addition and multiplication | -| [`op3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op3.rhai) | Change evaluation order with parenthesis | -| [`string.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/string.rhai) | [String] operations | -| [`strings_map.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/strings_map.rhai) | [String] and [object map] operations | -| [`while.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/while.rhai) | [`while`]({{rootUrl}}/language/while.md) loop | +| Script | Description | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| [`array.rhai`]({{repoTree}}/scripts/array.rhai) | [Arrays] | +| [`assignment.rhai`]({{repoTree}}/scripts/assignment.rhai) | Variable declarations | +| [`comments.rhai`]({{repoTree}}/scripts/comments.rhai) | Just comments | +| [`for1.rhai`]({{repoTree}}/scripts/for1.rhai) | [`for`]({{rootUrl}}/language/for.md) loops | +| [`for2.rhai`]({{repoTree}}/scripts/for2.rhai) | [`for`]({{rootUrl}}/language/for.md) loops on [arrays] | +| [`function_decl1.rhai`]({{repoTree}}/scripts/function_decl1.rhai) | A [function] without parameters | +| [`function_decl2.rhai`]({{repoTree}}/scripts/function_decl2.rhai) | A [function] with two parameters | +| [`function_decl3.rhai`]({{repoTree}}/scripts/function_decl3.rhai) | A [function] with many parameters | +| [`if1.rhai`]({{repoTree}}/scripts/if1.rhai) | [`if`]({{rootUrl}}/language/if.md) example | +| [`loop.rhai`]({{repoTree}}/scripts/loop.rhai) | Count-down [`loop`]({{rootUrl}}/language/loop.md) in Rhai, emulating a `do` .. `while` loop | +| [`oop.rhai`]({{repoTree}}/scripts/oop.rhai) | Simulate [object-oriented programming (OOP)][OOP] | +| [`op1.rhai`]({{repoTree}}/scripts/op1.rhai) | Just simple addition | +| [`op2.rhai`]({{repoTree}}/scripts/op2.rhai) | Simple addition and multiplication | +| [`op3.rhai`]({{repoTree}}/scripts/op3.rhai) | Change evaluation order with parenthesis | +| [`string.rhai`]({{repoTree}}/scripts/string.rhai) | [String] operations | +| [`strings_map.rhai`]({{repoTree}}/scripts/strings_map.rhai) | [String] and [object map] operations | +| [`while.rhai`]({{repoTree}}/scripts/while.rhai) | [`while`]({{rootUrl}}/language/while.md) loop | Benchmark Scripts @@ -34,12 +34,12 @@ Benchmark Scripts The following scripts are for benchmarking the speed of Rhai: -| Scripts | Description | -| ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | -| [`speed_test.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/speed_test.rhai) | A simple application to measure the speed of Rhai's interpreter (1 million iterations). | -| [`primes.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/primes.rhai) | Use Sieve of Eratosthenes to find all primes smaller than a limit. | -| [`fibonacci.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/fibonacci.rhai) | Calculate the n-th Fibonacci number using a really dumb algorithm. | -| [`mat_mul.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/mat_mul.rhai) | Matrix multiplication test to measure the speed of multi-dimensional array access. | +| Scripts | Description | +| --------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| [`speed_test.rhai`]({{repoTree}}/scripts/speed_test.rhai) | A simple application to measure the speed of Rhai's interpreter (1 million iterations). | +| [`primes.rhai`]({{repoTree}}/scripts/primes.rhai) | Use Sieve of Eratosthenes to find all primes smaller than a limit. | +| [`fibonacci.rhai`]({{repoTree}}/scripts/fibonacci.rhai) | Calculate the n-th Fibonacci number using a really dumb algorithm. | +| [`mat_mul.rhai`]({{repoTree}}/scripts/mat_mul.rhai) | Matrix multiplication test to measure the speed of multi-dimensional array access. | Running Example Scripts diff --git a/no_std/no_std_test/Cargo.toml b/no_std/no_std_test/Cargo.toml index 4b151047..6e26639b 100644 --- a/no_std/no_std_test/Cargo.toml +++ b/no_std/no_std_test/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2018" authors = ["Stephen Chung"] description = "no-std test application" -homepage = "https://github.com/jonathandturner/rhai/tree/master/no_std/no_std_test" +homepage = "https://github.com/jonathandturner/rhai/tree/no_std/no_std_test" repository = "https://github.com/jonathandturner/rhai" [dependencies] From 90ff503ddc71fd0e223c35c23f5f091cb6054794 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sat, 25 Jul 2020 10:02:06 +0200 Subject: [PATCH 3/7] Replace Travis and build with GitHub Actions --- .ci/build.sh | 11 ------ .github/workflows/build.yml | 74 +++++++++++++++++++++++++++++++++++++ .travis.yml | 10 ----- README.md | 2 +- 4 files changed, 75 insertions(+), 22 deletions(-) delete mode 100755 .ci/build.sh create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml diff --git a/.ci/build.sh b/.ci/build.sh deleted file mode 100755 index fb0e7e04..00000000 --- a/.ci/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -ex - -cargo build --verbose -cargo test --verbose - -if [[ $TRAVIS_RUST_VERSION == "nightly" ]]; then - cargo build --verbose --features no_std - cargo test --verbose --features no_std -fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..95466e13 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,74 @@ +name: Build + +on: + push: + branches: + - master + pull_request: {} + +jobs: + # typical build with various feature combinations + build: + name: Build + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.experimental }} + strategy: + matrix: + os: [ubuntu-latest] + flags: + - "" + - "--features serde" + - "--features plugins" + - "--features unchecked" + - "--features sync" + - "--features no_optimize" + - "--features no_float" + - "--features only_i32" + - "--features only_i64" + - "--features no_index" + - "--features no_object" + - "--features no_function" + - "--features no_module" + toolchain: [stable] + experimental: [false] + include: + # smoketests for future and experimental toolchains + - {toolchain: stable, os: windows-latest, experimental: false, flags: ""} + - {toolchain: stable, os: macos-latest, experimental: false, flags: ""} + - {toolchain: beta, os: ubuntu-latest, experimental: false, flags: ""} + - {toolchain: nightly, os: ubuntu-latest, experimental: true, flags: ""} + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{matrix.toolchain}} + override: true + - name: Test + uses: actions-rs/cargo@v1 + with: + command: test + args: --all {{matrix.flags}} + # no-std builds are a bit more extensive to test + no_std_build: + name: NoStdBuild + runs-on: ${{matrix.os}} + # TODO: remove once build works. + continue-on-error: true + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + - name: Build Project + uses: actions-rs/cargo@v1 + with: + command: build + args: --manifest-path=no_std/no_std_test/Cargo.toml \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 80702bdc..00000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: rust -rust: - - stable - - beta - - nightly -matrix: - allow_failures: - - rust: nightly - -script: bash ./.ci/build.sh \ No newline at end of file diff --git a/README.md b/README.md index b40d97a8..8a18b278 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Rhai - Embedded Scripting for Rust ================================= ![GitHub last commit](https://img.shields.io/github/last-commit/jonathandturner/rhai) -[![Travis (.org)](https://img.shields.io/travis/jonathandturner/rhai)](http://travis-ci.org/jonathandturner/rhai) +[![Build Status](https://github.com/jonathandturner/rhai/workflows/Build/badge.svg)](https://github.com/jonathandturner/rhai/actions) [![license](https://img.shields.io/github/license/jonathandturner/rhai)](https://github.com/license/jonathandturner/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/) From f601cc8c0a2d13e11fe0070dbc22f6c4b23c89ec Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 25 Jul 2020 16:51:29 +0800 Subject: [PATCH 4/7] Restore benchmark.yml. --- .github/workflows/benchmark.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/benchmark.yml diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 00000000..df310705 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,29 @@ +name: Benchmark +on: + push: + branches: + - master + +jobs: + benchmark: + name: Run Rust benchmark + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - run: rustup toolchain update nightly && rustup default nightly + - name: Run benchmark + run: cargo +nightly bench | tee output.txt + - name: Store benchmark result + uses: rhysd/github-action-benchmark@v1 + with: + name: Rust Benchmark + tool: 'cargo' + output-file-path: output.txt + # Use personal access token instead of GITHUB_TOKEN due to https://github.community/t5/GitHub-Actions/Github-action-not-triggering-gh-pages-upon-push/td-p/26869/highlight/false + github-token: ${{ secrets.RHAI }} + auto-push: true + # Show alert with commit comment on detecting possible performance regression + alert-threshold: '200%' + comment-on-alert: true + fail-on-alert: true + alert-comment-cc-users: '@schungx' From 66700b4a53538c064fe613ae8ed5ce627c0ee97b Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sat, 25 Jul 2020 10:48:29 +0200 Subject: [PATCH 5/7] Fix building no_std on Linux and Windows --- .github/workflows/build.yml | 10 ++++++---- no_std/no_std_test/Cargo.toml | 14 +++++++++++++- no_std/no_std_test/README.md | 4 +++- no_std/no_std_test/src/main.rs | 8 +++++++- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 95466e13..49318e1c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,11 +54,13 @@ jobs: no_std_build: name: NoStdBuild runs-on: ${{matrix.os}} - # TODO: remove once build works. - continue-on-error: true + continue-on-error: ${{matrix.experimental}} strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + include: + - {os: ubuntu-latest, flags: "--profile unix -Z unstable-options", experimental: false} + - {os: windows-latest, flags: "--profile windows -Z unstable-options", experimental: true} + - {os: macos-latest, flags: "--profile macos -Z unstable-options", experimental: false} steps: - name: Checkout uses: actions/checkout@v2 @@ -71,4 +73,4 @@ jobs: uses: actions-rs/cargo@v1 with: command: build - args: --manifest-path=no_std/no_std_test/Cargo.toml \ No newline at end of file + args: --manifest-path=no_std/no_std_test/Cargo.toml ${{matrix.flags}} diff --git a/no_std/no_std_test/Cargo.toml b/no_std/no_std_test/Cargo.toml index 4b151047..89a15bbb 100644 --- a/no_std/no_std_test/Cargo.toml +++ b/no_std/no_std_test/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["named-profiles"] + [package] name = "no_std_test" version = "0.1.0" @@ -18,7 +20,17 @@ panic = "abort" opt-level = "z" # optimize for size debug = false rpath = false -lto = "fat" debug-assertions = false codegen-units = 1 panic = "abort" + +[profile.unix] +inherits = "release" +lto = true + +[profile.windows] +inherits = "release" + +[profile.macos] +inherits = "release" +lto = "fat" diff --git a/no_std/no_std_test/README.md b/no_std/no_std_test/README.md index e7edfc51..0a12e48b 100644 --- a/no_std/no_std_test/README.md +++ b/no_std/no_std_test/README.md @@ -12,7 +12,9 @@ To Compile The nightly compiler is required: ```bash -cargo +nightly build --release +cargo +nightly build --release --profile unix -Z unstable-features ``` +Available profiles are: `unix`, `windows` and `macos`. + The release build is optimized for size. It can be changed to optimize on speed instead. diff --git a/no_std/no_std_test/src/main.rs b/no_std/no_std_test/src/main.rs index 829802f8..3db95447 100644 --- a/no_std/no_std_test/src/main.rs +++ b/no_std/no_std_test/src/main.rs @@ -2,7 +2,7 @@ //! a simple expression and uses the result as the return value. #![no_std] -#![feature(alloc_error_handler, start, core_intrinsics, lang_items)] +#![feature(alloc_error_handler, start, core_intrinsics, lang_items, link_cfg)] extern crate alloc; extern crate wee_alloc; @@ -10,6 +10,12 @@ extern crate wee_alloc; #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; +// NB: Rust needs a CRT runtime on Windows MSVC. +#[cfg(all(windows, target_env = "msvc"))] +#[link(name = "msvcrt")] +#[link(name = "libcmt")] +extern {} + use rhai::{Engine, INT}; #[start] From 353df6bea152184ad7fc3b3d511b8cee2f410d94 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 26 Jul 2020 10:03:59 +0800 Subject: [PATCH 6/7] Avoid warnings in standard build. --- src/engine.rs | 4 +--- src/fn_call.rs | 18 +++++++++++++++--- src/fn_native.rs | 9 ++++++--- src/packages/arithmetic.rs | 8 +++++++- src/packages/mod.rs | 1 + src/packages/time_basic.rs | 14 ++++++++------ src/syntax.rs | 7 +++++-- 7 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/engine.rs b/src/engine.rs index a852b3fa..b7b73f2a 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -639,9 +639,7 @@ impl Engine { ) .or_else(|err| match *err { // If there is no index setter, no need to set it back because the indexer is read-only - EvalAltResult::ErrorFunctionNotFound(s, _) - if s == FN_IDX_SET => - { + EvalAltResult::ErrorFunctionNotFound(_, _) => { Ok(Default::default()) } _ => Err(err), diff --git a/src/fn_call.rs b/src/fn_call.rs index 616fe2f6..98228853 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -864,10 +864,22 @@ impl Engine { EvalAltResult::ErrorFunctionNotFound(_, _) if def_val.is_some() => { Ok(def_val.unwrap().into()) } - EvalAltResult::ErrorFunctionNotFound(_, _) => { + EvalAltResult::ErrorFunctionNotFound(_, pos) => { Err(Box::new(EvalAltResult::ErrorFunctionNotFound( - format!("{}{}", modules, name), - Position::none(), + format!( + "{}{} ({})", + modules, + name, + args.iter() + .map(|a| if a.is::() { + "&str | ImmutableString | String" + } else { + self.map_type_name((*a).type_name()) + }) + .collect::>() + .join(", ") + ), + pos, ))) } _ => Err(err), diff --git a/src/fn_native.rs b/src/fn_native.rs index 2833729a..8fc60714 100644 --- a/src/fn_native.rs +++ b/src/fn_native.rs @@ -9,9 +9,12 @@ use crate::token::{is_valid_identifier, Position}; use crate::utils::{ImmutableString, StaticVec}; use crate::Scope; -use crate::stdlib::{ - boxed::Box, convert::TryFrom, fmt, mem, rc::Rc, string::String, sync::Arc, vec::Vec, -}; +use crate::stdlib::{boxed::Box, convert::TryFrom, fmt, mem, string::String, vec::Vec}; + +#[cfg(not(feature = "sync"))] +use crate::stdlib::rc::Rc; +#[cfg(feature = "sync")] +use crate::stdlib::sync::Arc; /// Trait that maps to `Send + Sync` only under the `sync` feature. #[cfg(feature = "sync")] diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index 5e43c05b..3e3852d6 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -20,9 +20,12 @@ use crate::stdlib::{ boxed::Box, fmt::Display, format, - ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub}, + ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Sub}, }; +#[cfg(feature = "unchecked")] +use crate::stdlib::ops::{Shl, Shr}; + // Checked add pub(crate) fn add(x: T, y: T) -> FuncReturn { x.checked_add(&y).ok_or_else(|| { @@ -171,10 +174,12 @@ pub(crate) fn shr(x: T, y: INT) -> FuncReturn { }) } // Unchecked left-shift - may panic if shifting by a negative number of bits +#[cfg(feature = "unchecked")] pub(crate) fn shl_u>(x: T, y: T) -> FuncReturn<>::Output> { Ok(x.shl(y)) } // Unchecked right-shift - may panic if shifting by a negative number of bits +#[cfg(feature = "unchecked")] pub(crate) fn shr_u>(x: T, y: T) -> FuncReturn<>::Output> { Ok(x.shr(y)) } @@ -229,6 +234,7 @@ pub(crate) fn pow_i_i(x: INT, y: INT) -> FuncReturn { } } // Unchecked integer power - may panic on overflow or if the power index is too high (> u32::MAX) +#[cfg(feature = "unchecked")] pub(crate) fn pow_i_i_u(x: INT, y: INT) -> FuncReturn { Ok(x.pow(y as u32)) } diff --git a/src/packages/mod.rs b/src/packages/mod.rs index 43ae5f28..8207a966 100644 --- a/src/packages/mod.rs +++ b/src/packages/mod.rs @@ -74,6 +74,7 @@ impl PackagesCollection { .flatten() } /// Does the specified TypeId iterator exist in the `PackagesCollection`? + #[allow(dead_code)] pub fn contains_iter(&self, id: TypeId) -> bool { self.0.iter().any(|p| p.contains_iter(id)) } diff --git a/src/packages/time_basic.rs b/src/packages/time_basic.rs index cbf13f1b..7c166ab1 100644 --- a/src/packages/time_basic.rs +++ b/src/packages/time_basic.rs @@ -1,12 +1,17 @@ #![cfg(not(feature = "no_std"))] use super::logic::{eq, gt, gte, lt, lte, ne}; + +#[cfg(feature = "no_float")] use super::math_basic::MAX_INT; use crate::def_package; -use crate::module::FuncReturn; -use crate::parser::INT; use crate::result::EvalAltResult; -use crate::token::Position; + +#[cfg(not(feature = "no_float"))] +use crate::parser::FLOAT; + +#[cfg(feature = "no_float")] +use crate::{module::FuncReturn, parser::INT, token::Position}; #[cfg(not(target_arch = "wasm32"))] use crate::stdlib::time::Instant; @@ -14,9 +19,6 @@ use crate::stdlib::time::Instant; #[cfg(target_arch = "wasm32")] use instant::Instant; -#[cfg(not(feature = "no_float"))] -use crate::parser::FLOAT; - def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, { // Register date/time functions lib.set_fn_0("timestamp", || Ok(Instant::now())); diff --git a/src/syntax.rs b/src/syntax.rs index 616833c1..9dfc255f 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -14,11 +14,14 @@ use crate::utils::StaticVec; use crate::stdlib::{ boxed::Box, fmt, format, - rc::Rc, string::{String, ToString}, - sync::Arc, }; +#[cfg(not(feature = "sync"))] +use crate::stdlib::rc::Rc; +#[cfg(feature = "sync")] +use crate::stdlib::sync::Arc; + /// A general expression evaluation trait object. #[cfg(not(feature = "sync"))] pub type FnCustomSyntaxEval = dyn Fn( From ba5c4fd0409c3baecf5625f764a9b5cf1c75cab8 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sun, 26 Jul 2020 10:05:47 +0800 Subject: [PATCH 7/7] Improve writeup. --- README.md | 2 +- doc/src/SUMMARY.md | 21 ++++----- doc/src/about/index.md | 5 ++- doc/src/about/license.md | 3 +- doc/src/about/non-design.md | 23 ++++++++-- doc/src/advanced.md | 4 +- doc/src/engine/hello-world.md | 30 ++++++++----- doc/src/engine/raw.md | 9 ++-- doc/src/language/for.md | 3 +- doc/src/language/if.md | 3 ++ doc/src/language/logic.md | 39 ---------------- doc/src/language/method.md | 13 +++--- doc/src/language/other-op.md | 66 ++++++++++++++++++++++++++++ doc/src/rust/custom.md | 4 +- doc/src/rust/functions.md | 6 +-- doc/src/rust/modules/imp-resolver.md | 2 +- doc/src/rust/override.md | 4 +- doc/src/start/builds/performance.md | 4 +- doc/src/start/features.md | 4 +- 19 files changed, 156 insertions(+), 89 deletions(-) create mode 100644 doc/src/language/other-op.md diff --git a/README.md b/README.md index f5431f6e..1516abcc 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Licensed under either: * [Apache License, Version 2.0](https://github.com/jonathandturner/rhai/blob/master/LICENSE-APACHE.txt), or * [MIT license](https://github.com/jonathandturner/rhai/blob/master/LICENSE-MIT.txt) -at your option. +at your choice. Unless explicitly stated otherwise, any contribution intentionally submitted for inclusion in this crate, as defined in the Apache-2.0 license, shall diff --git a/doc/src/SUMMARY.md b/doc/src/SUMMARY.md index b1e5a561..3592dbc5 100644 --- a/doc/src/SUMMARY.md +++ b/doc/src/SUMMARY.md @@ -21,7 +21,7 @@ The Rhai Scripting Language 2. [Scripts](start/examples/scripts.md) 3. [Using the `Engine`](engine/index.md) 1. [Hello World in Rhai - Evaluate a Script](engine/hello-world.md) - 2. [Compile a Script to AST for Repeated Evaluations](engine/compile.md) + 2. [Compile to AST for Repeated Evaluations](engine/compile.md) 3. [Call a Rhai Function from Rust](engine/call-fn.md) 4. [Create a Rust Anonymous Function from a Rhai Function](engine/func.md) 5. [Evaluate Expressions Only](engine/expressions.md) @@ -65,21 +65,22 @@ The Rhai Scripting Language 5. [Variables](language/variables.md) 6. [Constants](language/constants.md) 7. [Logic Operators](language/logic.md) - 8. [If Statement](language/if.md) - 9. [While Loop](language/while.md) - 10. [Loop Statement](language/loop.md) - 11. [For Loop](language/for.md) - 12. [Return Values](language/return.md) - 13. [Throw Exception on Error](language/throw.md) - 14. [Functions](language/functions.md) + 8. [Other Operators](language/other-op.md) + 9. [If Statement](language/if.md) + 10. [While Loop](language/while.md) + 11. [Loop Statement](language/loop.md) + 12. [For Loop](language/for.md) + 13. [Return Values](language/return.md) + 14. [Throw Exception on Error](language/throw.md) + 15. [Functions](language/functions.md) 1. [Call Method as Function](language/method.md) 2. [Overloading](language/overload.md) 3. [Namespaces](language/fn-namespaces.md) 4. [Function Pointers](language/fn-ptr.md) 5. [Anonymous Functions](language/fn-anon.md) 6. [Currying](language/fn-curry.md) - 15. [Print and Debug](language/print-debug.md) - 16. [Modules](language/modules/index.md) + 16. [Print and Debug](language/print-debug.md) + 17. [Modules](language/modules/index.md) 1. [Export Variables, Functions and Sub-Modules](language/modules/export.md) 2. [Import Modules](language/modules/import.md) 3. [Create from Rust](rust/modules/index.md) diff --git a/doc/src/about/index.md b/doc/src/about/index.md index 76603bde..cf021da5 100644 --- a/doc/src/about/index.md +++ b/doc/src/about/index.md @@ -7,6 +7,9 @@ Rhai is an embedded scripting language and evaluation engine for Rust that gives to add scripting to any application. -This Book is for version {{version}} of Rhai. +Versions +-------- + +This Book is for version **{{version}}** of Rhai. For the latest development version, see [here]({{rootUrl}}/vnext/). diff --git a/doc/src/about/license.md b/doc/src/about/license.md index a60ac1eb..a1f24339 100644 --- a/doc/src/about/license.md +++ b/doc/src/about/license.md @@ -6,9 +6,10 @@ Licensing Rhai is licensed under either: * [Apache License, Version 2.0]({{repoHome}}/LICENSE-APACHE.txt), or + * [MIT license]({{repoHome}}/LICENSE-MIT.txt) -at your option. +at your choice. Unless explicitly stated otherwise, any contribution intentionally submitted for inclusion in this crate, as defined in the Apache-2.0 license, shall be dual-licensed as above, diff --git a/doc/src/about/non-design.md b/doc/src/about/non-design.md index 52888164..7f40614e 100644 --- a/doc/src/about/non-design.md +++ b/doc/src/about/non-design.md @@ -18,21 +18,38 @@ It doesn't attempt to be a new language. For example: * No first-class functions - Code your functions in Rust instead, and register them with Rhai. - There is, however, support for simple [function pointers] allowing runtime dispatch by function name. + There is, however, support for simple [function pointers] to allow runtime dispatch by function name. * No garbage collection - this should be expected, so... * No closures - do your closure magic in Rust instead; [turn a Rhai scripted function into a Rust closure]({{rootUrl}}/engine/call-fn.md). + But you can [curry][currying] a [function pointer] with arguments to simulate it somewhat. + * No byte-codes/JIT - Rhai has an AST-walking interpreter which will not win any speed races. The purpose of Rhai is not to be extremely _fast_, but to make it as easy as possible to integrate with native Rust applications. + +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, 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. -Therefore, in actual practice, it is usually best to expose a Rust API into Rhai for scripts to call. -All your core functionalities should be in Rust. + +Thin Dynamic Wrapper Layer Over Rust Code +---------------------------------------- + +In actual practice, it is usually best to expose a Rust API into Rhai for scripts to call. + +All the core functionalities should be written in Rust, with Rhai being the dynamic _control_ layer. + This is similar to some dynamic languages where most of the core functionalities reside in a C/C++ standard library. + +Another similar scenario is a web front-end driving back-end services written in a systems language. +In this case, JavaScript takes the role of Rhai while the back-end language, well... it can actually also be Rust. +Except that Rhai integrates with Rust _much_ more tightly, removing the need for interfaces such +as XHR calls and payload encoding such as JSON. diff --git a/doc/src/advanced.md b/doc/src/advanced.md index b7d69e39..cd958c73 100644 --- a/doc/src/advanced.md +++ b/doc/src/advanced.md @@ -5,7 +5,7 @@ Advanced Topics This section covers advanced features such as: -* Simulated [Object Oriented Programming][OOP]. +* Simulated [Object Oriented Programming (OOP)][OOP]. * [`serde`] integration. @@ -13,4 +13,6 @@ This section covers advanced features such as: * [Domain-Specific Languages][DSL]. +* Low-level [function registration API]({{rootUrl}}/rust/register-raw.md) + * The dreaded (or beloved for those with twisted tastes) [`eval`] statement. diff --git a/doc/src/engine/hello-world.md b/doc/src/engine/hello-world.md index c4e868af..908a8cf8 100644 --- a/doc/src/engine/hello-world.md +++ b/doc/src/engine/hello-world.md @@ -22,19 +22,31 @@ fn main() -> Result<(), Box> } ``` -`rhai::EvalAltResult` is a Rust `enum` containing all errors encountered during the parsing or evaluation process. +Evaluate a script file directly: + +```rust +// 'eval_file' takes a 'PathBuf' +let result = engine.eval_file::("hello_world.rhai".into())?; +``` -Evaluate a Script ----------------- +Error Type +---------- -The type parameter is used to specify the type of the return value, which _must_ match the actual type or an error is returned. -Rhai is very strict here. +`rhai::EvalAltResult` is the standard Rhai error type, which is a Rust `enum` containing all errors encountered +during the parsing or evaluation process. -Use [`Dynamic`] for uncertain return types. + +Return Type +----------- + +The type parameter for `Engine::eval` is used to specify the type of the return value, +which _must_ match the actual type or an error is returned. Rhai is very strict here. There are two ways to specify the return type - _turbofish_ notation, or type inference. +Use [`Dynamic`] for uncertain return types. + ```rust let result = engine.eval::("40 + 2")?; // return type is i64, specified using 'turbofish' notation @@ -46,9 +58,3 @@ let result: Dynamic = engine.eval("boo()")?; // use 'Dynamic' if you're not s let result = engine.eval::("40 + 2")?; // returns an error because the actual return type is i64, not String ``` - -Evaluate a script file directly: - -```rust -let result = engine.eval_file::("hello_world.rhai".into())?; // 'eval_file' takes a 'PathBuf' -``` diff --git a/doc/src/engine/raw.md b/doc/src/engine/raw.md index ce61aa91..06e4ff33 100644 --- a/doc/src/engine/raw.md +++ b/doc/src/engine/raw.md @@ -10,7 +10,10 @@ In many controlled embedded environments, however, these may not be needed and u application code storage space. Use `Engine::new_raw` to create a _raw_ `Engine`, in which only a minimal set of -basic arithmetic and logical operators are supported. +basic arithmetic and logical operators are supported (see below). + +To add more functionalities to a _raw_ `Engine`, load [packages] into it. + Built-in Operators ------------------ @@ -20,7 +23,7 @@ Built-in Operators | `+`, | `+=` | `INT`, `FLOAT` (if not [`no_float`]), `ImmutableString` | | `-`, `*`, `/`, `%`, `~`, | `-=`, `*=`, `/=`, `%=`, `~=` | `INT`, `FLOAT` (if not [`no_float`]) | | `<<`, `>>`, `^`, | `<<=`, `>>=`, `^=` | `INT` | -| `&`, `|`, | `&=`, `|=` | `INT`, `bool` | -| `&&`, `||` | | `bool` | +| `&`, \|, | `&=`, \|= | `INT`, `bool` | +| `&&`, \|\| | | `bool` | | `==`, `!=` | | `INT`, `FLOAT` (if not [`no_float`]), `bool`, `char`, `()`, `ImmutableString` | | `>`, `>=`, `<`, `<=` | | `INT`, `FLOAT` (if not [`no_float`]), `char`, `()`, `ImmutableString` | diff --git a/doc/src/language/for.md b/doc/src/language/for.md index 6780a1cd..15ea22e2 100644 --- a/doc/src/language/for.md +++ b/doc/src/language/for.md @@ -3,7 +3,8 @@ {{#include ../links.md}} -Iterating through a range or an [array] is provided by the `for` ... `in` loop. +Iterating through a range or an [array], or any type with a registered _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; `break` can be used to break out of the loop unconditionally. diff --git a/doc/src/language/if.md b/doc/src/language/if.md index 3958a2e3..b9c63dab 100644 --- a/doc/src/language/if.md +++ b/doc/src/language/if.md @@ -19,6 +19,9 @@ if foo(x) { } ``` +Braces Are Mandatory +-------------------- + Unlike C, the condition expression does _not_ need to be enclosed in parentheses '`(`' .. '`)`', but all branches of the `if` statement must be enclosed within braces '`{`' .. '`}`', even when there is only one statement inside the branch. diff --git a/doc/src/language/logic.md b/doc/src/language/logic.md index 113641f6..699b9827 100644 --- a/doc/src/language/logic.md +++ b/doc/src/language/logic.md @@ -65,42 +65,3 @@ a() | b(); // both a() and b() are evaluated a() & b(); // both a() and b() are evaluated ``` - -Compound Assignment Operators ----------------------------- - -```rust -let number = 9; - -number += 8; // number = number + 8 - -number -= 7; // number = number - 7 - -number *= 6; // number = number * 6 - -number /= 5; // number = number / 5 - -number %= 4; // number = number % 4 - -number ~= 3; // number = number ~ 3 - -number <<= 2; // number = number << 2 - -number >>= 1; // number = number >> 1 - -number &= 0x00ff; // number = number & 0x00ff; - -number |= 0x00ff; // number = number | 0x00ff; - -number ^= 0x00ff; // number = number ^ 0x00ff; -``` - -The `+=` operator can also be used to build [strings]: - -```rust -let my_str = "abc"; -my_str += "ABC"; -my_str += 12345; - -my_str == "abcABC12345" -``` diff --git a/doc/src/language/method.md b/doc/src/language/method.md index 6b6b9314..c2e9e99e 100644 --- a/doc/src/language/method.md +++ b/doc/src/language/method.md @@ -4,8 +4,8 @@ Call Method as Function {{#include ../links.md}} -First `&mut` Reference Parameter -------------------------------- +First `&mut` Parameter +---------------------- Property [getters/setters] and [methods][custom types] in a Rust custom type registered with the [`Engine`] can be called just like a regular function. In fact, like Rust, property getters/setters and object methods @@ -37,19 +37,20 @@ array[0].update(); // <- call in method-call style will update 'a' ``` -Encouraged Usage ----------------- +`&mut` is Efficient +------------------ Using a `&mut` first parameter is highly encouraged when using types that are expensive to clone, even when the intention is not to mutate that argument, because it avoids cloning that argument value. -For primary types that are cheap to clone, including `ImmutableString`, this is not necessary. +For primary types that are cheap to clone (e.g. those that implement `Copy`), +including `ImmutableString`, this is not necessary. Avoid `&mut ImmutableString` --------------------------- -`ImmutableString`, Rhai internal [string] type, is an exception. +`ImmutableString`, Rhai's internal [string] type, is an exception. `ImmutableString` is cheap to clone, but expensive to take a mutable reference (because the underlying string must be cloned to make a private copy). diff --git a/doc/src/language/other-op.md b/doc/src/language/other-op.md new file mode 100644 index 00000000..bf5017d3 --- /dev/null +++ b/doc/src/language/other-op.md @@ -0,0 +1,66 @@ +Other Operators +=============== + +{{#include ../links.md}} + + +Compound Assignment Operators +---------------------------- + +```rust +let number = 9; + +number += 8; // number = number + 8 + +number -= 7; // number = number - 7 + +number *= 6; // number = number * 6 + +number /= 5; // number = number / 5 + +number %= 4; // number = number % 4 + +number ~= 3; // number = number ~ 3 + +number <<= 2; // number = number << 2 + +number >>= 1; // number = number >> 1 + +number &= 0x00ff; // number = number & 0x00ff; + +number |= 0x00ff; // number = number | 0x00ff; + +number ^= 0x00ff; // number = number ^ 0x00ff; +``` + + +The Flexible `+=` +---------------- + +The `+=` operator can also be used to build [strings]: + +```rust +let my_str = "abc"; +my_str += "ABC"; +my_str += 12345; + +my_str == "abcABC12345" +``` + +It may also be used to concatenate [arrays]: + +```rust +let my_array = [1, 2, 3]; +my_array += [4, 5]; + +my_array == [1, 2, 3, 4, 5]; +``` + +or mix two [object maps] together: + +```rust +let my_obj = #{a:1, b:2}; +my_obj += #{c:3, d:4, e:5}; + +my_obj.len() == 5; +``` diff --git a/doc/src/rust/custom.md b/doc/src/rust/custom.md index 7460f50e..3e6b5ca3 100644 --- a/doc/src/rust/custom.md +++ b/doc/src/rust/custom.md @@ -66,8 +66,8 @@ let mut engine = Engine::new(); engine.register_type::(); ``` -Methods on Custom Type ---------------------- +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. diff --git a/doc/src/rust/functions.md b/doc/src/rust/functions.md index a929484c..8d8666cf 100644 --- a/doc/src/rust/functions.md +++ b/doc/src/rust/functions.md @@ -11,8 +11,8 @@ see [fallible functions]({{rootUrl}}/rust/fallible.md)). ```rust use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString}; -use rhai::RegisterFn; // use 'RegisterFn' trait for 'register_fn' -use rhai::RegisterResultFn; // use 'RegisterResultFn' trait for 'register_result_fn' +use rhai::RegisterFn; // use 'RegisterFn' trait for 'register_fn' +use rhai::RegisterResultFn; // use 'RegisterResultFn' trait for 'register_result_fn' // Normal function that returns a standard type // Remember to use 'ImmutableString' and not 'String' @@ -26,7 +26,7 @@ fn add_len_str(x: i64, s: &str) -> i64 { // Function that returns a 'Dynamic' value - must return a 'Result' fn get_any_value() -> Result> { - Ok((42_i64).into()) // standard types can use 'into()' + Ok((42_i64).into()) // standard types can use 'into()' } let mut engine = Engine::new(); diff --git a/doc/src/rust/modules/imp-resolver.md b/doc/src/rust/modules/imp-resolver.md index 415abf72..55d68315 100644 --- a/doc/src/rust/modules/imp-resolver.md +++ b/doc/src/rust/modules/imp-resolver.md @@ -30,7 +30,7 @@ impl ModuleResolver for MyModuleResolver { &self, engine: &Engine, // reference to the current 'Engine' path: &str, // the module path - pos: Position, // location of the 'import' statement + pos: Position, // position of the 'import' statement ) -> Result> { // Check module path. if is_valid_module_path(path) { diff --git a/doc/src/rust/override.md b/doc/src/rust/override.md index 576b5ad8..f6d4d656 100644 --- a/doc/src/rust/override.md +++ b/doc/src/rust/override.md @@ -12,7 +12,9 @@ fn to_int(num) { print("Ha! Gotcha! " + num); } -print(to_int(123)); // what happens? +let x = (123).to_int(); + +print(x); // what happens? ``` A registered native Rust function, in turn, overrides any built-in function of the diff --git a/doc/src/start/builds/performance.md b/doc/src/start/builds/performance.md index dc47a4cc..27747208 100644 --- a/doc/src/start/builds/performance.md +++ b/doc/src/start/builds/performance.md @@ -37,8 +37,8 @@ Use `ImmutableString` Internally, Rhai uses _immutable_ [strings] instead of the Rust `String` type. This is mainly to avoid excessive cloning when passing function arguments. -The encapsulated immutable string type is `ImmutableString`. It is cheap to clone (just an `Rc` or `Arc` reference -count increment depending on the [`sync`] feature). +Rhai's internal string type is `ImmutableString` (basically `Rc` or `Arc` depending on the [`sync`] feature). +It is cheap to clone, but expensive to modify (a new copy of the string must be made in order to change it). Therefore, functions taking `String` parameters should use `ImmutableString` or `&str` (which maps to `ImmutableString`) for the best performance with Rhai. diff --git a/doc/src/start/features.md b/doc/src/start/features.md index 023834fd..f2286a38 100644 --- a/doc/src/start/features.md +++ b/doc/src/start/features.md @@ -25,7 +25,7 @@ more control over what a script can (or cannot) do. | `no_module` | Disable loading external [modules]. | | `no_std` | Build for `no-std`. Notice that additional dependencies will be pulled in to replace `std` features. | | `serde` | Enable serialization/deserialization via [`serde`]. Notice that the [`serde`](https://crates.io/crates/serde) crate will be pulled in together with its dependencies. | -| `internals` | Expose internal data structures (e.g. [`AST`] nodes) and enable defining [custom syntax]. Beware that Rhai internals are volatile and may change from version to version. | +| `internals` | Expose internal data structures (e.g. [`AST`] nodes). Beware that Rhai internals are volatile and may change from version to version. | Example @@ -46,7 +46,7 @@ rhai = { version = "{{version}}", features = [ "sync", "unchecked", "only_i32", ``` The resulting scripting engine supports only the `i32` integer numeral type (and no others like `u32`, `i16` or `i64`), -no floating-point, is `Send + Sync` (so it can be safely used across threads), does not support defining [functions] +no floating-point, is `Send + Sync` (so it can be safely used across threads), and does not support defining [functions] nor loading external [modules]. This configuration is perfect for an expression parser in a 32-bit embedded system without floating-point hardware.