Fix MarkDown style.
This commit is contained in:
parent
7893a9734b
commit
2e296ff9d7
100
README.md
100
README.md
@ -27,44 +27,51 @@ Beware that to use pre-releases (alpha and beta) you need to specify the exact v
|
|||||||
## Related
|
## Related
|
||||||
|
|
||||||
Other cool projects to check out:
|
Other cool projects to check out:
|
||||||
|
|
||||||
* [ChaiScript](http://chaiscript.com/) - A strong inspiration for Rhai. An embedded scripting language for C++ that I helped created many moons ago, now being lead by my cousin.
|
* [ChaiScript](http://chaiscript.com/) - A strong inspiration for Rhai. An embedded scripting language for C++ that I helped created many moons ago, now being lead by my cousin.
|
||||||
* You can also check out the list of [scripting languages for Rust](https://github.com/rust-unofficial/awesome-rust#scripting) on [awesome-rust](https://github.com/rust-unofficial/awesome-rust)
|
* You can also check out the list of [scripting languages for Rust](https://github.com/rust-unofficial/awesome-rust#scripting) on [awesome-rust](https://github.com/rust-unofficial/awesome-rust)
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
The repository contains several examples in the `examples` folder:
|
The repository contains several examples in the `examples` folder:
|
||||||
- `arrays_and_structs` demonstrates registering a new type to Rhai and the usage of arrays on it
|
|
||||||
- `custom_types_and_methods` shows how to register a type and methods for it
|
* `arrays_and_structs` demonstrates registering a new type to Rhai and the usage of arrays on it
|
||||||
- `hello` simple example that evaluates an expression and prints the result
|
* `custom_types_and_methods` shows how to register a type and methods for it
|
||||||
- `reuse_scope` evaluates two pieces of code in separate runs, but using a common scope
|
* `hello` simple example that evaluates an expression and prints the result
|
||||||
- `rhai_runner` runs each filename passed to it as a Rhai script
|
* `reuse_scope` evaluates two pieces of code in separate runs, but using a common scope
|
||||||
- `simple_fn` shows how to register a Rust function to a Rhai engine
|
* `rhai_runner` runs each filename passed to it as a Rhai script
|
||||||
- `repl` a simple REPL, see source code for what it can do at the moment
|
* `simple_fn` shows how to register a Rust function to a Rhai engine
|
||||||
|
* `repl` a simple REPL, see source code for what it can do at the moment
|
||||||
|
|
||||||
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 name
|
||||||
```
|
```
|
||||||
|
|
||||||
## Example Scripts
|
## Example Scripts
|
||||||
|
|
||||||
We also have a few examples scripts that showcase Rhai's features, all stored in the `scripts` folder:
|
We also have a few examples scripts that showcase Rhai's features, all stored in the `scripts` folder:
|
||||||
- `array.rhai` - arrays in Rhai
|
|
||||||
- `assignment.rhai` - variable declarations
|
* `array.rhai` - arrays in Rhai
|
||||||
- `comments.rhai` - just comments
|
* `assignment.rhai` - variable declarations
|
||||||
- `for1.rhai` - for loops
|
* `comments.rhai` - just comments
|
||||||
- `function_decl1.rhai` - a function without parameters
|
* `for1.rhai` - for loops
|
||||||
- `function_decl2.rhai` - a function with two parameters
|
* `function_decl1.rhai` - a function without parameters
|
||||||
- `function_decl3.rhai` - a function with many parameters
|
* `function_decl2.rhai` - a function with two parameters
|
||||||
- `if1.rhai` - if example
|
* `function_decl3.rhai` - a function with many parameters
|
||||||
- `loop.rhai` - endless loop in Rhai, this example emulates a do..while cycle
|
* `if1.rhai` - if example
|
||||||
- `op1.rhai` - just a simple addition
|
* `loop.rhai` - endless loop in Rhai, this example emulates a do..while cycle
|
||||||
- `op2.rhai` - simple addition and multiplication
|
* `op1.rhai` - just a simple addition
|
||||||
- `op3.rhai` - change evaluation order with parenthesis
|
* `op2.rhai` - simple addition and multiplication
|
||||||
- `speed_test.rhai` - a simple program to measure the speed of Rhai's interpreter
|
* `op3.rhai` - change evaluation order with parenthesis
|
||||||
- `string.rhai`- string operations
|
* `speed_test.rhai` - a simple program to measure the speed of Rhai's interpreter
|
||||||
- `while.rhai` - while loop
|
* `string.rhai`- string operations
|
||||||
|
* `while.rhai` - while loop
|
||||||
|
|
||||||
To run the scripts, you can either make your own tiny program, or make use of the `rhai_runner`
|
To run the scripts, you can either make your own tiny program, or make use of the `rhai_runner`
|
||||||
example program:
|
example program:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo run --example rhai_runner scripts/any_script.rhai
|
cargo run --example rhai_runner scripts/any_script.rhai
|
||||||
```
|
```
|
||||||
@ -95,7 +102,8 @@ if let Ok(result) = engine.eval_file::<i64>("hello_world.rhai") { ... }
|
|||||||
If you want to repeatedly evaluate a script, you can compile it first into an AST form:
|
If you want to repeatedly evaluate a script, you can compile it first into an AST form:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let ast = Engine::compile("40 + 2").unwrap(); // AST generated can be stored for later evaluations
|
// Compile to an AST and store it for later evaluations
|
||||||
|
let ast = Engine::compile("40 + 2").unwrap();
|
||||||
|
|
||||||
for _ in 0..42 {
|
for _ in 0..42 {
|
||||||
if let Ok(result) = engine.eval_ast::<i64>(&ast) {
|
if let Ok(result) = engine.eval_ast::<i64>(&ast) {
|
||||||
@ -116,15 +124,15 @@ Rhai's scripting engine is very lightweight. It gets its ability from the funct
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
extern crate rhai;
|
extern crate rhai;
|
||||||
use rhai::{Engine, RegisterFn};
|
use rhai::{Dynamic, Engine, RegisterFn};
|
||||||
|
|
||||||
// Normal function
|
// Normal function
|
||||||
fn add(x: i64, y: i64) -> i64 {
|
fn add(x: i64, y: i64) -> i64 {
|
||||||
x + y
|
x + y
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function that returns a dynamic value (i.e. Box<dyn Any>)
|
// Function that returns a Dynamic value
|
||||||
fn get_an_any() -> Box<dyn Any> {
|
fn get_an_any() -> Dynamic {
|
||||||
Box::new(42_i64)
|
Box::new(42_i64)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +145,8 @@ fn main() {
|
|||||||
println!("Answer: {}", result); // prints 42
|
println!("Answer: {}", result); // prints 42
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions that return dynamic values (i.e. Box<any Any>) must use register_box_fn()
|
// Functions that return Dynamic values must use register_dynamic_fn()
|
||||||
engine.register_box_fn("get_an_any", get_an_any);
|
engine.register_dynamic_fn("get_an_any", get_an_any);
|
||||||
|
|
||||||
if let Ok(result) = engine.eval::<i64>("get_an_any()") {
|
if let Ok(result) = engine.eval::<i64>("get_an_any()") {
|
||||||
println!("Answer: {}", result); // prints 42
|
println!("Answer: {}", result); // prints 42
|
||||||
@ -218,6 +226,7 @@ struct TestStruct {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Next, we create a few methods that we'll later use in our scripts. Notice that we register our custom type with the engine.
|
Next, we create a few methods that we'll later use in our scripts. Notice that we register our custom type with the engine.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl TestStruct {
|
impl TestStruct {
|
||||||
fn update(&mut self) {
|
fn update(&mut self) {
|
||||||
@ -244,12 +253,28 @@ engine.register_fn("new_ts", TestStruct::new);
|
|||||||
```
|
```
|
||||||
|
|
||||||
Finally, we call our script. The script can see the function and method we registered earlier. We need to get the result back out from script land just as before, this time casting to our custom struct type.
|
Finally, we call our script. The script can see the function and method we registered earlier. We need to get the result back out from script land just as before, this time casting to our custom struct type.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
if let Ok(result) = engine.eval::<TestStruct>("let x = new_ts(); x.update(); x") {
|
if let Ok(result) = engine.eval::<TestStruct>("let x = new_ts(); x.update(); x") {
|
||||||
println!("result: {}", result.x); // prints 1001
|
println!("result: {}", result.x); // prints 1001
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In fact, any function with a first argument (either by copy or via a `&mut` reference) can be used as a method-call on that type because internally they are the same thing: methods on a type is implemented as a functions taking an first argument.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn foo(ts: &mut TestStruct) -> i64 {
|
||||||
|
ts.x
|
||||||
|
}
|
||||||
|
|
||||||
|
engine.register_fn("foo", foo);
|
||||||
|
|
||||||
|
if let Ok(result) = engine.eval::<i64>("let x = new_ts(); x.foo()") {
|
||||||
|
println!("result: {}", result); // prints 1
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
# Getters and setters
|
# Getters and setters
|
||||||
|
|
||||||
Similarly, you can work with members of your custom types. This works by registering a 'get' or a 'set' function for working with your struct.
|
Similarly, you can work with members of your custom types. This works by registering a 'get' or a 'set' function for working with your struct.
|
||||||
@ -325,6 +350,7 @@ let x = (1 + 2) * (6 - 4) / 2;
|
|||||||
```
|
```
|
||||||
|
|
||||||
## If
|
## If
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
if true {
|
if true {
|
||||||
print("it's true!");
|
print("it's true!");
|
||||||
@ -335,6 +361,7 @@ else {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## While
|
## While
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let x = 10;
|
let x = 10;
|
||||||
while x > 0 {
|
while x > 0 {
|
||||||
@ -347,6 +374,7 @@ while x > 0 {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Loop
|
## Loop
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let x = 10;
|
let x = 10;
|
||||||
|
|
||||||
@ -379,10 +407,10 @@ fn add(x, y) {
|
|||||||
print(add(2, 3))
|
print(add(2, 3))
|
||||||
```
|
```
|
||||||
|
|
||||||
To return a dynamic value, box it and return it as `Box<dyn Any>`.
|
To return a `Dynamic` value, simply box it and return it.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn decide(yes_no: bool) -> Box<dyn Any> {
|
fn decide(yes_no: bool) -> Dynamic {
|
||||||
if yes_no {
|
if yes_no {
|
||||||
Box::new(42_i64)
|
Box::new(42_i64)
|
||||||
} else {
|
} else {
|
||||||
@ -417,11 +445,15 @@ last == 5;
|
|||||||
|
|
||||||
`push` is only defined for standard built-in types. If you want to use `push` with
|
`push` is only defined for standard built-in types. If you want to use `push` with
|
||||||
your own custom type, you need to define a specific override:
|
your own custom type, you need to define a specific override:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
engine.register_fn("push", |list: &mut Array, item: MyType| list.push(Box::new(item)));
|
engine.register_fn("push", |list: &mut rhai::Array, item: MyType| list.push(Box::new(item)));
|
||||||
```
|
```
|
||||||
|
|
||||||
## For
|
The type of a Rhai array is `rhai::Array`.
|
||||||
|
|
||||||
|
## For loops
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let array = [1, 3, 5, 7, 9, 42];
|
let array = [1, 3, 5, 7, 9, 42];
|
||||||
|
|
||||||
@ -461,6 +493,7 @@ name_and_age == "Bob C. Davis: age 42";
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Print and Debug
|
## Print and Debug
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
print("hello"); // prints hello to stdout
|
print("hello"); // prints hello to stdout
|
||||||
print(1 + 2 + 3); // prints 6 to stdout
|
print(1 + 2 + 3); // prints 6 to stdout
|
||||||
@ -468,7 +501,8 @@ print("hello" + 42); // prints hello42 to stdout
|
|||||||
debug("world!"); // prints "world!" to stdout using debug formatting
|
debug("world!"); // prints "world!" to stdout using debug formatting
|
||||||
```
|
```
|
||||||
|
|
||||||
## Overriding Print and Debug
|
### Overriding Print and Debug with Callback functions
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// Any function that takes a &str argument can be used to override print and debug
|
// Any function that takes a &str argument can be used to override print and debug
|
||||||
engine.on_print(|x: &str| println!("hello: {}", x));
|
engine.on_print(|x: &str| println!("hello: {}", x));
|
||||||
|
Loading…
Reference in New Issue
Block a user