Struct quad_compat_rhai::plugin::Engine [−][src]
pub struct Engine { /* fields omitted */ }
Expand description
Rhai main scripting engine.
Thread Safety
Engine
is re-entrant.
Currently, Engine
is neither Send
nor Sync
.
Use the sync
feature to make it Send
+
Sync
.
Example
use quad_compat_rhai::Engine;
let engine = Engine::new();
let result = engine.eval::<i64>("40 + 2")?;
println!("Answer: {}", result); // prints 42
Implementations
Evaluate a string.
Example
use quad_compat_rhai::Engine;
let engine = Engine::new();
assert_eq!(engine.eval::<i64>("40 + 2")?, 42);
pub fn eval_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope<'_>,
script: &str
) -> Result<T, Box<EvalAltResult>>
pub fn eval_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope<'_>,
script: &str
) -> Result<T, Box<EvalAltResult>>
Evaluate a string with own scope.
Constants Propagation
If not OptimizationLevel::None
, constants defined within
the scope are propagated throughout the script including functions. This allows functions
to be optimized based on dynamic global constants.
Example
use quad_compat_rhai::{Engine, Scope};
let engine = Engine::new();
// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 40_i64);
assert_eq!(engine.eval_with_scope::<i64>(&mut scope, "x += 2; x")?, 42);
assert_eq!(engine.eval_with_scope::<i64>(&mut scope, "x += 2; x")?, 44);
// The variable in the scope is modified
assert_eq!(scope.get_value::<i64>("x").expect("variable x should exist"), 44);
pub fn eval_expression<T: Variant + Clone>(
&self,
script: &str
) -> Result<T, Box<EvalAltResult>>
pub fn eval_expression<T: Variant + Clone>(
&self,
script: &str
) -> Result<T, Box<EvalAltResult>>
Evaluate a string containing an expression.
Example
use quad_compat_rhai::Engine;
let engine = Engine::new();
assert_eq!(engine.eval_expression::<i64>("40 + 2")?, 42);
pub fn eval_expression_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope<'_>,
script: &str
) -> Result<T, Box<EvalAltResult>>
pub fn eval_expression_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope<'_>,
script: &str
) -> Result<T, Box<EvalAltResult>>
Evaluate a string containing an expression with own scope.
Example
use quad_compat_rhai::{Engine, Scope};
let engine = Engine::new();
// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 40_i64);
assert_eq!(engine.eval_expression_with_scope::<i64>(&mut scope, "x + 2")?, 42);
pub fn eval_ast_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope<'_>,
ast: &AST
) -> Result<T, Box<EvalAltResult>>
pub fn eval_ast_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope<'_>,
ast: &AST
) -> Result<T, Box<EvalAltResult>>
Evaluate an AST
with own scope.
Example
use quad_compat_rhai::{Engine, Scope};
let engine = Engine::new();
// Compile a script to an AST and store it for later evaluation
let ast = engine.compile("x + 2")?;
// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 40_i64);
// Compile a script to an AST and store it for later evaluation
let ast = engine.compile("x += 2; x")?;
// Evaluate it
assert_eq!(engine.eval_ast_with_scope::<i64>(&mut scope, &ast)?, 42);
assert_eq!(engine.eval_ast_with_scope::<i64>(&mut scope, &ast)?, 44);
// The variable in the scope is modified
assert_eq!(scope.get_value::<i64>("x").expect("variable x should exist"), 44);
Evaluate a script, returning any error (if any).
pub fn run_with_scope(
&self,
scope: &mut Scope<'_>,
script: &str
) -> Result<(), Box<EvalAltResult>>
pub fn run_with_scope(
&self,
scope: &mut Scope<'_>,
script: &str
) -> Result<(), Box<EvalAltResult>>
Evaluate a script with own scope, returning any error (if any).
Constants Propagation
If not OptimizationLevel::None
, constants defined within
the scope are propagated throughout the script including functions. This allows functions
to be optimized based on dynamic global constants.
Evaluate an AST
, returning any error (if any).
pub fn run_ast_with_scope(
&self,
scope: &mut Scope<'_>,
ast: &AST
) -> Result<(), Box<EvalAltResult>>
pub fn run_ast_with_scope(
&self,
scope: &mut Scope<'_>,
ast: &AST
) -> Result<(), Box<EvalAltResult>>
Evaluate an AST
with own scope, returning any error (if any).
Compile a string into an AST
, which can be used later for evaluation.
Example
use quad_compat_rhai::Engine;
let engine = Engine::new();
// Compile a script to an AST and store it for later evaluation
let ast = engine.compile("40 + 2")?;
for _ in 0..42 {
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
}
pub fn compile_with_scope(
&self,
scope: &Scope<'_>,
script: impl AsRef<str>
) -> Result<AST, ParseError>
pub fn compile_with_scope(
&self,
scope: &Scope<'_>,
script: impl AsRef<str>
) -> Result<AST, ParseError>
Compile a string into an AST
using own scope, which can be used later for evaluation.
Constants Propagation
If not OptimizationLevel::None
, constants defined within
the scope are propagated throughout the script including functions. This allows functions
to be optimized based on dynamic global constants.
Example
use quad_compat_rhai::{Engine, Scope, OptimizationLevel};
let mut engine = Engine::new();
// Create initialized scope
let mut scope = Scope::new();
scope.push_constant("x", 42_i64); // 'x' is a constant
// Compile a script to an AST and store it for later evaluation.
// Notice that `Full` optimization is on, so constants are folded
// into function calls and operators.
let ast = engine.compile_with_scope(&mut scope,
"if x > 40 { x } else { 0 }" // all 'x' are replaced with 42
)?;
// Normally this would have failed because no scope is passed into the 'eval_ast'
// call and so the variable 'x' does not exist. Here, it passes because the script
// has been optimized and all references to 'x' are already gone.
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
pub fn compile_into_self_contained(
&self,
scope: &Scope<'_>,
script: impl AsRef<str>
) -> Result<AST, Box<EvalAltResult>>
pub fn compile_into_self_contained(
&self,
scope: &Scope<'_>,
script: impl AsRef<str>
) -> Result<AST, Box<EvalAltResult>>
Compile a string into an AST
using own scope, which can be used later for evaluation,
embedding all imported modules.
Not available under no_module
.
Modules referred by import
statements containing literal string paths are eagerly resolved
via the current module resolver and embedded into the resultant
AST
. When it is evaluated later, import
statement directly recall pre-resolved
modules and the resolution process is not performed again.
pub fn compile_scripts_with_scope(
&self,
scope: &Scope<'_>,
scripts: &[impl AsRef<str>]
) -> Result<AST, ParseError>
pub fn compile_scripts_with_scope(
&self,
scope: &Scope<'_>,
scripts: &[impl AsRef<str>]
) -> Result<AST, ParseError>
When passed a list of strings, first join the strings into one large script, and then
compile them into an AST
using own scope, which can be used later for evaluation.
The scope is useful for passing constants into the script for optimization when using
OptimizationLevel::Full
.
Note
All strings are simply parsed one after another with nothing inserted in between, not even a newline or space.
Constants Propagation
If not OptimizationLevel::None
, constants defined within
the scope are propagated throughout the script including functions. This allows functions
to be optimized based on dynamic global constants.
Example
use quad_compat_rhai::{Engine, Scope, OptimizationLevel};
let mut engine = Engine::new();
// Create initialized scope
let mut scope = Scope::new();
scope.push_constant("x", 42_i64); // 'x' is a constant
// Compile a script made up of script segments to an AST and store it for later evaluation.
// Notice that `Full` optimization is on, so constants are folded
// into function calls and operators.
let ast = engine.compile_scripts_with_scope(&mut scope, &[
"if x > 40", // all 'x' are replaced with 42
"{ x } el",
"se { 0 }" // segments do not need to be valid scripts!
])?;
// Normally this would have failed because no scope is passed into the 'eval_ast'
// call and so the variable 'x' does not exist. Here, it passes because the script
// has been optimized and all references to 'x' are already gone.
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
Compile a string containing an expression into an AST
,
which can be used later for evaluation.
Example
use quad_compat_rhai::Engine;
let engine = Engine::new();
// Compile a script to an AST and store it for later evaluation
let ast = engine.compile_expression("40 + 2")?;
for _ in 0..42 {
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
}
pub fn compile_expression_with_scope(
&self,
scope: &Scope<'_>,
script: impl AsRef<str>
) -> Result<AST, ParseError>
pub fn compile_expression_with_scope(
&self,
scope: &Scope<'_>,
script: impl AsRef<str>
) -> Result<AST, ParseError>
Compile a string containing an expression into an AST
using own scope,
which can be used later for evaluation.
Example
use quad_compat_rhai::{Engine, Scope, OptimizationLevel};
let mut engine = Engine::new();
// Create initialized scope
let mut scope = Scope::new();
scope.push_constant("x", 10_i64); // 'x' is a constant
// Compile a script to an AST and store it for later evaluation.
// Notice that `Full` optimization is on, so constants are folded
// into function calls and operators.
let ast = engine.compile_expression_with_scope(&mut scope,
"2 + (x + x) * 2" // all 'x' are replaced with 10
)?;
// Normally this would have failed because no scope is passed into the 'eval_ast'
// call and so the variable 'x' does not exist. Here, it passes because the script
// has been optimized and all references to 'x' are already gone.
assert_eq!(engine.eval_ast::<i64>(&ast)?, 42);
pub fn parse_json(
&self,
json: impl AsRef<str>,
has_null: bool
) -> Result<Map, Box<EvalAltResult>>
pub fn parse_json(
&self,
json: impl AsRef<str>,
has_null: bool
) -> Result<Map, Box<EvalAltResult>>
Parse a JSON string into an object map.
This is a light-weight alternative to using, say,
serde_json
to deserialize the JSON.
Not available under no_object
.
The JSON string must be an object hash. It cannot be a simple scalar value.
Set has_null
to true
in order to map null
values to ()
.
Setting it to false
will cause an ErrorVariableNotFound
error during parsing.
JSON With Sub-Objects
This method assumes no sub-objects in the JSON string. That is because the syntax
of a JSON sub-object (or object hash), { .. }
, is different from Rhai’s syntax, #{ .. }
.
Parsing a JSON string with sub-objects will cause a syntax error.
If it is certain that the character {
never appears in any text string within the JSON object,
which is a valid assumption for many use cases, then globally replace {
with #{
before calling this method.
Example
use quad_compat_rhai::{Engine, Map};
let engine = Engine::new();
let map = engine.parse_json(
r#"{"a":123, "b":42, "c":{"x":false, "y":true}, "d":null}"#
.replace("{", "#{").as_str(),
true)?;
assert_eq!(map.len(), 4);
assert_eq!(map["a"].as_int().expect("a should exist"), 123);
assert_eq!(map["b"].as_int().expect("b should exist"), 42);
assert!(map["d"].is::<()>());
let c = map["c"].read_lock::<Map>().expect("c should exist");
assert_eq!(c["x"].as_bool().expect("x should be bool"), false);
Compile a script file into an AST
, which can be used later for evaluation.
Not available under no_std
or WASM
.
Example
use quad_compat_rhai::Engine;
let engine = Engine::new();
// Compile a script file to an AST and store it for later evaluation.
// Notice that a PathBuf is required which can easily be constructed from a string.
let ast = engine.compile_file("script.rhai".into())?;
for _ in 0..42 {
engine.eval_ast::<i64>(&ast)?;
}
pub fn compile_file_with_scope(
&self,
scope: &Scope<'_>,
path: PathBuf
) -> Result<AST, Box<EvalAltResult>>
pub fn compile_file_with_scope(
&self,
scope: &Scope<'_>,
path: PathBuf
) -> Result<AST, Box<EvalAltResult>>
Compile a script file into an AST
using own scope, which can be used later for evaluation.
Not available under no_std
or WASM
.
Constants Propagation
If not OptimizationLevel::None
, constants defined within
the scope are propagated throughout the script including functions. This allows functions
to be optimized based on dynamic global constants.
Example
use quad_compat_rhai::{Engine, Scope, OptimizationLevel};
let mut engine = Engine::new();
// Create initialized scope
let mut scope = Scope::new();
scope.push_constant("x", 42_i64); // 'x' is a constant
// Compile a script to an AST and store it for later evaluation.
// Notice that a PathBuf is required which can easily be constructed from a string.
let ast = engine.compile_file_with_scope(&mut scope, "script.rhai".into())?;
let result = engine.eval_ast::<i64>(&ast)?;
Evaluate a script file.
Not available under no_std
or WASM
.
Example
use quad_compat_rhai::Engine;
let engine = Engine::new();
// Notice that a PathBuf is required which can easily be constructed from a string.
let result = engine.eval_file::<i64>("script.rhai".into())?;
pub fn eval_file_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope<'_>,
path: PathBuf
) -> Result<T, Box<EvalAltResult>>
pub fn eval_file_with_scope<T: Variant + Clone>(
&self,
scope: &mut Scope<'_>,
path: PathBuf
) -> Result<T, Box<EvalAltResult>>
Evaluate a script file with own scope.
Not available under no_std
or WASM
.
Constants Propagation
If not OptimizationLevel::None
, constants defined within
the scope are propagated throughout the script including functions. This allows functions
to be optimized based on dynamic global constants.
Example
use quad_compat_rhai::{Engine, Scope};
let engine = Engine::new();
// Create initialized scope
let mut scope = Scope::new();
scope.push("x", 42_i64);
// Notice that a PathBuf is required which can easily be constructed from a string.
let result = engine.eval_file_with_scope::<i64>(&mut scope, "script.rhai".into())?;
Evaluate a file, returning any error (if any).
Not available under no_std
or WASM
.
pub fn run_file_with_scope(
&self,
scope: &mut Scope<'_>,
path: PathBuf
) -> Result<(), Box<EvalAltResult>>
pub fn run_file_with_scope(
&self,
scope: &mut Scope<'_>,
path: PathBuf
) -> Result<(), Box<EvalAltResult>>
Evaluate a file with own scope, returning any error (if any).
Not available under no_std
or WASM
.
Constants Propagation
If not OptimizationLevel::None
, constants defined within
the scope are propagated throughout the script including functions. This allows functions
to be optimized based on dynamic global constants.
pub fn register_fn<N, A, F>(&mut self, name: N, func: F) -> &mut Self where
N: AsRef<str> + Into<Identifier>,
F: RegisterNativeFunction<A, ()>,
pub fn register_fn<N, A, F>(&mut self, name: N, func: F) -> &mut Self where
N: AsRef<str> + Into<Identifier>,
F: RegisterNativeFunction<A, ()>,
Register a custom function with the Engine
.
Example
use quad_compat_rhai::Engine;
// Normal function
fn add(x: i64, y: i64) -> i64 {
x + y
}
let mut engine = Engine::new();
engine.register_fn("add", add);
assert_eq!(engine.eval::<i64>("add(40, 2)")?, 42);
// You can also register a closure.
engine.register_fn("sub", |x: i64, y: i64| x - y );
assert_eq!(engine.eval::<i64>("sub(44, 2)")?, 42);
pub fn register_result_fn<N, A, F, R>(&mut self, name: N, func: F) -> &mut Self where
N: AsRef<str> + Into<Identifier>,
F: RegisterNativeFunction<A, Result<R, Box<EvalAltResult>>>,
pub fn register_result_fn<N, A, F, R>(&mut self, name: N, func: F) -> &mut Self where
N: AsRef<str> + Into<Identifier>,
F: RegisterNativeFunction<A, Result<R, Box<EvalAltResult>>>,
Register a custom fallible function with the Engine
.
Example
use quad_compat_rhai::{Engine, EvalAltResult};
// Normal function
fn div(x: i64, y: i64) -> Result<i64, Box<EvalAltResult>> {
if y == 0 {
// '.into()' automatically converts to 'Box<EvalAltResult::ErrorRuntime>'
Err("division by zero!".into())
} else {
Ok(x / y)
}
}
let mut engine = Engine::new();
engine.register_result_fn("div", div);
engine.eval::<i64>("div(42, 0)")
.expect_err("expecting division by zero error!");
pub fn register_raw_fn<N, T>(
&mut self,
name: N,
arg_types: &[TypeId],
func: impl Fn(NativeCallContext<'_>, &mut [&'_ mut Dynamic]) -> Result<T, Box<EvalAltResult>> + SendSync + 'static
) -> &mut Self where
N: AsRef<str> + Into<Identifier>,
T: Variant + Clone,
pub fn register_raw_fn<N, T>(
&mut self,
name: N,
arg_types: &[TypeId],
func: impl Fn(NativeCallContext<'_>, &mut [&'_ mut Dynamic]) -> Result<T, Box<EvalAltResult>> + SendSync + 'static
) -> &mut Self where
N: AsRef<str> + Into<Identifier>,
T: Variant + Clone,
Register a function of the Engine
.
WARNING - Low Level API
This function is very low level. It takes a list of TypeId
’s
indicating the actual types of the parameters.
Arguments
Arguments are simply passed in as a mutable array of &mut Dynamic
.
The arguments are guaranteed to be of the correct types matching the TypeId
’s.
To access a primary argument value (i.e. cloning is cheap), use: args[n].as_xxx().unwrap()
To access an argument value and avoid cloning, use std::mem::take(args[n]).cast::<T>()
.
Notice that this will consume the argument, replacing it with ()
.
To access the first mutable parameter, use args.get_mut(0).unwrap()
Register a custom type for use with the Engine
.
The type must implement Clone
.
Example
#[derive(Debug, Clone, Eq, PartialEq)]
struct TestStruct {
field: i64
}
impl TestStruct {
fn new() -> Self { Self { field: 1 } }
fn update(&mut self, offset: i64) { self.field += offset; }
}
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register API for the custom type.
engine
.register_type::<TestStruct>()
.register_fn("new_ts", TestStruct::new)
// Use `register_fn` to register methods on the type.
.register_fn("update", TestStruct::update);
assert_eq!(
engine.eval::<TestStruct>("let x = new_ts(); x.update(41); x")?,
TestStruct { field: 42 }
);
Register a custom type for use with the Engine
, with a pretty-print name
for the type_of
function. The type must implement Clone
.
Example
#[derive(Clone)]
struct TestStruct {
field: i64
}
impl TestStruct {
fn new() -> Self { Self { field: 1 } }
}
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register API for the custom type.
engine
.register_type::<TestStruct>()
.register_fn("new_ts", TestStruct::new);
assert_eq!(
engine.eval::<String>("let x = new_ts(); type_of(x)")?,
"rust_out::TestStruct"
);
// Re-register the custom type with a name.
engine.register_type_with_name::<TestStruct>("Hello");
assert_eq!(
engine.eval::<String>("let x = new_ts(); type_of(x)")?,
"Hello"
);
pub fn register_type_with_name_raw(
&mut self,
fully_qualified_type_path: impl Into<SmartString<LazyCompact>>,
name: impl Into<SmartString<LazyCompact>>
) -> &mut Self
pub fn register_type_with_name_raw(
&mut self,
fully_qualified_type_path: impl Into<SmartString<LazyCompact>>,
name: impl Into<SmartString<LazyCompact>>
) -> &mut Self
Register a custom type for use with the Engine
, with a pretty-print name
for the type_of
function. The type must implement Clone
.
WARNING - Low Level API
This function is low level.
pub fn register_iterator<T>(&mut self) -> &mut Self where
T: Variant + Clone + IntoIterator,
<T as IntoIterator>::Item: Variant + Clone,
pub fn register_iterator<T>(&mut self) -> &mut Self where
T: Variant + Clone + IntoIterator,
<T as IntoIterator>::Item: Variant + Clone,
Register an type iterator for an iterable type with the Engine
.
This is an advanced feature.
Register a getter function for a member of a registered type with the Engine
.
The function signature must start with &mut self
and not &self
.
Not available under no_object
.
Example
#[derive(Clone)]
struct TestStruct {
field: i64
}
impl TestStruct {
fn new() -> Self { Self { field: 1 } }
// Even a getter must start with `&mut self` and not `&self`.
fn get_field(&mut self) -> i64 { self.field }
}
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register API for the custom type.
engine
.register_type::<TestStruct>()
.register_fn("new_ts", TestStruct::new)
// Register a getter on a property (notice it doesn't have to be the same name).
.register_get("xyz", TestStruct::get_field);
assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz")?, 1);
Register a getter function for a member of a registered type with the Engine
.
The function signature must start with &mut self
and not &self
.
Not available under no_object
.
Example
use quad_compat_rhai::{Engine, Dynamic, EvalAltResult};
#[derive(Clone)]
struct TestStruct {
field: i64
}
impl TestStruct {
fn new() -> Self { Self { field: 1 } }
// Even a getter must start with `&mut self` and not `&self`.
fn get_field(&mut self) -> Result<i64, Box<EvalAltResult>> {
Ok(self.field)
}
}
let mut engine = Engine::new();
// Register API for the custom type.
engine
.register_type::<TestStruct>()
.register_fn("new_ts", TestStruct::new)
// Register a getter on a property (notice it doesn't have to be the same name).
.register_get_result("xyz", TestStruct::get_field);
assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz")?, 1);
Register a setter function for a member of a registered type with the Engine
.
Not available under no_object
.
Example
#[derive(Debug, Clone, Eq, PartialEq)]
struct TestStruct {
field: i64
}
impl TestStruct {
fn new() -> Self { Self { field: 1 } }
fn set_field(&mut self, new_val: i64) { self.field = new_val; }
}
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register API for the custom type.
engine
.register_type::<TestStruct>()
.register_fn("new_ts", TestStruct::new)
// Register a setter on a property (notice it doesn't have to be the same name)
.register_set("xyz", TestStruct::set_field);
// Notice that, with a getter, there is no way to get the property value
assert_eq!(
engine.eval::<TestStruct>("let a = new_ts(); a.xyz = 42; a")?,
TestStruct { field: 42 }
);
Register a setter function for a member of a registered type with the Engine
.
Not available under no_object
.
Example
use quad_compat_rhai::{Engine, Dynamic, EvalAltResult};
#[derive(Debug, Clone, Eq, PartialEq)]
struct TestStruct {
field: i64
}
impl TestStruct {
fn new() -> Self { Self { field: 1 } }
fn set_field(&mut self, new_val: i64) -> Result<(), Box<EvalAltResult>> {
self.field = new_val;
Ok(())
}
}
let mut engine = Engine::new();
// Register API for the custom type.
engine
.register_type::<TestStruct>()
.register_fn("new_ts", TestStruct::new)
// Register a setter on a property (notice it doesn't have to be the same name)
.register_set_result("xyz", TestStruct::set_field);
// Notice that, with a getter, there is no way to get the property value
assert_eq!(
engine.eval::<TestStruct>("let a = new_ts(); a.xyz = 42; a")?,
TestStruct { field: 42 }
);
Short-hand for registering both getter and setter functions
of a registered type with the Engine
.
All function signatures must start with &mut self
and not &self
.
Not available under no_object
.
Example
#[derive(Clone)]
struct TestStruct {
field: i64
}
impl TestStruct {
fn new() -> Self { Self { field: 1 } }
// Even a getter must start with `&mut self` and not `&self`.
fn get_field(&mut self) -> i64 { self.field }
fn set_field(&mut self, new_val: i64) { self.field = new_val; }
}
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register API for the custom type.
engine
.register_type::<TestStruct>()
.register_fn("new_ts", TestStruct::new)
// Register both a getter and a setter on a property
// (notice it doesn't have to be the same name)
.register_get_set("xyz", TestStruct::get_field, TestStruct::set_field);
assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz = 42; a.xyz")?, 42);
Register an index getter for a custom type with the Engine
.
The function signature must start with &mut self
and not &self
.
Not available under both no_index
and no_object
.
Panics
Panics if the type is Array
, Map
, String
,
ImmutableString
, &str
or INT
.
Indexers for arrays, object maps, strings and integers cannot be registered.
Example
#[derive(Clone)]
struct TestStruct {
fields: Vec<i64>
}
impl TestStruct {
fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
// Even a getter must start with `&mut self` and not `&self`.
fn get_field(&mut self, index: i64) -> i64 { self.fields[index as usize] }
}
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register API for the custom type.
engine.register_type::<TestStruct>();
engine
.register_fn("new_ts", TestStruct::new)
// Register an indexer.
.register_indexer_get(TestStruct::get_field);
assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2]")?, 3);
Register an index getter for a custom type with the Engine
.
The function signature must start with &mut self
and not &self
.
Not available under both no_index
and no_object
.
Panics
Panics if the type is Array
, Map
, String
,
ImmutableString
, &str
or INT
.
Indexers for arrays, object maps, strings and integers cannot be registered.
Example
use quad_compat_rhai::{Engine, Dynamic, EvalAltResult};
#[derive(Clone)]
struct TestStruct {
fields: Vec<i64>
}
impl TestStruct {
fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
// Even a getter must start with `&mut self` and not `&self`.
fn get_field(&mut self, index: i64) -> Result<i64, Box<EvalAltResult>> {
Ok(self.fields[index as usize])
}
}
let mut engine = Engine::new();
// Register API for the custom type.
engine.register_type::<TestStruct>();
engine
.register_fn("new_ts", TestStruct::new)
// Register an indexer.
.register_indexer_get_result(TestStruct::get_field);
assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2]")?, 3);
Register an index setter for a custom type with the Engine
.
Not available under both no_index
and no_object
.
Panics
Panics if the type is Array
, Map
, String
,
ImmutableString
, &str
or INT
.
Indexers for arrays, object maps, strings and integers cannot be registered.
Example
#[derive(Clone)]
struct TestStruct {
fields: Vec<i64>
}
impl TestStruct {
fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
fn set_field(&mut self, index: i64, value: i64) { self.fields[index as usize] = value; }
}
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register API for the custom type.
engine.register_type::<TestStruct>();
engine
.register_fn("new_ts", TestStruct::new)
// Register an indexer.
.register_indexer_set(TestStruct::set_field);
assert_eq!(
engine.eval::<TestStruct>("let a = new_ts(); a[2] = 42; a")?.fields[2],
42
);
Register an index setter for a custom type with the Engine
.
Not available under both no_index
and no_object
.
Panics
Panics if the type is Array
, Map
, String
,
ImmutableString
, &str
or INT
.
Indexers for arrays, object maps, strings and integers cannot be registered.
Example
use quad_compat_rhai::{Engine, Dynamic, EvalAltResult};
#[derive(Clone)]
struct TestStruct {
fields: Vec<i64>
}
impl TestStruct {
fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
fn set_field(&mut self, index: i64, value: i64) -> Result<(), Box<EvalAltResult>> {
self.fields[index as usize] = value;
Ok(())
}
}
let mut engine = Engine::new();
// Register API for the custom type.
engine.register_type::<TestStruct>();
engine
.register_fn("new_ts", TestStruct::new)
// Register an indexer.
.register_indexer_set_result(TestStruct::set_field);
assert_eq!(
engine.eval::<TestStruct>("let a = new_ts(); a[2] = 42; a")?.fields[2],
42
);
Short-hand for registering both index getter and setter functions for a custom type with the Engine
.
Not available under both no_index
and no_object
.
Panics
Panics if the type is Array
, Map
, String
,
ImmutableString
, &str
or INT
.
Indexers for arrays, object maps, strings and integers cannot be registered.
Example
#[derive(Clone)]
struct TestStruct {
fields: Vec<i64>
}
impl TestStruct {
fn new() -> Self { Self { fields: vec![1, 2, 3, 4, 5] } }
// Even a getter must start with `&mut self` and not `&self`.
fn get_field(&mut self, index: i64) -> i64 { self.fields[index as usize] }
fn set_field(&mut self, index: i64, value: i64) { self.fields[index as usize] = value; }
}
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register API for the custom type.
engine.register_type::<TestStruct>();
engine
.register_fn("new_ts", TestStruct::new)
// Register an indexer.
.register_indexer_get_set(TestStruct::get_field, TestStruct::set_field);
assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2] = 42; a[2]")?, 42);
Register a shared Module
into the global namespace of Engine
.
All functions and type iterators are automatically available to scripts without namespace qualifications.
Sub-modules and variables are ignored.
When searching for functions, modules loaded later are preferred. In other words, loaded modules are searched in reverse order.
pub fn register_static_module(
&mut self,
name: impl AsRef<str> + Into<Identifier>,
module: Shared<Module>
) -> &mut Self
pub fn register_static_module(
&mut self,
name: impl AsRef<str> + Into<Identifier>,
module: Shared<Module>
) -> &mut Self
Register a shared Module
as a static module namespace with the Engine
.
Functions marked FnNamespace::Global
and type iterators are exposed to scripts without
namespace qualifications.
Not available under no_module
.
Example
use quad_compat_rhai::{Engine, Shared, Module};
let mut engine = Engine::new();
// Create the module
let mut module = Module::new();
module.set_native_fn("calc", |x: i64| Ok(x + 1));
let module: Shared<Module> = module.into();
engine
// Register the module as a fixed sub-module
.register_static_module("foo::bar::baz", module.clone())
// Multiple registrations to the same partial path is also OK!
.register_static_module("foo::bar::hello", module.clone())
.register_static_module("CalcService", module);
assert_eq!(engine.eval::<i64>("foo::bar::baz::calc(41)")?, 42);
assert_eq!(engine.eval::<i64>("foo::bar::hello::calc(41)")?, 42);
assert_eq!(engine.eval::<i64>("CalcService::calc(41)")?, 42);
(metadata) Generate a list of all registered functions.
Exported under the metadata
feature only.
Functions from the following sources are included, in order:
- Functions registered into the global namespace
- Functions in registered sub-modules
- Functions in packages (optional)
Call a script function defined in an AST
with multiple arguments.
Not available under no_function
.
The AST
is evaluated before calling the function.
This allows a script to load the necessary modules.
This is usually desired. If not, a specialized AST
can be prepared that contains only
function definitions without any body script via AST::clear_statements
.
Example
use quad_compat_rhai::{Engine, Scope};
let engine = Engine::new();
let ast = engine.compile("
fn add(x, y) { len(x) + y + foo }
fn add1(x) { len(x) + 1 + foo }
fn bar() { foo/2 }
")?;
let mut scope = Scope::new();
scope.push("foo", 42_i64);
// Call the script-defined function
let result: i64 = engine.call_fn(&mut scope, &ast, "add", ( "abc", 123_i64 ) )?;
assert_eq!(result, 168);
let result: i64 = engine.call_fn(&mut scope, &ast, "add1", ( "abc", ) )?;
// ^^^^^^^^^^ tuple of one
assert_eq!(result, 46);
let result: i64 = engine.call_fn(&mut scope, &ast, "bar", () )?;
assert_eq!(result, 21);
Call a script function defined in an AST
with multiple Dynamic
arguments
and the following options:
- whether to evaluate the
AST
to load necessary modules before calling the function - whether to rewind the
Scope
after the function call - a value for binding to the
this
pointer (if any)
Not available under no_function
.
WARNING - Low Level API
This function is very low level.
Arguments
All the arguments are consumed, meaning that they’re replaced by ()
.
This is to avoid unnecessarily cloning the arguments.
Do not use the arguments after this call. If they are needed afterwards,
clone them before calling this function.
Example
use quad_compat_rhai::{Engine, Scope, Dynamic};
let engine = Engine::new();
let ast = engine.compile("
fn add(x, y) { len(x) + y + foo }
fn add1(x) { len(x) + 1 + foo }
fn bar() { foo/2 }
fn action(x) { this += x; } // function using 'this' pointer
fn decl(x) { let hello = x; } // declaring variables
")?;
let mut scope = Scope::new();
scope.push("foo", 42_i64);
// Call the script-defined function
let result = engine.call_fn_raw(&mut scope, &ast, true, true, "add", None, [ "abc".into(), 123_i64.into() ])?;
// ^^^^ no 'this' pointer
assert_eq!(result.cast::<i64>(), 168);
let result = engine.call_fn_raw(&mut scope, &ast, true, true, "add1", None, [ "abc".into() ])?;
assert_eq!(result.cast::<i64>(), 46);
let result = engine.call_fn_raw(&mut scope, &ast, true, true, "bar", None, [])?;
assert_eq!(result.cast::<i64>(), 21);
let mut value: Dynamic = 1_i64.into();
let result = engine.call_fn_raw(&mut scope, &ast, true, true, "action", Some(&mut value), [ 41_i64.into() ])?;
// ^^^^^^^^^^^^^^^^ binding the 'this' pointer
assert_eq!(value.as_int().expect("value should be INT"), 42);
engine.call_fn_raw(&mut scope, &ast, true, false, "decl", None, [ 42_i64.into() ])?;
// ^^^^^ do not rewind scope
assert_eq!(scope.get_value::<i64>("hello").unwrap(), 42);
Is if
-expression allowed?
Set whether if
-expression is allowed.
Is switch
expression allowed?
Set whether switch
expression is allowed.
Is statement-expression allowed?
Set whether statement-expression is allowed.
Is anonymous function allowed?
Not available under no_function
.
Set whether anonymous function is allowed.
Not available under no_function
.
Is looping allowed?
Set whether looping is allowed.
Is strict variables mode enabled?
Set whether strict variables mode is enabled.
Set the maximum levels of function calls allowed for a script in order to avoid infinite recursion and stack overflows.
Not available under unchecked
or no_function
.
The maximum levels of function calls allowed for a script.
Not available under unchecked
or no_function
.
Set the maximum number of operations allowed for a script to run to avoid consuming too much resources (0 for unlimited).
Not available under unchecked
.
The maximum number of operations allowed for a script to run (0 for unlimited).
Not available under unchecked
.
Set the maximum number of imported modules allowed for a script.
Not available under unchecked
or no_module
.
The maximum number of imported modules allowed for a script.
Not available under unchecked
or no_module
.
pub fn set_max_expr_depths(
&mut self,
max_expr_depth: usize,
max_function_expr_depth: usize
) -> &mut Self
pub fn set_max_expr_depths(
&mut self,
max_expr_depth: usize,
max_function_expr_depth: usize
) -> &mut Self
Set the depth limits for expressions (0 for unlimited).
Not available under unchecked
.
The depth limit for expressions (0 for unlimited).
Not available under unchecked
.
The depth limit for expressions in functions (0 for unlimited).
Not available under unchecked
or no_function
.
Set the maximum length of strings (0 for unlimited).
Not available under unchecked
.
The maximum length of strings (0 for unlimited).
Not available under unchecked
.
Set the maximum length of arrays (0 for unlimited).
Not available under unchecked
or no_index
.
The maximum length of arrays (0 for unlimited).
Not available under unchecked
or no_index
.
Set the maximum size of object maps (0 for unlimited).
Not available under unchecked
or no_object
.
The maximum size of object maps (0 for unlimited).
Not available under unchecked
or no_object
.
Provide a callback that will be invoked before each variable access.
Callback Function Signature
The callback function signature takes the following form:
Fn(name: &str, index: usize, context: &EvalContext)
-> Result<Option<Dynamic>, Box<EvalAltResult>> + 'static
where:
-
index
: an offset from the bottom of the currentScope
that the variable is supposed to reside. Offsets start from 1, with 1 meaning the last variable in the currentScope
. Essentially the correct variable is at positionscope.len() - index
. Ifindex
is zero, then there is no pre-calculated offset position and a search through the currentScope
must be performed. -
context
: the current evaluation context.
Return value
Ok(None)
: continue with normal variable access.Ok(Some(Dynamic))
: the variable’s value.
Raising errors
Return Err(...)
if there is an error.
Example
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register a variable resolver.
engine.on_var(|name, _, _| {
match name {
"MYSTIC_NUMBER" => Ok(Some(42_i64.into())),
_ => Ok(None)
}
});
engine.eval::<i64>("MYSTIC_NUMBER")?;
pub fn on_parse_token(
&mut self,
callback: impl Fn(Token, Position, &TokenizeState) -> Token + SendSync + 'static
) -> &mut Self
pub fn on_parse_token(
&mut self,
callback: impl Fn(Token, Position, &TokenizeState) -> Token + SendSync + 'static
) -> &mut Self
(internals) Provide a callback that will be invoked during parsing to remap certain tokens.
Exported under the internals
feature only.
Callback Function Signature
The callback function signature takes the following form:
Fn(token: Token, pos: Position, state: &TokenizeState) -> Token
where:
Raising errors
It is possible to raise a parsing error by returning
Token::LexError
as the mapped token.
Example
use quad_compat_rhai::{Engine, Token};
let mut engine = Engine::new();
// Register a token mapper.
engine.on_parse_token(|token, _, _| {
match token {
// Convert all integer literals to strings
Token::IntegerConstant(n) => Token::StringConstant(n.to_string().into()),
// Convert 'begin' .. 'end' to '{' .. '}'
Token::Identifier(s) if &*s == "begin" => Token::LeftBrace,
Token::Identifier(s) if &*s == "end" => Token::RightBrace,
// Pass through all other tokens unchanged
_ => token
}
});
assert_eq!(engine.eval::<String>("42")?, "42");
assert_eq!(engine.eval::<bool>("true")?, true);
assert_eq!(engine.eval::<String>("let x = 42; begin let x = 0; end; x")?, "42");
Register a callback for script evaluation progress.
Not available under unchecked
.
Callback Function Signature
The callback function signature takes the following form:
Fn(counter: u64) -> Option<Dynamic>
Return value
None
: continue running the script.Some(Dynamic)
: terminate the script with the specified exception value.
Example
use quad_compat_rhai::Engine;
let result = Arc::new(RwLock::new(0_u64));
let logger = result.clone();
let mut engine = Engine::new();
engine.on_progress(move |ops| {
if ops > 1000 {
Some("Over 1,000 operations!".into())
} else if ops % 123 == 0 {
*logger.write().unwrap() = ops;
None
} else {
None
}
});
engine.run("for x in 0..5000 { print(x); }")
.expect_err("should error");
assert_eq!(*result.read().unwrap(), 984);
Override default action of print
(print to stdout using println!
)
Example
use quad_compat_rhai::Engine;
let result = Arc::new(RwLock::new(String::new()));
let mut engine = Engine::new();
// Override action of 'print' function
let logger = result.clone();
engine.on_print(move |s| logger.write().unwrap().push_str(s));
engine.run("print(40 + 2);")?;
assert_eq!(*result.read().unwrap(), "42");
Override default action of debug
(print to stdout using println!
)
Callback Function Signature
The callback function signature passed takes the following form:
Fn(text: &str, source: Option<&str>, pos: Position)
where:
text
: the text to displaysource
: current source, if anypos
: location of thedebug
call
Example
use quad_compat_rhai::Engine;
let result = Arc::new(RwLock::new(String::new()));
let mut engine = Engine::new();
// Override action of 'print' function
let logger = result.clone();
engine.on_debug(move |s, src, pos| logger.write().unwrap().push_str(
&format!("{} @ {:?} > {}", src.unwrap_or("unknown"), pos, s)
));
let mut ast = engine.compile(r#"let x = "hello"; debug(x);"#)?;
ast.set_source("world");
engine.run_ast(&ast)?;
#[cfg(not(feature = "no_position"))]
assert_eq!(*result.read().unwrap(), r#"world @ 1:18 > "hello""#);
#[cfg(feature = "no_position")]
assert_eq!(*result.read().unwrap(), r#"world @ none > "hello""#);
👎 Deprecated since 1.1.0: use run_file
instead
use run_file
instead
Evaluate a file, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.
Not available under no_std
or WASM
.
Deprecated
This method is deprecated. Use run_file
instead.
This method will be removed in the next major version.
pub fn consume_file_with_scope(
&self,
scope: &mut Scope<'_>,
path: PathBuf
) -> Result<(), Box<EvalAltResult>>
👎 Deprecated since 1.1.0: use run_file_with_scope
instead
pub fn consume_file_with_scope(
&self,
scope: &mut Scope<'_>,
path: PathBuf
) -> Result<(), Box<EvalAltResult>>
use run_file_with_scope
instead
Evaluate a file with own scope, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.
Not available under no_std
or WASM
.
Deprecated
This method is deprecated. Use run_file_with_scope
instead.
This method will be removed in the next major version.
👎 Deprecated since 1.1.0: use run
instead
use run
instead
Evaluate a string, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.
Deprecated
This method is deprecated. Use run
instead.
This method will be removed in the next major version.
pub fn consume_with_scope(
&self,
scope: &mut Scope<'_>,
script: &str
) -> Result<(), Box<EvalAltResult>>
👎 Deprecated since 1.1.0: use run_with_scope
instead
pub fn consume_with_scope(
&self,
scope: &mut Scope<'_>,
script: &str
) -> Result<(), Box<EvalAltResult>>
use run_with_scope
instead
Evaluate a string with own scope, but throw away the result and only return error (if any). Useful for when you don’t need the result, but still need to keep track of possible errors.
Deprecated
This method is deprecated. Use run_with_scope
instead.
This method will be removed in the next major version.
👎 Deprecated since 1.1.0: use run_ast
instead
use run_ast
instead
Evaluate an AST
, but throw away the result and only return error (if any).
Useful for when you don’t need the result, but still need to keep track of possible errors.
Deprecated
This method is deprecated. Use run_ast
instead.
This method will be removed in the next major version.
pub fn consume_ast_with_scope(
&self,
scope: &mut Scope<'_>,
ast: &AST
) -> Result<(), Box<EvalAltResult>>
👎 Deprecated since 1.1.0: use run_ast_with_scope
instead
pub fn consume_ast_with_scope(
&self,
scope: &mut Scope<'_>,
ast: &AST
) -> Result<(), Box<EvalAltResult>>
use run_ast_with_scope
instead
Evaluate an AST
with own scope, but throw away the result and only return error (if any).
Useful for when you don’t need the result, but still need to keep track of possible errors.
Deprecated
This method is deprecated. Use run_ast_with_scope
instead.
This method will be removed in the next major version.
pub fn call_fn_dynamic(
&self,
scope: &mut Scope<'_>,
ast: &AST,
eval_ast: bool,
name: impl AsRef<str>,
this_ptr: Option<&mut Dynamic>,
arg_values: impl AsMut<[Dynamic]>
) -> Result<Dynamic, Box<EvalAltResult>>
👎 Deprecated since 1.1.0: use call_fn_raw
instead
pub fn call_fn_dynamic(
&self,
scope: &mut Scope<'_>,
ast: &AST,
eval_ast: bool,
name: impl AsRef<str>,
this_ptr: Option<&mut Dynamic>,
arg_values: impl AsMut<[Dynamic]>
) -> Result<Dynamic, Box<EvalAltResult>>
use call_fn_raw
instead
Call a script function defined in an AST
with multiple Dynamic
arguments
and optionally a value for binding to the this
pointer.
Not available under no_function
.
There is an option to evaluate the AST
to load necessary modules before calling the function.
Deprecated
This method is deprecated. Use run_ast_with_scope
instead.
This method will be removed in the next major version.
WARNING - Low Level API
This function is very low level.
Arguments
All the arguments are consumed, meaning that they’re replaced by ()
.
This is to avoid unnecessarily cloning the arguments.
Do not use the arguments after this call. If they are needed afterwards,
clone them before calling this function.
Example
use quad_compat_rhai::{Engine, Scope, Dynamic};
let engine = Engine::new();
let ast = engine.compile("
fn add(x, y) { len(x) + y + foo }
fn add1(x) { len(x) + 1 + foo }
fn bar() { foo/2 }
fn action(x) { this += x; } // function using 'this' pointer
")?;
let mut scope = Scope::new();
scope.push("foo", 42_i64);
// Call the script-defined function
let result = engine.call_fn_dynamic(&mut scope, &ast, true, "add", None, [ "abc".into(), 123_i64.into() ])?;
// ^^^^ no 'this' pointer
assert_eq!(result.cast::<i64>(), 168);
let result = engine.call_fn_dynamic(&mut scope, &ast, true, "add1", None, [ "abc".into() ])?;
assert_eq!(result.cast::<i64>(), 46);
let result = engine.call_fn_dynamic(&mut scope, &ast, true, "bar", None, [])?;
assert_eq!(result.cast::<i64>(), 21);
let mut value: Dynamic = 1_i64.into();
let result = engine.call_fn_dynamic(&mut scope, &ast, true, "action", Some(&mut value), [ 41_i64.into() ])?;
// ^^^^^^^^^^^^^^^^ binding the 'this' pointer
assert_eq!(value.as_int().expect("value should be INT"), 42);
Script optimization API.
pub fn optimize_ast(
&self,
scope: &Scope<'_>,
ast: AST,
optimization_level: OptimizationLevel
) -> AST
pub fn optimize_ast(
&self,
scope: &Scope<'_>,
ast: AST,
optimization_level: OptimizationLevel
) -> AST
Optimize the AST
with constants defined in an external Scope. An optimized
copy of the AST
is returned while the original AST
is consumed.
Not available under no_optimize
.
Although optimization is performed by default during compilation, sometimes it is necessary
to re-optimize an AST
. For example, when working with constants that are
passed in via an external scope, it will be more efficient to optimize the
AST
once again to take advantage of the new constants.
With this method, it is no longer necessary to recompile a large script. The script
AST
can be compiled just once. Before evaluation, constants are passed into
the Engine
via an external scope (i.e. with
Scope::push_constant
). Then, the AST
is
cloned and the copy re-optimized before running.
Set the module resolution service used by the Engine
.
Not available under no_module
.
Disable a particular keyword or operator in the language.
Examples
The following will raise an error during parsing because the if
keyword is disabled
and is recognized as a reserved symbol!
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
engine.disable_symbol("if"); // disable the 'if' keyword
engine.compile("let x = if true { 42 } else { 0 };")?;
// ^ 'if' is rejected as a reserved symbol
The following will raise an error during parsing because the +=
operator is disabled.
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
engine.disable_symbol("+="); // disable the '+=' operator
engine.compile("let x = 42; x += 1;")?;
// ^ unknown operator
pub fn register_custom_operator(
&mut self,
keyword: impl AsRef<str> + Into<Identifier>,
precedence: u8
) -> Result<&mut Self, String>
pub fn register_custom_operator(
&mut self,
keyword: impl AsRef<str> + Into<Identifier>,
precedence: u8
) -> Result<&mut Self, String>
Register a custom operator with a precedence into the language.
The operator can be a valid identifier, a reserved symbol, a disabled operator or a disabled keyword.
The precedence cannot be zero.
Example
use quad_compat_rhai::Engine;
let mut engine = Engine::new();
// Register a custom operator called '#' and give it
// a precedence of 160 (i.e. between +|- and *|/).
engine.register_custom_operator("#", 160).expect("should succeed");
// Register a binary function named '#'
engine.register_fn("#", |x: i64, y: i64| (x * y) - (x + y));
assert_eq!(
engine.eval_expression::<i64>("1 + 2 * 3 # 4 - 5 / 6")?,
15
);
pub fn register_custom_syntax<S: AsRef<str> + Into<Identifier>>(
&mut self,
symbols: &[S],
scope_may_be_changed: bool,
func: impl Fn(&mut EvalContext<'_, '_, '_, '_, '_, '_, '_, '_>, &[Expression<'_>]) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static
) -> Result<&mut Self, ParseError>
pub fn register_custom_syntax<S: AsRef<str> + Into<Identifier>>(
&mut self,
symbols: &[S],
scope_may_be_changed: bool,
func: impl Fn(&mut EvalContext<'_, '_, '_, '_, '_, '_, '_, '_>, &[Expression<'_>]) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static
) -> Result<&mut Self, ParseError>
Register a custom syntax with the Engine
.
symbols
holds a slice of strings that define the custom syntax.scope_may_be_changed
specifies variables may be added/removed by this custom syntax.func
is the implementation function.
Note on symbols
- Whitespaces around symbols are stripped.
- Symbols that are all-whitespace or empty are ignored.
- If
symbols
does not contain at least one valid token, then the custom syntax registration is simply ignored.
Note on scope_may_be_changed
If scope_may_be_changed
is true
, then size of the current Scope
may be modified by this custom syntax.
Adding new variables and/or removing variables count.
Simply modifying the values of existing variables does NOT count, as the size of the
current Scope
is unchanged, so false
should be passed.
Replacing one variable with another (i.e. adding a new variable and removing one variable at
the same time so that the total size of the Scope
is unchanged) also
does NOT count, so false
should be passed.
pub fn register_custom_syntax_raw(
&mut self,
key: impl Into<Identifier>,
parse: impl Fn(&[ImmutableString], &str) -> Result<Option<ImmutableString>, ParseError> + SendSync + 'static,
scope_may_be_changed: bool,
func: impl Fn(&mut EvalContext<'_, '_, '_, '_, '_, '_, '_, '_>, &[Expression<'_>]) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static
) -> &mut Self
pub fn register_custom_syntax_raw(
&mut self,
key: impl Into<Identifier>,
parse: impl Fn(&[ImmutableString], &str) -> Result<Option<ImmutableString>, ParseError> + SendSync + 'static,
scope_may_be_changed: bool,
func: impl Fn(&mut EvalContext<'_, '_, '_, '_, '_, '_, '_, '_>, &[Expression<'_>]) -> Result<Dynamic, Box<EvalAltResult>> + SendSync + 'static
) -> &mut Self
Register a custom syntax with the Engine
.
WARNING - Low Level API
This function is very low level.
scope_may_be_changed
specifies variables have been added/removed by this custom syntax.parse
is the parsing function.func
is the implementation function.
All custom keywords used as symbols must be manually registered via Engine::register_custom_operator
.
Otherwise, they won’t be recognized.
Implementation Function Signature
The implementation function has the following signature:
Fn(symbols: &[ImmutableString], look_ahead: &str) -> Result<Option<ImmutableString>, ParseError>
where:
symbols
: a slice of symbols that have been parsed so far, possibly containing$expr$
and/or$block$
;$ident$
and other literal markers are replaced by the actual textlook_ahead
: a string slice containing the next symbol that is about to be read
Return value
Ok(None)
: parsing complete and there are no more symbols to match.Ok(Some(symbol))
: the next symbol to match, which can also be$expr$
,$ident$
or$block$
.Err(ParseError)
: error that is reflected back to theEngine
, normallyParseError(ParseErrorType::BadInput(LexError::ImproperSymbol(message)), Position::NONE)
to indicate a syntax error, but it can be anyParseError
.
Create a new Engine
with minimal built-in functions.
Use register_global_module
to add packages of functions.
Get an empty ImmutableString
.
Engine
keeps a single instance of an empty ImmutableString
and uses this to create
shared instances for subsequent uses. This minimizes unnecessary allocations for empty strings.
Pretty-print a type name.
If a type is registered via register_type_with_name
,
the type name provided for the registration will be used.
pub fn lex<'a>(
&'a self,
input: impl IntoIterator<Item = &'a impl AsRef<str> + 'a>
) -> (TokenIterator<'a>, TokenizerControl)
pub fn lex<'a>(
&'a self,
input: impl IntoIterator<Item = &'a impl AsRef<str> + 'a>
) -> (TokenIterator<'a>, TokenizerControl)
(internals) Tokenize an input text stream.
Exported under the internals
feature only.
pub fn lex_with_map<'a>(
&'a self,
input: impl IntoIterator<Item = &'a impl AsRef<str> + 'a>,
token_mapper: &'a dyn Fn(Token, Position, &TokenizeState) -> Token
) -> (TokenIterator<'a>, TokenizerControl)
pub fn lex_with_map<'a>(
&'a self,
input: impl IntoIterator<Item = &'a impl AsRef<str> + 'a>,
token_mapper: &'a dyn Fn(Token, Position, &TokenizeState) -> Token
) -> (TokenIterator<'a>, TokenizerControl)
(internals) Tokenize an input text stream with a mapping function.
Exported under the internals
feature only.
(metadata) Generate a list of all functions (including those defined in an
AST
) in JSON format.
Exported under the metadata
feature only.
Functions from the following sources are included:
- Functions defined in an
AST
- Functions registered into the global namespace
- Functions in static modules
- Functions in global modules (optional)
Generate a list of all functions in JSON format.
Exported under the metadata
feature only.
Functions from the following sources are included:
- Functions registered into the global namespace
- Functions in static modules
- Functions in global modules (optional)
Trait Implementations
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, D: Variant + Clone, E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(A, B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<A: Variant + Clone, B: Variant + Clone, C: Variant + Clone, D: Variant + Clone, E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(A, B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
type Output = Box<dyn Fn(A, B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V) -> Result<RET, Box<EvalAltResult>>>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<B: Variant + Clone, C: Variant + Clone, D: Variant + Clone, E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<B: Variant + Clone, C: Variant + Clone, D: Variant + Clone, E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
type Output = Box<dyn Fn(B, C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V) -> Result<RET, Box<EvalAltResult>>>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<C: Variant + Clone, D: Variant + Clone, E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<C: Variant + Clone, D: Variant + Clone, E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
type Output = Box<dyn Fn(C, D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V) -> Result<RET, Box<EvalAltResult>>>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<D: Variant + Clone, E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<D: Variant + Clone, E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
type Output = Box<dyn Fn(D, E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V) -> Result<RET, Box<EvalAltResult>>>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<E: Variant + Clone, F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
type Output = Box<dyn Fn(E, F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V) -> Result<RET, Box<EvalAltResult>>>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<F: Variant + Clone, G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
type Output = Box<dyn Fn(F, G, H, J, K, L, M, N, P, Q, R, S, T, U, V) -> Result<RET, Box<EvalAltResult>>>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<G: Variant + Clone, H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(G, H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
type Output = Box<dyn Fn(G, H, J, K, L, M, N, P, Q, R, S, T, U, V) -> Result<RET, Box<EvalAltResult>>>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<H: Variant + Clone, J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(H, J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<J: Variant + Clone, K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(J, K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
impl<K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
impl<K: Variant + Clone, L: Variant + Clone, M: Variant + Clone, N: Variant + Clone, P: Variant + Clone, Q: Variant + Clone, R: Variant + Clone, S: Variant + Clone, T: Variant + Clone, U: Variant + Clone, V: Variant + Clone, RET: Variant + Clone> Func<(K, L, M, N, P, Q, R, S, T, U, V), RET> for Engine
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
fn create_from_script(
self,
script: &str,
entry_point: &str
) -> Result<Self::Output, ParseError>
Create a Rust closure from a script. Read more