1) Change namespaces to iter_namespaces

2) throw can throw any value
This commit is contained in:
Stephen Chung
2020-10-20 18:09:26 +08:00
parent 09f8b13f2d
commit 5ee9dfc5cd
15 changed files with 97 additions and 69 deletions

View File

@@ -121,7 +121,7 @@ where:
* `context: &mut EvalContext` - mutable reference to the current evaluation _context_, exposing the following:
* `context.scope: &mut Scope` - mutable reference to the current [`Scope`]; variables can be added to/removed from it.
* `context.engine(): &Engine` - reference to the current [`Engine`].
* `context.namespaces(): &[&Module]` - reference to the chain of namespaces (as a slice of [modules]) containing all script-defined functions.
* `context.iter_namespaces(): impl Iterator<Item = &Module>` - iterator of the namespaces (as [modules]) containing all script-defined functions.
* `context.this_ptr(): Option<&Dynamic>` - reference to the current bound [`this`] pointer, if any.
* `context.call_level(): usize` - the current nesting level of function calls.

View File

@@ -77,7 +77,7 @@ where:
* `context: &EvalContext` - reference to the current evaluation _context_, which exposes the following fields:
* `context.scope: &Scope` - reference to the current [`Scope`] containing all variables up to the current evaluation position.
* `context.engine(): &Engine` - reference to the current [`Engine`].
* `context.namespaces(): &[&Module]` - reference to the chain of namespaces (as a slice of [modules]) containing all script-defined functions.
* `context.iter_namespaces(): impl Iterator<Item = &Module>` - iterator of the namespaces (as [modules]) containing all script-defined functions.
* `context.this_ptr(): Option<&Dynamic>` - reference to the current bound [`this`] pointer, if any.
* `context.call_level(): usize` - the current nesting level of function calls.

View File

@@ -199,9 +199,9 @@ fn call_fn_ptr_with_value(context: NativeCallContext, args: &mut [&mut Dynamic])
-> Result<Dynamic, Box<EvalAltResult>>
{
// 'args' is guaranteed to contain enough arguments of the correct types
let fp = std::mem::take(args[1]).cast::<FnPtr>(); // 2nd argument - function pointer
let value = args[2].clone(); // 3rd argument - function argument
let this_ptr = args.get_mut(0).unwrap(); // 1st argument - this pointer
let fp = std::mem::take(args[1]).cast::<FnPtr>(); // 2nd argument - function pointer
let value = args[2].clone(); // 3rd argument - function argument
let this_ptr = args.get_mut(0).unwrap(); // 1st argument - this pointer
// Use 'FnPtr::call_dynamic' to call the function pointer.
// Beware, private script-defined functions will not be found.
@@ -238,7 +238,7 @@ let engine = Engine::new();
let mut ast = engine.compile(
r#"
let test = "hello";
|x| test + x // this creates an closure
|x| test + x // this creates an closure
"#,
)?;
@@ -248,9 +248,13 @@ let fn_ptr = engine.eval_ast::<FnPtr>(&ast)?;
// Get rid of the script, retaining only functions
ast.retain_functions(|_, _, _| true);
// Create native call context via a tuple containing the Engine and the
// set of script-defined functions (within the AST) in form of a slice.
let context = (&engine, &[ast.as_ref()]).into();
// Create native call context via a tuple
let context =
(
&engine, // the 'Engine'
&[ast.as_ref()] // function namespace from the 'AST'
// as a one-element slice
).into();
// 'f' captures: the engine, the AST, and the closure
let f = move |x: i64| fn_ptr.call_dynamic(context, None, [x.into()]);

View File

@@ -10,24 +10,24 @@ To deliberately return an error during an evaluation, use the `throw` keyword.
```rust
if some_bad_condition_has_happened {
throw error; // 'throw' takes a string as the exception text
throw error; // 'throw' any value as the exception
}
throw; // defaults to empty exception text: ""
throw; // defaults to '()'
```
Exceptions thrown via `throw` in the script can be captured in Rust by matching
`Err(Box<EvalAltResult::ErrorRuntime(reason, position)>)` with the exception text
captured by `reason`.
`Err(Box<EvalAltResult::ErrorRuntime(value, position)>)` with the exception value
captured by `value`.
```rust
let result = engine.eval::<i64>(r#"
let x = 42;
if x > 0 {
throw x + " is too large!";
throw x;
}
"#);
println!(result); // prints "Runtime error: 42 is too large! (line 5, position 15)"
println!(result); // prints "Runtime error: 42 (line 5, position 15)"
```

View File

@@ -70,9 +70,8 @@ where:
* `context: NativeCallContext` - the current _native call context_, which exposes the following:
* `context.engine(): &Engine` - the current [`Engine`], with all configurations and settings.
This is sometimes useful for calling a script-defined function within the same evaluation context
using [`Engine::call_fn`][`call_fn`], or calling a [function pointer].
* `context.namespaces(): &[&Module]` - reference to the chain of namespaces (as a slice of [modules]) containing all script-defined functions.
This is sometimes useful for calling a script-defined function within the same evaluation context using [`Engine::call_fn`][`call_fn`], or calling a [function pointer].
* `context.iter_namespaces(): impl Iterator<Item = &Module>` - iterator of the namespaces (as [modules]) containing all script-defined functions.
* `args: &mut [&mut Dynamic]` - a slice containing `&mut` references to [`Dynamic`] values.
The slice is guaranteed to contain enough arguments _of the correct types_.