Merge branch 'master' into plugins

This commit is contained in:
Stephen Chung 2020-07-26 10:05:56 +08:00
commit 8e33cbfe34
35 changed files with 364 additions and 179 deletions

View File

@ -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

76
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,76 @@
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}}
continue-on-error: ${{matrix.experimental}}
strategy:
matrix:
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
- 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 ${{matrix.flags}}

View File

@ -1,10 +0,0 @@
language: rust
rust:
- stable
- beta
- nightly
matrix:
allow_failures:
- rust: nightly
script: bash ./.ci/build.sh

View File

@ -2,7 +2,7 @@ Rhai - Embedded Scripting for Rust
================================= =================================
![GitHub last commit](https://img.shields.io/github/last-commit/jonathandturner/rhai) ![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) [![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/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/)
@ -73,7 +73,7 @@ Licensed under either:
* [Apache License, Version 2.0](https://github.com/jonathandturner/rhai/blob/master/LICENSE-APACHE.txt), or * [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) * [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 Unless explicitly stated otherwise, any contribution intentionally submitted
for inclusion in this crate, as defined in the Apache-2.0 license, shall for inclusion in this crate, as defined in the Apache-2.0 license, shall

View File

@ -5,8 +5,9 @@ The Rhai Scripting Language
1. [Features](about/features.md) 1. [Features](about/features.md)
2. [Supported Targets and Builds](about/targets.md) 2. [Supported Targets and Builds](about/targets.md)
3. [What Rhai Isn't](about/non-design.md) 3. [What Rhai Isn't](about/non-design.md)
4. [Related Resources](about/related.md) 4. [Licensing](about/license.md)
3. [Getting Started](start/index.md) 5. [Related Resources](about/related.md)
2. [Getting Started](start/index.md)
1. [Online Playground](start/playground.md) 1. [Online Playground](start/playground.md)
2. [Install the Rhai Crate](start/install.md) 2. [Install the Rhai Crate](start/install.md)
3. [Optional Features](start/features.md) 3. [Optional Features](start/features.md)
@ -18,14 +19,14 @@ The Rhai Scripting Language
5. [Examples](start/examples/index.md) 5. [Examples](start/examples/index.md)
1. [Rust](start/examples/rust.md) 1. [Rust](start/examples/rust.md)
2. [Scripts](start/examples/scripts.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) 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) 3. [Call a Rhai Function from Rust](engine/call-fn.md)
4. [Create a Rust Anonymous Function from a Rhai Function](engine/func.md) 4. [Create a Rust Anonymous Function from a Rhai Function](engine/func.md)
5. [Evaluate Expressions Only](engine/expressions.md) 5. [Evaluate Expressions Only](engine/expressions.md)
6. [Raw Engine](engine/raw.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) 1. [Traits](rust/traits.md)
2. [Register a Rust Function](rust/functions.md) 2. [Register a Rust Function](rust/functions.md)
1. [String Parameters in Rust Functions](rust/strings.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) 4. [Printing Custom Types](rust/print-custom.md)
9. [Scope - Initializing and Maintaining State](rust/scope.md) 9. [Scope - Initializing and Maintaining State](rust/scope.md)
10. [Engine Configuration Options](rust/options.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) 1. [Comments](language/comments.md)
2. [Values and Types](language/values-and-types.md) 2. [Values and Types](language/values-and-types.md)
1. [Dynamic Values](language/dynamic.md) 1. [Dynamic Values](language/dynamic.md)
@ -64,28 +65,29 @@ The Rhai Scripting Language
5. [Variables](language/variables.md) 5. [Variables](language/variables.md)
6. [Constants](language/constants.md) 6. [Constants](language/constants.md)
7. [Logic Operators](language/logic.md) 7. [Logic Operators](language/logic.md)
8. [If Statement](language/if.md) 8. [Other Operators](language/other-op.md)
9. [While Loop](language/while.md) 9. [If Statement](language/if.md)
10. [Loop Statement](language/loop.md) 10. [While Loop](language/while.md)
11. [For Loop](language/for.md) 11. [Loop Statement](language/loop.md)
12. [Return Values](language/return.md) 12. [For Loop](language/for.md)
13. [Throw Exception on Error](language/throw.md) 13. [Return Values](language/return.md)
14. [Functions](language/functions.md) 14. [Throw Exception on Error](language/throw.md)
15. [Functions](language/functions.md)
1. [Call Method as Function](language/method.md) 1. [Call Method as Function](language/method.md)
2. [Overloading](language/overload.md) 2. [Overloading](language/overload.md)
3. [Namespaces](language/fn-namespaces.md) 3. [Namespaces](language/fn-namespaces.md)
4. [Function Pointers](language/fn-ptr.md) 4. [Function Pointers](language/fn-ptr.md)
5. [Anonymous Functions](language/fn-anon.md) 5. [Anonymous Functions](language/fn-anon.md)
6. [Currying](language/fn-curry.md) 6. [Currying](language/fn-curry.md)
15. [Print and Debug](language/print-debug.md) 16. [Print and Debug](language/print-debug.md)
16. [Modules](language/modules/index.md) 17. [Modules](language/modules/index.md)
1. [Export Variables, Functions and Sub-Modules](language/modules/export.md) 1. [Export Variables, Functions and Sub-Modules](language/modules/export.md)
2. [Import Modules](language/modules/import.md) 2. [Import Modules](language/modules/import.md)
3. [Create from Rust](rust/modules/index.md) 3. [Create from Rust](rust/modules/index.md)
4. [Create from AST](language/modules/ast.md) 4. [Create from AST](language/modules/ast.md)
5. [Module Resolvers](rust/modules/resolvers.md) 5. [Module Resolvers](rust/modules/resolvers.md)
1. [Custom Implementation](rust/modules/imp-resolver.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) 1. [Checked Arithmetic](safety/checked.md)
2. [Sand-Boxing](safety/sandbox.md) 2. [Sand-Boxing](safety/sandbox.md)
3. [Maximum Length of Strings](safety/max-string-size.md) 3. [Maximum Length of Strings](safety/max-string-size.md)
@ -96,7 +98,7 @@ The Rhai Scripting Language
7. [Maximum Number of Modules](safety/max-modules.md) 7. [Maximum Number of Modules](safety/max-modules.md)
8. [Maximum Call Stack Depth](safety/max-call-stack.md) 8. [Maximum Call Stack Depth](safety/max-call-stack.md)
9. [Maximum Statement Depth](safety/max-stmt-depth.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) 1. [Object-Oriented Programming (OOP)](language/oop.md)
2. [Serialization/Deserialization of `Dynamic` with `serde`](rust/serde.md) 2. [Serialization/Deserialization of `Dynamic` with `serde`](rust/serde.md)
3. [Script Optimization](engine/optimize/index.md) 3. [Script Optimization](engine/optimize/index.md)
@ -112,7 +114,7 @@ The Rhai Scripting Language
2. [Custom Operators](engine/custom-op.md) 2. [Custom Operators](engine/custom-op.md)
3. [Extending with Custom Syntax](engine/custom-syntax.md) 3. [Extending with Custom Syntax](engine/custom-syntax.md)
6. [Eval Statement](language/eval.md) 6. [Eval Statement](language/eval.md)
9. [Appendix](appendix/index.md) 8. [Appendix](appendix/index.md)
1. [Keywords](appendix/keywords.md) 1. [Keywords](appendix/keywords.md)
2. [Operators and Symbols](appendix/operators.md) 2. [Operators and Symbols](appendix/operators.md)
3. [Literals](appendix/literals.md) 3. [Literals](appendix/literals.md)

View File

@ -7,6 +7,9 @@ Rhai is an embedded scripting language and evaluation engine for Rust that gives
to add scripting to any application. 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/). For the latest development version, see [here]({{rootUrl}}/vnext/).

