zen_engine/nodes/expression/
mod.rs

1use crate::model::CompilationKey;
2use crate::model::ExpressionNodeContent;
3use crate::nodes::result::NodeResult;
4use ahash::HashMap;
5use std::rc::Rc;
6
7use crate::nodes::context::{NodeContext, NodeContextExt};
8use crate::nodes::definition::NodeHandler;
9use zen_expression::variable::{ToVariable, Variable};
10use zen_expression::{ExpressionKind, Isolate};
11use zen_types::decision::TransformAttributes;
12
13#[derive(Debug, Clone)]
14pub struct ExpressionNodeHandler;
15
16pub type ExpressionNodeData = ExpressionNodeContent;
17pub type ExpressionNodeTrace = HashMap<Rc<str>, ExpressionNodeTraceItem>;
18
19impl NodeHandler for ExpressionNodeHandler {
20    type NodeData = ExpressionNodeData;
21    type TraceData = ExpressionNodeTrace;
22
23    fn transform_attributes(
24        &self,
25        ctx: &NodeContext<Self::NodeData, Self::TraceData>,
26    ) -> Option<TransformAttributes> {
27        Some(ctx.node.transform_attributes.clone())
28    }
29
30    async fn handle(&self, ctx: NodeContext<Self::NodeData, Self::TraceData>) -> NodeResult {
31        let result = Variable::empty_object();
32        let mut isolate = Isolate::new();
33        isolate.set_environment(ctx.input.depth_clone(1));
34
35        for expression in ctx.node.expressions.iter() {
36            if expression.key.is_empty() || expression.value.is_empty() {
37                continue;
38            }
39            let key = CompilationKey {
40                kind: ExpressionKind::Standard,
41                source: expression.value.clone(),
42            };
43            let value;
44            match ctx
45                .extensions
46                .compiled_cache
47                .as_ref()
48                .and_then(|cc| cc.get(&key))
49            {
50                Some(codes) => value = isolate.run_compiled(codes.as_slice()),
51                None => value = isolate.run_standard(&expression.value),
52            }
53
54            let value = value.with_node_context(&ctx, |_| {
55                format!(r#"Failed to evaluate expression: "{}""#, &expression.value)
56            })?;
57            ctx.trace(|trace| {
58                trace.insert(
59                    Rc::from(&*expression.key),
60                    ExpressionNodeTraceItem {
61                        result: value.clone(),
62                    },
63                );
64            });
65
66            isolate.update_environment(|env| {
67                let Some(environment) = env else {
68                    return;
69                };
70
71                let key = format!("$.{}", &expression.key);
72                let _ = environment.dot_insert(key.as_str(), value.depth_clone(2));
73            });
74
75            result.dot_insert(&expression.key, value);
76        }
77
78        ctx.success(result)
79    }
80}
81
82#[derive(Debug, Clone, ToVariable)]
83pub struct ExpressionNodeTraceItem {
84    result: Variable,
85}