More benchmarks and examples.
This commit is contained in:
parent
331513f5e0
commit
c6e5f672c9
63
README.md
63
README.md
@ -37,7 +37,7 @@ Features
|
|||||||
to do checked arithmetic operations); for [`no-std`](#optional-features) builds, a number of additional dependencies are
|
to do checked arithmetic operations); for [`no-std`](#optional-features) builds, a number of additional dependencies are
|
||||||
pulled in to provide for functionalities that used to be in `std`.
|
pulled in to provide for functionalities that used to be in `std`.
|
||||||
|
|
||||||
**Note:** Currently, the version is 0.15.0, so the language and API's may change before they stabilize.
|
**Note:** Currently, the version is `0.15.0`, so the language and API's may change before they stabilize.
|
||||||
|
|
||||||
What Rhai doesn't do
|
What Rhai doesn't do
|
||||||
--------------------
|
--------------------
|
||||||
@ -67,7 +67,7 @@ This is similar to some dynamic languages where most of the core functionalities
|
|||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Install the Rhai crate by adding this line to `dependencies`:
|
Install the Rhai crate on [`crates.io`](https::/crates.io/crates/rhai/) by adding this line to `dependencies`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -191,33 +191,35 @@ A number of examples can be found in the `examples` folder:
|
|||||||
Examples can be run with the following command:
|
Examples can be run with the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo run --example name
|
cargo run --example {example_name}
|
||||||
```
|
```
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
Example Scripts
|
Example scripts
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
There are also a number of examples scripts that showcase Rhai's features, all in the `scripts` folder:
|
There are also a number of examples scripts that showcase Rhai's features, all in the `scripts` folder:
|
||||||
|
|
||||||
| Language feature scripts | Description |
|
| Language feature scripts | Description |
|
||||||
| ---------------------------------------------------- | ------------------------------------------------------------- |
|
| ---------------------------------------------------- | ----------------------------------------------------------------------------- |
|
||||||
| [`array.rhai`](scripts/array.rhai) | [arrays] in Rhai |
|
| [`array.rhai`](scripts/array.rhai) | [arrays] in Rhai |
|
||||||
| [`assignment.rhai`](scripts/assignment.rhai) | variable declarations |
|
| [`assignment.rhai`](scripts/assignment.rhai) | variable declarations |
|
||||||
| [`comments.rhai`](scripts/comments.rhai) | just comments |
|
| [`comments.rhai`](scripts/comments.rhai) | just comments |
|
||||||
| [`for1.rhai`](scripts/for1.rhai) | for loops |
|
| [`for1.rhai`](scripts/for1.rhai) | [`for`](#for-loop) loops |
|
||||||
| [`function_decl1.rhai`](scripts/function_decl1.rhai) | a function without parameters |
|
| [`for2.rhai`](scripts/for2.rhai) | [`for`](#for-loop) loops on [arrays] |
|
||||||
| [`function_decl2.rhai`](scripts/function_decl2.rhai) | a function with two parameters |
|
| [`function_decl1.rhai`](scripts/function_decl1.rhai) | a [function] without parameters |
|
||||||
| [`function_decl3.rhai`](scripts/function_decl3.rhai) | a function with many parameters |
|
| [`function_decl2.rhai`](scripts/function_decl2.rhai) | a [function] with two parameters |
|
||||||
| [`if1.rhai`](scripts/if1.rhai) | if example |
|
| [`function_decl3.rhai`](scripts/function_decl3.rhai) | a [function] with many parameters |
|
||||||
| [`loop.rhai`](scripts/loop.rhai) | endless loop in Rhai, this example emulates a do..while cycle |
|
| [`if1.rhai`](scripts/if1.rhai) | [`if`](#if-statement) example |
|
||||||
| [`op1.rhai`](scripts/op1.rhai) | just a simple addition |
|
| [`loop.rhai`](scripts/loop.rhai) | count-down [`loop`](#infinite-loop) in Rhai, emulating a `do` .. `while` loop |
|
||||||
| [`op2.rhai`](scripts/op2.rhai) | simple addition and multiplication |
|
| [`op1.rhai`](scripts/op1.rhai) | just simple addition |
|
||||||
| [`op3.rhai`](scripts/op3.rhai) | change evaluation order with parenthesis |
|
| [`op2.rhai`](scripts/op2.rhai) | simple addition and multiplication |
|
||||||
| [`string.rhai`](scripts/string.rhai) | [string] operations |
|
| [`op3.rhai`](scripts/op3.rhai) | change evaluation order with parenthesis |
|
||||||
| [`while.rhai`](scripts/while.rhai) | while loop |
|
| [`string.rhai`](scripts/string.rhai) | [string] operations |
|
||||||
|
| [`strings_map.rhai`](scripts/strings_map.rhai) | [string] and [object map] operations |
|
||||||
|
| [`while.rhai`](scripts/while.rhai) | [`while`](#while-loop) loop |
|
||||||
|
|
||||||
| Example scripts | Description |
|
| Example scripts | Description |
|
||||||
| -------------------------------------------- | ---------------------------------------------------------------------------------- |
|
| -------------------------------------------- | ---------------------------------------------------------------------------------- |
|
||||||
@ -247,6 +249,7 @@ fn main() -> Result<(), Box<EvalAltResult>>
|
|||||||
let engine = Engine::new();
|
let engine = Engine::new();
|
||||||
|
|
||||||
let result = engine.eval::<i64>("40 + 2")?;
|
let result = engine.eval::<i64>("40 + 2")?;
|
||||||
|
// ^^^^^^^ cast the result to an 'i64', this is required
|
||||||
|
|
||||||
println!("Answer: {}", result); // prints 42
|
println!("Answer: {}", result); // prints 42
|
||||||
|
|
||||||
@ -303,6 +306,8 @@ let ast = engine.compile_file("hello_world.rhai".into())?;
|
|||||||
|
|
||||||
### Calling Rhai functions from Rust
|
### Calling Rhai functions from Rust
|
||||||
|
|
||||||
|
[`private`]: #calling-rhai-functions-from-rust
|
||||||
|
|
||||||
Rhai also allows working _backwards_ from the other direction - i.e. calling a Rhai-scripted function from Rust via `Engine::call_fn`.
|
Rhai also allows working _backwards_ from the other direction - i.e. calling a Rhai-scripted function from Rust via `Engine::call_fn`.
|
||||||
Functions declared with `private` are hidden and cannot be called from Rust (see also [modules]).
|
Functions declared with `private` are hidden and cannot be called from Rust (see also [modules]).
|
||||||
|
|
||||||
@ -1870,8 +1875,8 @@ my_str += 12345;
|
|||||||
my_str == "abcABC12345"
|
my_str == "abcABC12345"
|
||||||
```
|
```
|
||||||
|
|
||||||
`if` statements
|
`if` statement
|
||||||
---------------
|
--------------
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
if foo(x) {
|
if foo(x) {
|
||||||
@ -1906,8 +1911,8 @@ let x = if decision { 42 }; // no else branch defaults to '()'
|
|||||||
x == ();
|
x == ();
|
||||||
```
|
```
|
||||||
|
|
||||||
`while` loops
|
`while` loop
|
||||||
-------------
|
------------
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let x = 10;
|
let x = 10;
|
||||||
@ -1934,8 +1939,8 @@ loop {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`for` loops
|
`for` loop
|
||||||
-----------
|
----------
|
||||||
|
|
||||||
Iterating through a range or an [array] is provided by the `for` ... `in` loop.
|
Iterating through a range or an [array] is provided by the `for` ... `in` loop.
|
||||||
|
|
||||||
@ -2206,8 +2211,8 @@ Modules can be disabled via the [`no_module`] feature.
|
|||||||
A _module_ is a single script (or pre-compiled `AST`) containing global variables and functions.
|
A _module_ is a single script (or pre-compiled `AST`) containing global variables and functions.
|
||||||
The `export` statement, which can only be at global level, exposes selected variables as members of a module.
|
The `export` statement, which can only be at global level, exposes selected variables as members of a module.
|
||||||
Variables not exported are _private_ and invisible to the outside.
|
Variables not exported are _private_ and invisible to the outside.
|
||||||
On the other hand, all functions are automatically exported, _unless_ it is explicitly opt-out with the `private` prefix.
|
On the other hand, all functions are automatically exported, _unless_ it is explicitly opt-out with the [`private`] prefix.
|
||||||
Functions declared `private` are invisible to the outside.
|
Functions declared [`private`] are invisible to the outside.
|
||||||
|
|
||||||
Everything exported from a module is **constant** (**read-only**).
|
Everything exported from a module is **constant** (**read-only**).
|
||||||
|
|
||||||
@ -2301,7 +2306,7 @@ engine.eval_expression_with_scope::<i64>(&scope, "question::inc(question::answer
|
|||||||
|
|
||||||
It is easy to convert a pre-compiled `AST` into a module: just use `Module::eval_ast_as_new`.
|
It is easy to convert a pre-compiled `AST` into a module: just use `Module::eval_ast_as_new`.
|
||||||
Don't forget the `export` statement, otherwise there will be no variables exposed by the module
|
Don't forget the `export` statement, otherwise there will be no variables exposed by the module
|
||||||
other than non-`private` functions (unless that's intentional).
|
other than non-[`private`] functions (unless that's intentional).
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use rhai::{Engine, Module};
|
use rhai::{Engine, Module};
|
||||||
|
@ -61,3 +61,27 @@ fn bench_eval_array_large_set(bench: &mut Bencher) {
|
|||||||
|
|
||||||
bench.iter(|| engine.consume_ast(&ast).unwrap());
|
bench.iter(|| engine.consume_ast(&ast).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[bench]
|
||||||
|
fn bench_eval_array_loop(bench: &mut Bencher) {
|
||||||
|
let script = r#"
|
||||||
|
let list = [];
|
||||||
|
|
||||||
|
for i in range(0, 10_000) {
|
||||||
|
list.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
let sum = 0;
|
||||||
|
|
||||||
|
for i in list {
|
||||||
|
sum += i;
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
engine.set_optimization_level(OptimizationLevel::None);
|
||||||
|
|
||||||
|
let ast = engine.compile(script).unwrap();
|
||||||
|
|
||||||
|
bench.iter(|| engine.consume_ast(&ast).unwrap());
|
||||||
|
}
|
||||||
|
22
scripts/for2.rhai
Normal file
22
scripts/for2.rhai
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
const MAX = 1_000_000;
|
||||||
|
|
||||||
|
print("Iterating an array with " + MAX + " items...");
|
||||||
|
|
||||||
|
print("Ready... Go!");
|
||||||
|
|
||||||
|
let now = timestamp();
|
||||||
|
|
||||||
|
let list = [];
|
||||||
|
|
||||||
|
for i in range(0, MAX) {
|
||||||
|
list.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
let sum = 0;
|
||||||
|
|
||||||
|
for i in list {
|
||||||
|
sum += i;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Sum = " + sum);
|
||||||
|
print("Finished. Run time = " + now.elapsed + " seconds.");
|
103
scripts/strings_map.rhai
Normal file
103
scripts/strings_map.rhai
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
print("Ready... Go!");
|
||||||
|
|
||||||
|
let now = timestamp();
|
||||||
|
|
||||||
|
let adverbs = [ "moderately", "really", "slightly", "very" ];
|
||||||
|
|
||||||
|
let adjectives = [
|
||||||
|
"abandoned", "able", "absolute", "academic", "acceptable", "acclaimed",
|
||||||
|
"accomplished", "accurate", "aching", "acidic", "acrobatic", "active",
|
||||||
|
"actual", "adept", "admirable", "admired", "adolescent", "adorable", "adored",
|
||||||
|
"advanced", "adventurous", "affectionate", "afraid", "aged", "aggravating",
|
||||||
|
"aggressive", "agile", "agitated", "agonizing", "agreeable", "ajar",
|
||||||
|
"alarmed", "alarming", "alert", "alienated", "alive", "all", "altruistic",
|
||||||
|
"amazing", "ambitious", "ample", "amused", "amusing", "anchored", "ancient",
|
||||||
|
"angelic", "angry", "anguished", "animated", "annual", "another", "antique",
|
||||||
|
"anxious", "any", "apprehensive", "appropriate", "apt", "arctic", "arid",
|
||||||
|
"aromatic", "artistic", "ashamed", "assured", "astonishing", "athletic",
|
||||||
|
"attached", "attentive", "attractive", "austere", "authentic", "authorized",
|
||||||
|
"automatic", "avaricious", "average", "aware", "awesome", "awful", "awkward",
|
||||||
|
"babyish", "back", "bad", "baggy", "bare", "barren", "basic", "beautiful",
|
||||||
|
"belated", "beloved", "beneficial", "best", "better", "bewitched", "big",
|
||||||
|
"big-hearted", "biodegradable", "bite-sized", "bitter", "black",
|
||||||
|
"black-and-white", "bland", "blank", "blaring", "bleak", "blind", "blissful",
|
||||||
|
"blond", "blue", "blushing", "bogus", "boiling", "bold", "bony", "boring",
|
||||||
|
"bossy", "both", "bouncy", "bountiful", "bowed", "brave", "breakable",
|
||||||
|
"brief", "bright", "brilliant", "brisk", "broken", "bronze", "brown",
|
||||||
|
"bruised", "bubbly", "bulky", "bumpy", "buoyant", "burdensome", "burly",
|
||||||
|
"bustling", "busy", "buttery", "buzzing", "calculating", "calm", "candid",
|
||||||
|
"canine", "capital", "carefree", "careful", "careless", "caring", "cautious",
|
||||||
|
"cavernous", "celebrated", "charming", "cheap", "cheerful", "cheery", "chief",
|
||||||
|
"chilly", "chubby", "circular", "classic", "clean", "clear", "clear-cut",
|
||||||
|
"clever", "close", "closed", "cloudy", "clueless", "clumsy", "cluttered",
|
||||||
|
"coarse", "cold", "colorful", "colorless", "colossal", "comfortable",
|
||||||
|
"common", "compassionate", "competent", "complete", "complex", "complicated",
|
||||||
|
"composed", "concerned", "concrete", "confused", "conscious", "considerate",
|
||||||
|
"constant", "content", "conventional", "cooked", "cool", "cooperative",
|
||||||
|
"coordinated", "corny", "corrupt", "costly", "courageous", "courteous",
|
||||||
|
"crafty"
|
||||||
|
];
|
||||||
|
|
||||||
|
let animals = [
|
||||||
|
"aardvark", "african buffalo", "albatross", "alligator", "alpaca", "ant",
|
||||||
|
"anteater", "antelope", "ape", "armadillo", "baboon", "badger", "barracuda",
|
||||||
|
"bat", "bear", "beaver", "bee", "bison", "black panther", "blue jay", "boar",
|
||||||
|
"butterfly", "camel", "capybara", "carduelis", "caribou", "cassowary", "cat",
|
||||||
|
"caterpillar", "cattle", "chamois", "cheetah", "chicken", "chimpanzee",
|
||||||
|
"chinchilla", "chough", "clam", "cobra", "cockroach", "cod", "cormorant",
|
||||||
|
"coyote", "crab", "crane", "crocodile", "crow", "curlew", "deer", "dinosaur",
|
||||||
|
"dog", "dolphin", "domestic pig", "donkey", "dotterel", "dove", "dragonfly",
|
||||||
|
"duck", "dugong", "dunlin", "eagle", "echidna", "eel", "elephant seal",
|
||||||
|
"elephant", "elk", "emu", "falcon", "ferret", "finch", "fish", "flamingo",
|
||||||
|
"fly", "fox", "frog", "gaur", "gazelle", "gerbil", "giant panda", "giraffe",
|
||||||
|
"gnat", "goat", "goldfish", "goose", "gorilla", "goshawk", "grasshopper",
|
||||||
|
"grouse", "guanaco", "guinea fowl", "guinea pig", "gull", "hamster", "hare",
|
||||||
|
"hawk", "hedgehog", "heron", "herring", "hippopotamus", "hornet", "horse",
|
||||||
|
"human", "hummingbird", "hyena", "ibex", "ibis", "jackal", "jaguar", "jay",
|
||||||
|
"jellyfish", "kangaroo", "kingfisher", "koala", "komodo dragon", "kookabura",
|
||||||
|
"kouprey", "kudu", "lapwing", "lark", "lemur", "leopard", "lion", "llama",
|
||||||
|
"lobster", "locust", "loris", "louse", "lyrebird", "magpie", "mallard",
|
||||||
|
"manatee", "mandrill", "mantis", "marten", "meerkat", "mink", "mole",
|
||||||
|
"mongoose", "monkey", "moose", "mosquito", "mouse", "mule", "narwhal", "newt",
|
||||||
|
"nightingale", "octopus", "okapi", "opossum", "oryx", "ostrich", "otter",
|
||||||
|
"owl", "oyster", "parrot", "partridge", "peafowl", "pelican", "penguin",
|
||||||
|
"pheasant", "pigeon", "pinniped", "polar bear", "pony", "porcupine",
|
||||||
|
"porpoise", "prairie dog", "quail", "quelea", "quetzal", "rabbit", "raccoon",
|
||||||
|
"ram", "rat", "raven", "red deer", "red panda", "reindeer", "rhinoceros",
|
||||||
|
"rook", "salamander", "salmon", "sand dollar", "sandpiper", "sardine",
|
||||||
|
"scorpion", "sea lion", "sea urchin", "seahorse", "shark", "sheep", "shrew",
|
||||||
|
"skunk", "snail", "snake", "sparrow", "spider", "spoonbill", "squid",
|
||||||
|
"wallaby", "wildebeest"
|
||||||
|
];
|
||||||
|
|
||||||
|
let keys = [];
|
||||||
|
|
||||||
|
for animal in animals {
|
||||||
|
for adjective in adjectives {
|
||||||
|
for adverb in adverbs {
|
||||||
|
keys.push(adverb + " " + adjective + " " + animal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let map = #{};
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
for key in keys {
|
||||||
|
map[key] = i;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sum = 0;
|
||||||
|
|
||||||
|
for key in keys {
|
||||||
|
sum += map[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
for key in keys {
|
||||||
|
map.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Sum = " + sum);
|
||||||
|
print("Finished. Run time = " + now.elapsed + " seconds.");
|
@ -385,10 +385,10 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr {
|
|||||||
// ( stmt )
|
// ( stmt )
|
||||||
stmt => Expr::Stmt(Box::new((stmt, x.1))),
|
stmt => Expr::Stmt(Box::new((stmt, x.1))),
|
||||||
},
|
},
|
||||||
// id = expr
|
// id op= expr
|
||||||
Expr::Assignment(x) => match x.2 {
|
Expr::Assignment(x) => match x.2 {
|
||||||
//id = id2 op= expr2
|
//id = id2 op= rhs
|
||||||
Expr::Assignment(x2) if x.1 == "=" => match (x.0, x2.0) {
|
Expr::Assignment(x2) if x.1.is_empty() => match (x.0, &x2.0) {
|
||||||
// var = var op= expr2 -> var op= expr2
|
// var = var op= expr2 -> var op= expr2
|
||||||
(Expr::Variable(a), Expr::Variable(b))
|
(Expr::Variable(a), Expr::Variable(b))
|
||||||
if a.1.is_none() && b.1.is_none() && a.0 == b.0 && a.3 == b.3 =>
|
if a.1.is_none() && b.1.is_none() && a.0 == b.0 && a.3 == b.3 =>
|
||||||
@ -397,14 +397,10 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr {
|
|||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
Expr::Assignment(Box::new((Expr::Variable(a), x2.1, optimize_expr(x2.2, state), x.3)))
|
Expr::Assignment(Box::new((Expr::Variable(a), x2.1, optimize_expr(x2.2, state), x.3)))
|
||||||
}
|
}
|
||||||
// id1 = id2 op= expr2
|
// expr1 = expr2 op= rhs
|
||||||
(id1, id2) => {
|
(expr1, _) => Expr::Assignment(Box::new((expr1, x.1, optimize_expr(Expr::Assignment(x2), state), x.3))),
|
||||||
Expr::Assignment(Box::new((
|
|
||||||
id1, x.1, Expr::Assignment(Box::new((id2, x2.1, optimize_expr(x2.2, state), x2.3))), x.3,
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// id op= expr
|
// expr = rhs
|
||||||
expr => Expr::Assignment(Box::new((x.0, x.1, optimize_expr(expr, state), x.3))),
|
expr => Expr::Assignment(Box::new((x.0, x.1, optimize_expr(expr, state), x.3))),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user