16
doc/src/about/license.md Normal file
View File

@ -0,0 +1,16 @@
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 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,
without any additional terms or conditions.

View File

@ -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. * 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 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). * 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 * 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. 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 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. 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 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. 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. 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.

View File

@ -5,7 +5,7 @@ Advanced Topics
This section covers advanced features such as: This section covers advanced features such as:
* Simulated [Object Oriented Programming][OOP]. * Simulated [Object Oriented Programming (OOP)][OOP].
* [`serde`] integration. * [`serde`] integration.
@ -13,4 +13,6 @@ This section covers advanced features such as:
* [Domain-Specific Languages][DSL]. * [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. * The dreaded (or beloved for those with twisted tastes) [`eval`] statement.

View File

@ -1,5 +1,7 @@
{ {
"version": "0.18.0", "version": "0.18.0",
"repoHome": "https://github.com/jonathandturner/rhai/blob/master",
"repoTree": "https://github.com/jonathandturner/rhai/tree/master",
"rootUrl": "", "rootUrl": "",
"rootUrlX": "/rhai", "rootUrlX": "/rhai",
"rootUrlXX": "/rhai/vnext" "rootUrlXX": "/rhai/vnext"

View File

@ -22,19 +22,31 @@ fn main() -> Result<(), Box<EvalAltResult>>
} }
``` ```
`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::<i64>("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::EvalAltResult` is the standard Rhai error type, which is a Rust `enum` containing all errors encountered
Rhai is very strict here. 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. There are two ways to specify the return type - _turbofish_ notation, or type inference.
Use [`Dynamic`] for uncertain return types.
```rust ```rust
let result = engine.eval::<i64>("40 + 2")?; // return type is i64, specified using 'turbofish' notation let result = engine.eval::<i64>("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::<String>("40 + 2")?; // returns an error because the actual return type is i64, not String let result = engine.eval::<String>("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::<i64>("hello_world.rhai".into())?; // 'eval_file' takes a 'PathBuf'
```

View File

@ -10,7 +10,10 @@ In many controlled embedded environments, however, these may not be needed and u
application code storage space. application code storage space.
Use `Engine::new_raw` to create a _raw_ `Engine`, in which only a minimal set of 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 Built-in Operators
------------------ ------------------
@ -20,7 +23,7 @@ Built-in Operators
| `+`, | `+=` | `INT`, `FLOAT` (if not [`no_float`]), `ImmutableString` | | `+`, | `+=` | `INT`, `FLOAT` (if not [`no_float`]), `ImmutableString` |
| `-`, `*`, `/`, `%`, `~`, | `-=`, `*=`, `/=`, `%=`, `~=` | `INT`, `FLOAT` (if not [`no_float`]) | | `-`, `*`, `/`, `%`, `~`, | `-=`, `*=`, `/=`, `%=`, `~=` | `INT`, `FLOAT` (if not [`no_float`]) |
| `<<`, `>>`, `^`, | `<<=`, `>>=`, `^=` | `INT` | | `<<`, `>>`, `^`, | `<<=`, `>>=`, `^=` | `INT` |
| `&`, `|`, | `&=`, `|=` | `INT`, `bool` | | `&`, <code>\|</code>, | `&=`, <code>\|=</code> | `INT`, `bool` |
| `&&`, `||` | | `bool` | | `&&`, <code>\|\|</code> | | `bool` |
| `==`, `!=` | | `INT`, `FLOAT` (if not [`no_float`]), `bool`, `char`, `()`, `ImmutableString` | | `==`, `!=` | | `INT`, `FLOAT` (if not [`no_float`]), `bool`, `char`, `()`, `ImmutableString` |
| `>`, `>=`, `<`, `<=` | | `INT`, `FLOAT` (if not [`no_float`]), `char`, `()`, `ImmutableString` | | `>`, `>=`, `<`, `<=` | | `INT`, `FLOAT` (if not [`no_float`]), `char`, `()`, `ImmutableString` |

View File

@ -3,7 +3,8 @@
{{#include ../links.md}} {{#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; 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. `break` can be used to break out of the loop unconditionally.

View File

@ -19,6 +19,9 @@ if foo(x) {
} }
``` ```
Braces Are Mandatory
--------------------
Unlike C, the condition expression does _not_ need to be enclosed in parentheses '`(`' .. '`)`', but 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 '`{`' .. '`}`', all branches of the `if` statement must be enclosed within braces '`{`' .. '`}`',
even when there is only one statement inside the branch. even when there is only one statement inside the branch.

View File

@ -65,42 +65,3 @@ a() | b(); // both a() and b() are evaluated
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"
```

View File

@ -4,8 +4,8 @@ Call Method as Function
{{#include ../links.md}} {{#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 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 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, 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. 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` 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 `ImmutableString` is cheap to clone, but expensive to take a mutable reference (because the underlying
string must be cloned to make a private copy). string must be cloned to make a private copy).

View File

@ -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;
```

View File

@ -66,8 +66,8 @@ let mut engine = Engine::new();
engine.register_type::<TestStruct>(); engine.register_type::<TestStruct>();
``` ```
Methods on Custom Type Methods on The Custom Type
--------------------- -------------------------
To use native custom types, methods and functions in Rhai scripts, simply register them To use native custom types, methods and functions in Rhai scripts, simply register them
using one of the `Engine::register_XXX` API. using one of the `Engine::register_XXX` API.

View File

@ -11,8 +11,8 @@ see [fallible functions]({{rootUrl}}/rust/fallible.md)).
```rust ```rust
use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString}; use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString};
use rhai::RegisterFn; // use 'RegisterFn' trait for 'register_fn' use rhai::RegisterFn; // use 'RegisterFn' trait for 'register_fn'
use rhai::RegisterResultFn; // use 'RegisterResultFn' trait for 'register_result_fn' use rhai::RegisterResultFn; // use 'RegisterResultFn' trait for 'register_result_fn'
// Normal function that returns a standard type // Normal function that returns a standard type
// Remember to use 'ImmutableString' and not 'String' // 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' // Function that returns a 'Dynamic' value - must return a 'Result'
fn get_any_value() -> Result<Dynamic, Box<EvalAltResult>> { fn get_any_value() -> Result<Dynamic, Box<EvalAltResult>> {
Ok((42_i64).into()) // standard types can use 'into()' Ok((42_i64).into()) // standard types can use 'into()'
} }
let mut engine = Engine::new(); let mut engine = Engine::new();

View File

@ -30,7 +30,7 @@ impl ModuleResolver for MyModuleResolver {
&self, &self,
engine: &Engine, // reference to the current 'Engine' engine: &Engine, // reference to the current 'Engine'
path: &str, // the module path path: &str, // the module path
pos: Position, // location of the 'import' statement pos: Position, // position of the 'import' statement
) -> Result<Module, Box<EvalAltResult>> { ) -> Result<Module, Box<EvalAltResult>> {
// Check module path. // Check module path.
if is_valid_module_path(path) { if is_valid_module_path(path) {

View File

@ -12,7 +12,9 @@ fn to_int(num) {
print("Ha! Gotcha! " + 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 A registered native Rust function, in turn, overrides any built-in function of the

View File

@ -37,8 +37,8 @@ Use `ImmutableString`
Internally, Rhai uses _immutable_ [strings] instead of the Rust `String` type. This is mainly to avoid excessive Internally, Rhai uses _immutable_ [strings] instead of the Rust `String` type. This is mainly to avoid excessive
cloning when passing function arguments. cloning when passing function arguments.
The encapsulated immutable string type is `ImmutableString`. It is cheap to clone (just an `Rc` or `Arc` reference Rhai's internal string type is `ImmutableString` (basically `Rc<String>` or `Arc<String>` depending on the [`sync`] feature).
count increment 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`) Therefore, functions taking `String` parameters should use `ImmutableString` or `&str` (which maps to `ImmutableString`)
for the best performance with Rhai. for the best performance with Rhai.

