Skip to main content

gridline_engine/engine/
eval.rs

1use rhai::Engine;
2use std::sync::Arc;
3
4use super::{AST, Dynamic, Grid, SpillMap};
5
6/// Create a Rhai engine with built-ins registered.
7pub fn create_engine(grid: Arc<Grid>) -> Engine {
8    let spill_map = Arc::new(SpillMap::new());
9    create_engine_with_spill(grid, spill_map)
10}
11
12/// Create a Rhai engine with built-ins registered and a shared spill map.
13pub fn create_engine_with_spill(grid: Arc<Grid>, spill_map: Arc<SpillMap>) -> Engine {
14    let mut engine = Engine::new();
15    crate::builtins::register_builtins(&mut engine, grid, spill_map);
16    engine
17}
18
19/// Create a Rhai engine with built-ins registered.
20/// Optionally compiles custom functions from the provided script.
21/// Returns the engine, compiled AST (if any), and any error message.
22pub fn create_engine_with_functions(
23    grid: Arc<Grid>,
24    custom_script: Option<&str>,
25) -> (Engine, Option<AST>, Option<String>) {
26    let spill_map = Arc::new(SpillMap::new());
27    create_engine_with_functions_and_spill(grid, spill_map, custom_script)
28}
29
30/// Create a Rhai engine with built-ins, custom functions, and a shared spill map.
31/// Returns the engine, compiled AST (if any), and any error message.
32pub fn create_engine_with_functions_and_spill(
33    grid: Arc<Grid>,
34    spill_map: Arc<SpillMap>,
35    custom_script: Option<&str>,
36) -> (Engine, Option<AST>, Option<String>) {
37    let engine = create_engine_with_spill(grid, spill_map);
38
39    let (ast, error) = if let Some(script) = custom_script {
40        match engine.compile(script) {
41            Ok(ast) => (Some(ast), None),
42            Err(e) => (None, Some(format!("Error in custom functions: {}", e))),
43        }
44    } else {
45        (None, None)
46    };
47
48    (engine, ast, error)
49}
50
51/// Evaluate a formula, optionally with custom functions AST.
52pub fn eval_with_functions(
53    engine: &Engine,
54    formula: &str,
55    custom_ast: Option<&AST>,
56) -> Result<Dynamic, String> {
57    if let Some(ast) = custom_ast {
58        match engine.compile(formula) {
59            Ok(formula_ast) => {
60                let merged = ast.clone().merge(&formula_ast);
61                engine.eval_ast(&merged).map_err(|e| e.to_string())
62            }
63            Err(e) => Err(e.to_string()),
64        }
65    } else {
66        engine.eval(formula).map_err(|e| e.to_string())
67    }
68}