Struct AST
pub struct AST { /* private fields */ }
Expand description
Implementations§
§impl AST
impl AST
pub fn set_source(&mut self, source: impl Into<ImmutableString>) -> &mut AST
pub fn set_source(&mut self, source: impl Into<ImmutableString>) -> &mut AST
Set the source.
pub fn clear_source(&mut self) -> &mut AST
pub fn clear_source(&mut self) -> &mut AST
Clear the source.
pub fn clone_statements_only(&self) -> AST
pub fn clone_statements_only(&self) -> AST
pub fn merge(&self, other: &AST) -> AST
pub fn merge(&self, other: &AST) -> AST
Merge two AST
into one. Both AST
’s are untouched and a new, merged,
version is returned.
Statements in the second AST
are simply appended to the end of the first without any processing.
Thus, the return value of the first AST
(if using expression-statement syntax) is buried.
Of course, if the first AST
uses a return
statement at the end, then
the second AST
will essentially be dead code.
All script-defined functions in the second AST
overwrite similarly-named functions
in the first AST
with the same number of parameters.
§Example
use rhai::Engine;
let engine = Engine::new();
let ast1 = engine.compile("
fn foo(x) { 42 + x }
foo(1)
")?;
let ast2 = engine.compile(r#"
fn foo(n) { `hello${n}` }
foo("!")
"#)?;
let ast = ast1.merge(&ast2); // Merge 'ast2' into 'ast1'
// Notice that using the '+' operator also works:
// let ast = &ast1 + &ast2;
// 'ast' is essentially:
//
// fn foo(n) { `hello${n}` } // <- definition of first 'foo' is overwritten
// foo(1) // <- notice this will be "hello1" instead of 43,
// // but it is no longer the return value
// foo("!") // returns "hello!"
// Evaluate it
assert_eq!(engine.eval_ast::<String>(&ast)?, "hello!");
pub fn combine(&mut self, other: AST) -> &mut AST
pub fn combine(&mut self, other: AST) -> &mut AST
Combine one AST
with another. The second AST
is consumed.
Statements in the second AST
are simply appended to the end of the first without any processing.
Thus, the return value of the first AST
(if using expression-statement syntax) is buried.
Of course, if the first AST
uses a return
statement at the end, then
the second AST
will essentially be dead code.
All script-defined functions in the second AST
overwrite similarly-named functions
in the first AST
with the same number of parameters.
§Example
use rhai::Engine;
let engine = Engine::new();
let mut ast1 = engine.compile("
fn foo(x) { 42 + x }
foo(1)
")?;
let ast2 = engine.compile(r#"
fn foo(n) { `hello${n}` }
foo("!")
"#)?;
ast1.combine(ast2); // Combine 'ast2' into 'ast1'
// Notice that using the '+=' operator also works:
// ast1 += ast2;
// 'ast1' is essentially:
//
// fn foo(n) { `hello${n}` } // <- definition of first 'foo' is overwritten
// foo(1) // <- notice this will be "hello1" instead of 43,
// // but it is no longer the return value
// foo("!") // returns "hello!"
// Evaluate it
assert_eq!(engine.eval_ast::<String>(&ast1)?, "hello!");
pub fn clear_statements(&mut self) -> &mut AST
pub fn clear_statements(&mut self) -> &mut AST
Clear all statements in the AST
, leaving only function definitions.
pub fn iter_literal_variables(
&self,
include_constants: bool,
include_variables: bool,
) -> impl Iterator<Item = (&str, bool, Dynamic)>
pub fn iter_literal_variables( &self, include_constants: bool, include_variables: bool, ) -> impl Iterator<Item = (&str, bool, Dynamic)>
Extract all top-level literal constant and/or variable definitions. This is useful for extracting all global constants from a script without actually running it.
A literal constant/variable definition takes the form of:
const VAR =
value;
and let VAR =
value;
where value is a literal expression or will be optimized into a literal.
§Example
use rhai::{Engine, Scope};
let engine = Engine::new();
let ast = engine.compile(
"
const A = 40 + 2; // constant that optimizes into a literal
let b = 123; // literal variable
const B = b * A; // non-literal constant
const C = 999; // literal constant
b = A + C; // expression
{ // <- new block scope
const Z = 0; // <- literal constant not at top-level
print(Z); // make sure the block is not optimized away
}
")?;
let mut iter = ast.iter_literal_variables(true, false)
.map(|(name, is_const, value)| (name, is_const, value.as_int().unwrap()));
assert_eq!(iter.next(), Some(("A", true, 42)));
assert_eq!(iter.next(), Some(("C", true, 999)));
assert_eq!(iter.next(), None);
let mut iter = ast.iter_literal_variables(false, true)
.map(|(name, is_const, value)| (name, is_const, value.as_int().unwrap()));
assert_eq!(iter.next(), Some(("b", false, 123)));
assert_eq!(iter.next(), None);
let mut iter = ast.iter_literal_variables(true, true)
.map(|(name, is_const, value)| (name, is_const, value.as_int().unwrap()));
assert_eq!(iter.next(), Some(("A", true, 42)));
assert_eq!(iter.next(), Some(("b", false, 123)));
assert_eq!(iter.next(), Some(("C", true, 999)));
assert_eq!(iter.next(), None);
let scope: Scope = ast.iter_literal_variables(true, false).collect();
assert_eq!(scope.len(), 2);
Ok(())