View File

@ -5,17 +5,17 @@ Rust Examples
A number of examples can be found in the `examples` directory: A number of examples can be found in the `examples` directory:
| Example | Description | | 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. | | [`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`](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. | | [`custom_types_and_methods`]({{repoTree}}/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. | | [`hello`]({{repoTree}}/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`]. | | [`reuse_scope`]({{repoTree}}/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. | | [`rhai_runner`]({{repoTree}}/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).<br/>The [`serde`] feature is required to run. | | [`serde`]({{repoTree}}/examples/serde.rs) | Example to serialize and deserialize Rust types with [`serde`](https://crates.io/crates/serde).<br/>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. | | [`simple_fn`]({{repoTree}}/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. | | [`strings`]({{repoTree}}/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. | | [`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 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). 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: To illustrate `no-std` builds, a number of sample applications are available under the `no_std` directory:
| Sample | Description | Optimization | Allocator | Panics | | 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 | | [`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: `cargo run` cannot be used to run a `no-std` sample. It must first be built:

View File

@ -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: There are also a number of examples scripts that showcase Rhai's features, all in the `scripts` directory:
| Script | Description | | Script | Description |
| -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| [`array.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/array.rhai) | [Arrays] | | [`array.rhai`]({{repoTree}}/scripts/array.rhai) | [Arrays] |
| [`assignment.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/assignment.rhai) | Variable declarations | | [`assignment.rhai`]({{repoTree}}/scripts/assignment.rhai) | Variable declarations |
| [`comments.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/comments.rhai) | Just comments | | [`comments.rhai`]({{repoTree}}/scripts/comments.rhai) | Just comments |
| [`for1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/for1.rhai) | [`for`]({{rootUrl}}/language/for.md) loops | | [`for1.rhai`]({{repoTree}}/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] | | [`for2.rhai`]({{repoTree}}/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_decl1.rhai`]({{repoTree}}/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_decl2.rhai`]({{repoTree}}/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 | | [`function_decl3.rhai`]({{repoTree}}/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 | | [`if1.rhai`]({{repoTree}}/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 | | [`loop.rhai`]({{repoTree}}/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] | | [`oop.rhai`]({{repoTree}}/scripts/oop.rhai) | Simulate [object-oriented programming (OOP)][OOP] |
| [`op1.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op1.rhai) | Just simple addition | | [`op1.rhai`]({{repoTree}}/scripts/op1.rhai) | Just simple addition |
| [`op2.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op2.rhai) | Simple addition and multiplication | | [`op2.rhai`]({{repoTree}}/scripts/op2.rhai) | Simple addition and multiplication |
| [`op3.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/op3.rhai) | Change evaluation order with parenthesis | | [`op3.rhai`]({{repoTree}}/scripts/op3.rhai) | Change evaluation order with parenthesis |
| [`string.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/string.rhai) | [String] operations | | [`string.rhai`]({{repoTree}}/scripts/string.rhai) | [String] operations |
| [`strings_map.rhai`](https://github.com/jonathandturner/rhai/tree/master/scripts/strings_map.rhai) | [String] and [object map] operations | | [`strings_map.rhai`]({{repoTree}}/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 | | [`while.rhai`]({{repoTree}}/scripts/while.rhai) | [`while`]({{rootUrl}}/language/while.md) loop |
Benchmark Scripts Benchmark Scripts
@ -34,12 +34,12 @@ Benchmark Scripts
The following scripts are for benchmarking the speed of Rhai: The following scripts are for benchmarking the speed of Rhai:
| Scripts | Description | | 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). | | [`speed_test.rhai`]({{repoTree}}/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. | | [`primes.rhai`]({{repoTree}}/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. | | [`fibonacci.rhai`]({{repoTree}}/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. | | [`mat_mul.rhai`]({{repoTree}}/scripts/mat_mul.rhai) | Matrix multiplication test to measure the speed of multi-dimensional array access. |
Running Example Scripts Running Example Scripts

View File

@ -25,7 +25,7 @@ more control over what a script can (or cannot) do.
| `no_module` | Disable loading external [modules]. | | `no_module` | Disable loading external [modules]. |
| `no_std` | Build for `no-std`. Notice that additional dependencies will be pulled in to replace `std` features. | | `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. | | `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 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`), 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]. nor loading external [modules].
This configuration is perfect for an expression parser in a 32-bit embedded system without floating-point hardware. This configuration is perfect for an expression parser in a 32-bit embedded system without floating-point hardware.

View File

@ -1,10 +1,12 @@
cargo-features = ["named-profiles"]
[package] [package]
name = "no_std_test" name = "no_std_test"
version = "0.1.0" version = "0.1.0"
edition = "2018" edition = "2018"
authors = ["Stephen Chung"] authors = ["Stephen Chung"]
description = "no-std test application" 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" repository = "https://github.com/jonathandturner/rhai"
[dependencies] [dependencies]
@ -18,7 +20,17 @@ panic = "abort"
opt-level = "z" # optimize for size opt-level = "z" # optimize for size
debug = false debug = false
rpath = false rpath = false
lto = "fat"
debug-assertions = false debug-assertions = false
codegen-units = 1 codegen-units = 1
panic = "abort" panic = "abort"
[profile.unix]
inherits = "release"
lto = true
[profile.windows]
inherits = "release"
[profile.macos]
inherits = "release"
lto = "fat"

View File

@ -12,7 +12,9 @@ To Compile
The nightly compiler is required: The nightly compiler is required:
```bash ```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. The release build is optimized for size. It can be changed to optimize on speed instead.

View File

@ -2,7 +2,7 @@
//! a simple expression and uses the result as the return value. //! a simple expression and uses the result as the return value.
#![no_std] #![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 alloc;
extern crate wee_alloc; extern crate wee_alloc;
@ -10,6 +10,12 @@ extern crate wee_alloc;
#[global_allocator] #[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; 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}; use rhai::{Engine, INT};
#[start] #[start]

View File

@ -639,9 +639,7 @@ impl Engine {
) )
.or_else(|err| match *err { .or_else(|err| match *err {
// If there is no index setter, no need to set it back because the indexer is read-only // If there is no index setter, no need to set it back because the indexer is read-only
EvalAltResult::ErrorFunctionNotFound(s, _) EvalAltResult::ErrorFunctionNotFound(_, _) => {
if s == FN_IDX_SET =>
{
Ok(Default::default()) Ok(Default::default())
} }
_ => Err(err), _ => Err(err),

View File

@ -865,10 +865,22 @@ impl Engine {
EvalAltResult::ErrorFunctionNotFound(_, _) if def_val.is_some() => { EvalAltResult::ErrorFunctionNotFound(_, _) if def_val.is_some() => {
Ok(def_val.unwrap().into()) Ok(def_val.unwrap().into())
} }
EvalAltResult::ErrorFunctionNotFound(_, _) => { EvalAltResult::ErrorFunctionNotFound(_, pos) => {
Err(Box::new(EvalAltResult::ErrorFunctionNotFound( Err(Box::new(EvalAltResult::ErrorFunctionNotFound(
format!("{}{}", modules, name), format!(
Position::none(), "{}{} ({})",
modules,
name,
args.iter()
.map(|a| if a.is::<ImmutableString>() {
"&str | ImmutableString | String"
} else {
self.map_type_name((*a).type_name())
})
.collect::<Vec<_>>()
.join(", ")
),
pos,
))) )))
} }
_ => Err(err), _ => Err(err),

View File

@ -10,9 +10,12 @@ use crate::token::{is_valid_identifier, Position};
use crate::utils::{ImmutableString, StaticVec}; use crate::utils::{ImmutableString, StaticVec};
use crate::Scope; use crate::Scope;
use crate::stdlib::{ use crate::stdlib::{boxed::Box, convert::TryFrom, fmt, mem, string::String, vec::Vec};
boxed::Box, convert::TryFrom, fmt, mem, rc::Rc, string::String, sync::Arc, 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. /// Trait that maps to `Send + Sync` only under the `sync` feature.
#[cfg(feature = "sync")] #[cfg(feature = "sync")]

View File

@ -20,9 +20,12 @@ use crate::stdlib::{
boxed::Box, boxed::Box,
fmt::Display, fmt::Display,
format, 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 // Checked add
pub(crate) fn add<T: Display + CheckedAdd>(x: T, y: T) -> FuncReturn<T> { pub(crate) fn add<T: Display + CheckedAdd>(x: T, y: T) -> FuncReturn<T> {
x.checked_add(&y).ok_or_else(|| { x.checked_add(&y).ok_or_else(|| {
@ -171,10 +174,12 @@ pub(crate) fn shr<T: Display + CheckedShr>(x: T, y: INT) -> FuncReturn<T> {
}) })
} }
// Unchecked left-shift - may panic if shifting by a negative number of bits // Unchecked left-shift - may panic if shifting by a negative number of bits
#[cfg(feature = "unchecked")]
pub(crate) fn shl_u<T: Shl<T>>(x: T, y: T) -> FuncReturn<<T as Shl<T>>::Output> { pub(crate) fn shl_u<T: Shl<T>>(x: T, y: T) -> FuncReturn<<T as Shl<T>>::Output> {
Ok(x.shl(y)) Ok(x.shl(y))
} }
// Unchecked right-shift - may panic if shifting by a negative number of bits // Unchecked right-shift - may panic if shifting by a negative number of bits
#[cfg(feature = "unchecked")]
pub(crate) fn shr_u<T: Shr<T>>(x: T, y: T) -> FuncReturn<<T as Shr<T>>::Output> { pub(crate) fn shr_u<T: Shr<T>>(x: T, y: T) -> FuncReturn<<T as Shr<T>>::Output> {
Ok(x.shr(y)) Ok(x.shr(y))
} }
@ -229,6 +234,7 @@ pub(crate) fn pow_i_i(x: INT, y: INT) -> FuncReturn<INT> {
} }
} }
// Unchecked integer power - may panic on overflow or if the power index is too high (> u32::MAX) // 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<INT> { pub(crate) fn pow_i_i_u(x: INT, y: INT) -> FuncReturn<INT> {
Ok(x.pow(y as u32)) Ok(x.pow(y as u32))
} }

View File

@ -74,6 +74,7 @@ impl PackagesCollection {
.flatten() .flatten()
} }
/// Does the specified TypeId iterator exist in the `PackagesCollection`? /// Does the specified TypeId iterator exist in the `PackagesCollection`?
#[allow(dead_code)]
pub fn contains_iter(&self, id: TypeId) -> bool { pub fn contains_iter(&self, id: TypeId) -> bool {
self.0.iter().any(|p| p.contains_iter(id)) self.0.iter().any(|p| p.contains_iter(id))
} }

View File

@ -1,12 +1,17 @@
#![cfg(not(feature = "no_std"))] #![cfg(not(feature = "no_std"))]
use super::logic::{eq, gt, gte, lt, lte, ne}; use super::logic::{eq, gt, gte, lt, lte, ne};
#[cfg(feature = "no_float")]
use super::math_basic::MAX_INT; use super::math_basic::MAX_INT;
use crate::def_package; use crate::def_package;
use crate::module::FuncReturn;
use crate::parser::INT;
use crate::result::EvalAltResult; 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"))] #[cfg(not(target_arch = "wasm32"))]
use crate::stdlib::time::Instant; use crate::stdlib::time::Instant;
@ -14,9 +19,6 @@ use crate::stdlib::time::Instant;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use instant::Instant; use instant::Instant;
#[cfg(not(feature = "no_float"))]
use crate::parser::FLOAT;
def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, { def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, {
// Register date/time functions // Register date/time functions
lib.set_fn_0("timestamp", || Ok(Instant::now())); lib.set_fn_0("timestamp", || Ok(Instant::now()));

View File

@ -14,11 +14,14 @@ use crate::utils::StaticVec;
use crate::stdlib::{ use crate::stdlib::{
boxed::Box, boxed::Box,
fmt, format, fmt, format,
rc::Rc,
string::{String, ToString}, 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. /// A general expression evaluation trait object.
#[cfg(not(feature = "sync"))] #[cfg(not(feature = "sync"))]
pub type FnCustomSyntaxEval = dyn Fn( pub type FnCustomSyntaxEval = dyn Fn(