From 63482d5a79e99b20c99a59b795be1cb2843c20e5 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 9 Mar 2020 16:54:43 +0800 Subject: [PATCH] Use ? operator for examples. --- README.md | 117 ++++++++++++++++++++++------------------ examples/hello.rs | 12 +++-- examples/reuse_scope.rs | 16 +++--- examples/simple_fn.rs | 12 +++-- 4 files changed, 87 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 66ec3a9d..a135bcae 100644 --- a/README.md +++ b/README.md @@ -38,17 +38,11 @@ Beware that in order to use pre-releases (alpha and beta) you need to specify th Optional features ----------------- -### `debug_msgs` - -Print debug messages to stdout (using `println!`) related to function registrations and function calls. - -### `no_stdlib` - -Exclude the standard library of utility functions in the build, and only include the minimum necessary functionalities. - -### `unchecked` - -Exclude arithmetic checking in the standard library. Beware that a bad script may panic the entire system! +| Feature | Description | +| ------------ | ----------------------------------------------------------------------------------------------------------------------- | +| `debug_msgs` | Print debug messages to stdout (using `println!`) related to function registrations and function calls. | +| `no_stdlib` | Exclude the standard library of utility functions in the build, and only include the minimum necessary functionalities. | +| `unchecked` | Exclude arithmetic checking in the standard library. Beware that a bad script may panic the entire system! | Related ------- @@ -115,40 +109,48 @@ Hello world To get going with Rhai, you create an instance of the scripting engine and then run eval. ```rust -use rhai::Engine; +use rhai::{Engine, EvalAltResult}; -fn main() { +fn main() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); - if let Ok(result) = engine.eval::("40 + 2") { - println!("Answer: {}", result); // prints 42 - } + let result = engine.eval::("40 + 2")?; + + println!("Answer: {}", result); // prints 42 } ``` You can also evaluate a script file: ```rust -if let Ok(result) = engine.eval_file::("hello_world.rhai") { ... } +let result = engine.eval_file::("hello_world.rhai")?; ``` If you want to repeatedly evaluate a script, you can _compile_ it first into an AST (abstract syntax tree) form: ```rust +use rhai::Engine; + +let mut engine = Engine::new(); + // Compile to an AST and store it for later evaluations -let ast = Engine::compile("40 + 2").unwrap(); +let ast = engine.compile("40 + 2")?; for _ in 0..42 { - if let Ok(result) = engine.eval_ast::(&ast) { - println!("Answer: {}", result); // prints 42 - } + let result = engine.eval_ast::(&ast)?; + + println!("Answer: {}", result); // prints 42 } ``` Compiling a script file is also supported: ```rust -let ast = Engine::compile_file("hello_world.rhai").unwrap(); +use rhai::Engine; + +let mut engine = Engine::new(); + +let ast = engine.compile_file("hello_world.rhai").unwrap(); ``` Rhai also allows you to work _backwards_ from the other direction - i.e. calling a Rhai-scripted function from Rust. @@ -156,8 +158,12 @@ You do this via `call_fn`, which takes a compiled AST (output from `compile`) an function call arguments: ```rust +use rhai::Engine; + +let mut engine = Engine::new(); + // Define a function in a script and compile to AST -let ast = Engine::compile("fn hello(x, y) { x.len() + y }")?; +let ast = engine.compile("fn hello(x, y) { x.len() + y }")?; // Evaluate the function in the AST, passing arguments into the script as a tuple // (beware, arguments must be of the correct types because Rhai does not have built-in type conversions) @@ -212,7 +218,7 @@ Working with functions Rhai's scripting engine is very lightweight. It gets its ability from the functions in your program. To call these functions, you need to register them with the scripting engine. ```rust -use rhai::Engine; +use rhai::{Engine, EvalAltResult}; use rhai::RegisterFn; // include the `RegisterFn` trait to use `register_fn` use rhai::{Dynamic, RegisterDynamicFn}; // include the `RegisterDynamicFn` trait to use `register_dynamic_fn` @@ -226,21 +232,23 @@ fn get_an_any() -> Dynamic { Box::new(42_i64) } -fn main() { +fn main() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); engine.register_fn("add", add); - if let Ok(result) = engine.eval::("add(40, 2)") { - println!("Answer: {}", result); // prints 42 - } + let result = engine.eval::("add(40, 2)")?; + + println!("Answer: {}", result); // prints 42 // Functions that return Dynamic values must use register_dynamic_fn() engine.register_dynamic_fn("get_an_any", get_an_any); - if let Ok(result) = engine.eval::("get_an_any()") { - println!("Answer: {}", result); // prints 42 - } + let result = engine.eval::("get_an_any()")?; + + println!("Answer: {}", result); // prints 42 + + Ok(()) } ``` @@ -334,7 +342,8 @@ Custom types and methods Here's an more complete example of working with Rust. First the example, then we'll break it into parts: ```rust -use rhai::{Engine, RegisterFn}; +use rhai::{Engine, EvalAltResult}; +use rhai::RegisterFn; #[derive(Clone)] struct TestStruct { @@ -351,7 +360,7 @@ impl TestStruct { } } -fn main() { +fn main() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); engine.register_type::(); @@ -359,9 +368,11 @@ fn main() { engine.register_fn("update", TestStruct::update); engine.register_fn("new_ts", TestStruct::new); - if let Ok(result) = engine.eval::("let x = new_ts(); x.update(); x") { - println!("result: {}", result.x); // prints 1001 - } + let result = engine.eval::("let x = new_ts(); x.update(); x")?; + + println!("result: {}", result.x); // prints 1001 + + Ok(()) } ``` @@ -404,9 +415,9 @@ 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. ```rust -if let Ok(result) = engine.eval::("let x = new_ts(); x.update(); x") { - println!("result: {}", result.x); // prints 1001 -} +let result = engine.eval::("let x = new_ts(); x.update(); x")?; + +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. @@ -418,9 +429,9 @@ fn foo(ts: &mut TestStruct) -> i64 { engine.register_fn("foo", foo); -if let Ok(result) = engine.eval::("let x = new_ts(); x.foo()") { - println!("result: {}", result); // prints 1 -} +let result = engine.eval::("let x = new_ts(); x.foo()")?; + +println!("result: {}", result); // prints 1 ``` `type_of` works fine with custom types and returns the name of the type: @@ -466,9 +477,9 @@ engine.register_type::(); engine.register_get_set("x", TestStruct::get_x, TestStruct::set_x); engine.register_fn("new_ts", TestStruct::new); -if let Ok(result) = engine.eval::("let a = new_ts(); a.x = 500; a.x") { - println!("result: {}", result); -} +let result = engine.eval::("let a = new_ts(); a.x = 500; a.x")?; + +println!("result: {}", result); ``` Initializing and maintaining state @@ -479,9 +490,9 @@ By default, Rhai treats each engine invocation as a fresh one, persisting only t In this example, we first create a state with a few initialized variables, then thread the same state through multiple invocations: ```rust -use rhai::{Engine, Scope}; +use rhai::{Engine, Scope, EvalAltResult}; -fn main() { +fn main() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); // First create the state @@ -497,15 +508,17 @@ fn main() { engine.eval_with_scope::<()>(&mut scope, r" let x = 4 + 5 - y + z; y = 1; - ").expect("y and z not found?"); + ")?; // Second invocation using the same state - if let Ok(result) = engine.eval_with_scope::(&mut scope, "x") { - println!("result: {}", result); // should print 966 - } + let result = engine.eval_with_scope::(&mut scope, "x")?; + + println!("result: {}", result); // should print 966 // Variable y is changed in the script - assert_eq!(scope.get_value::("y").unwrap(), 1); + assert_eq!(scope.get_value::("y")?, 1); + + Ok(()) } ``` diff --git a/examples/hello.rs b/examples/hello.rs index cb889fe5..590074e7 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -1,9 +1,11 @@ -use rhai::Engine; +use rhai::{Engine, EvalAltResult}; -fn main() { +fn main() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); - if let Ok(result) = engine.eval::("40 + 2") { - println!("Answer: {}", result); // prints 42 - } + let result = engine.eval::("40 + 2")?; + + println!("Answer: {}", result); // prints 42 + + Ok(()) } diff --git a/examples/reuse_scope.rs b/examples/reuse_scope.rs index 071eb9f3..a6509ffe 100644 --- a/examples/reuse_scope.rs +++ b/examples/reuse_scope.rs @@ -1,14 +1,14 @@ -use rhai::{Engine, Scope}; +use rhai::{Engine, EvalAltResult, Scope}; -fn main() { +fn main() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); let mut scope = Scope::new(); - assert!(engine - .eval_with_scope::<()>(&mut scope, "let x = 4 + 5") - .is_ok()); + engine.eval_with_scope::<()>(&mut scope, "let x = 4 + 5")?; - if let Ok(result) = engine.eval_with_scope::(&mut scope, "x") { - println!("result: {}", result); - } + let result = engine.eval_with_scope::(&mut scope, "x")?; + + println!("result: {}", result); + + Ok(()) } diff --git a/examples/simple_fn.rs b/examples/simple_fn.rs index 4be5e5b6..994eb7ec 100644 --- a/examples/simple_fn.rs +++ b/examples/simple_fn.rs @@ -1,6 +1,6 @@ -use rhai::{Engine, RegisterFn}; +use rhai::{Engine, EvalAltResult, RegisterFn}; -fn main() { +fn main() -> Result<(), EvalAltResult> { let mut engine = Engine::new(); fn add(x: i64, y: i64) -> i64 { @@ -9,7 +9,9 @@ fn main() { engine.register_fn("add", add); - if let Ok(result) = engine.eval::("add(40, 2)") { - println!("Answer: {}", result); // prints 42 - } + let result = engine.eval::("add(40, 2)")?; + + println!("Answer: {}", result); // prints 42 + + Ok(()) }