Create a Module from an AST
Module::eval_ast_as_new
Module::eval_ast_as_new encapsulates the entire AST into each function call, merging the
module namespace with the global namespace.
Therefore, functions defined within the same module script can cross-call each other.
See Export Variables, Functions and Sub-Modules from Script for details on how to prepare a Rhai script for this purpose as well as to control which functions/variables to export.
A module can be created from a single script (or pre-compiled AST) containing global
variables, functions and sub-modules via Module::eval_ast_as_new.
When given an AST, it is first evaluated (usually to import modules and set up global
constants used by functions), then the following items are exposed as members of the new module:
-
global variables and constants – all variables and constants exported via the
exportstatement (those not exported remain hidden), -
imported modules that remain in the
Scopeat the end of a script run become sub-modules.
Examples
Don’t forget the export statement, otherwise there will be no variables exposed by the
module other than non-private functions (unless that’s intentional).
use rhai::{Engine, Module};
let engine = Engine::new();
// Compile a script into an 'AST'
let ast = engine.compile(
r#"
// Functions become module functions
fn calc(x) {
x + add_len(x, 1) // functions within the same module
// can always cross-call each other!
}
fn add_len(x, y) {
x + y.len
}
// Imported modules become sub-modules
import "another module" as extra;
// Variables defined at global level can become module variables
const x = 123;
let foo = 41;
let hello;
// Variable values become constant module variable values
foo = calc(foo);
hello = `hello, ${foo} worlds!`;
// Finally, export the variables and modules
export x as abc; // aliased variable name
export foo;
export hello;
"#)?;
// Convert the 'AST' into a module, using the 'Engine' to evaluate it first
// A copy of the entire 'AST' is encapsulated into each function,
// allowing functions in the module script to cross-call each other.
let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
// 'module' now contains:
// - sub-module: 'extra'
// - functions: 'calc', 'add_len'
// - constants: 'abc' (renamed from 'x'), 'foo', 'hello'