Manage `AST`'s ============== {{#include ../links.md}} When compiling a Rhai script to an [`AST`], the following data are packaged together as a single unit: | Data | Type | Description | Requires feature | Access API | | -------------------------------- | :---------------------------------------: | ------------------------------------------------------------------------------------------------- | :------------------------------------: | :------------------------------------------------------------------------------------------------------------: | | Source name | [`ImmutableString`] | optional text name to identify the source of the script | | `source(&self)`,
`clone_source(&self)`,
`set_source(&mut self, source)`,
`clear_source(&mut self)` | | [Module documentation][comments] | [`Vec`][`SmartString`] | documentation of the script | [`metadata`] | `doc(&self)`,
`clear_doc(&mut self)` | | Statements | `Vec` | list of script statements at global level | [`internals`] | `statements(&self)`,
`statements_mut(&mut self)` | | Functions | [`Shared`][`Module`] | [functions] defined in the script | [`internals`],
not [`no_function`] | `shared_lib(&self)` | | Embedded [module resolver] | [`StaticModuleResolver`][module resolver] | embedded [module resolver] for [self-contained `AST`]({{rootUrl}}/rust/modules/self-contained.md) | [`internals`],
not [`no_module`] | `resolver(&self)` | Most of the [`AST`] API is available only under the [`internals`] feature. ```admonish tip.small "Tip: Source name" Use the source name to identify the source script in errors – useful when multiple [modules] are imported recursively. ``` ~~~admonish info.small "`AST` public API" For the complete [`AST`] API, refer to the [documentation](https://docs.rs/rhai/{{version}}/rhai/struct.AST.html) online. ~~~ Extract Only Functions ---------------------- The following methods, not available under [`no_function`], allow manipulation of the [functions] encapsulated within an [`AST`]: | Method | Description | | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | `clone_functions_only(&self)` | clone the [`AST`] into a new [`AST`] with only [functions], excluding statements | | `clone_functions_only_filtered(&self, filter)` | clone the [`AST`] into a new [`AST`] with only [functions] that pass the filter predicate, excluding statements | | `retain_functions(&mut self, filter)` | remove all [functions] in the [`AST`] that do not pass a particular predicate filter; statements are untouched | | `iter_functions(&self)` | return an iterator on all the [functions] in the [`AST`] | | `clear_functions(&mut self)` | remove all [functions] from the [`AST`], leaving only statements | Extract Only Statements ----------------------- The following methods allow manipulation of the statements in an [`AST`]: | Method | Description | | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | `clone_statements_only(&self)` | clone the [`AST`] into a new [`AST`] with only the statements, excluding [functions] | | `clear_statements(&mut self)` | remove all statements from the [`AST`], leaving only [functions] | | `iter_literal_variables(&self, constants, variables)` | return an iterator on all top-level literal constant and/or variable definitions in the [`AST`] | Merge and Combine AST's ----------------------- The following methods merge one [`AST`] with another: | Method | Description | | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `merge(&self, &ast)`,
`+` operator | append the second [`AST`] to this [`AST`], yielding a new [`AST`] that is a combination of the two; statements are simply appended, [functions] in the second [`AST`] of the same name and arity override similar [functions] in this [`AST`] | | `merge_filtered(&self, &ast, filter)` | append the second [`AST`] (but only [functions] that pass the predicate filter) to this [`AST`], yielding a new [`AST`] that is a combination of the two; statements are simply appended, [functions] in the second [`AST`] of the same name and arity override similar [functions] in this [`AST`] | | `combine(&mut self, ast)`,
`+=` operator | append the second [`AST`] to this [`AST`]; statements are simply appended, [functions] in the second [`AST`] of the same name and arity override similar [functions] in this [`AST`] | | `combine_filtered(&mut self, ast, filter)` | append the second [`AST`] (but only [functions] that pass the predicate filter) to this [`AST`]; statements are simply appended, [functions] in the second [`AST`] of the same name and arity override similar [functions] in this [`AST`] | When statements are appended, beware that this may change the semantics of the script. ```rust // First script let ast1 = engine.compile( " fn foo(x) { 42 + x } foo(1) ")?; // Second script let ast2 = engine.compile( " fn foo(n) { `hello${n}` } foo("!") ")?; // Merge them let merged = ast1.merge(&ast2); // Notice that using the '+' operator also works: let merged = &ast1 + &ast2; ``` `merged` in the above example essentially contains the following script program: ```js 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!" ``` Walk an AST ----------- The [`internals`] feature allows access to internal Rhai data structures, particularly the nodes that make up the [`AST`]. ### AST node types There are a few useful types when walking an [`AST`]: | Type | Description | | ------------ | ----------------------------------------------------------------- | | `ASTNode` | an `enum` with two variants: `Expr` or `Stmt` | | `Expr` | an _expression_ | | `Stmt` | a _statement_ | | `BinaryExpr` | a sub-type containing the LHS and RHS of a binary expression | | `FnCallExpr` | a sub-type containing information on a function call | | `CustomExpr` | a sub-type containing information on a [custom syntax] expression | The `AST::walk` method takes a callback function and recursively walks the [`AST`] in depth-first manner, with the parent node visited before its children. ### Callback function signature The signature of the callback function takes the following form. > ```rust > FnMut(&[ASTNode]) -> bool > ``` The single argument passed to the method contains a slice of `ASTNode` types representing the path from the current node to the root of the [`AST`]. Return `true` to continue walking the [`AST`], or `false` to terminate. ### Children visit order The order of visits to the children of each node type: | Node type | Children visit order | | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`if`] statement |
  1. condition expression
  2. _then_ statements
  3. _else_ statements (if any)
| | [`switch`] statement |
  1. match element
  2. each of the case conditions and statements, in order
  3. each of the range conditions and statements, in order
  4. default statements (if any)
| | [`while`], [`do`], [`loop`] statement |
  1. condition expression
  2. statements body
| | [`for`] statement |
  1. collection expression
  2. statements body
| | [`return`] statement | return value expression | | [`throw`] statement | exception value expression | | [`try` ... `catch`][exception] statement |
  1. `try` statements body
  2. `catch` statements body
| | [`import`] statement | path expression | | [Array] literal | each of the element expressions, in order | | [Object map] literal | each of the element expressions, in order | | Interpolated [string] | each of the [string]/expression segments, in order | | Indexing |
  1. LHS expression
  2. RHS (index) expression
| | Field access/method call |
  1. LHS expression
  2. RHS expression
| | `&&`, \|\|, `??` |
  1. LHS expression
  2. RHS expression
| | [Function] call, [operator] expression | each of the argument expressions, in order | | [`let`][variable], [`const`][constant] statement | value expression | | Assignment statement |
  1. l-value expression
  2. value expression
| | Statements block | each of the statements, in order | | Custom syntax expression | each of the inputs stream, in order | | All others | single child (if any) |