devalang_core/core/preprocessor/resolver/
trigger.rs

1use std::collections::HashMap;
2
3use crate::{
4    core::{
5        parser::statement::{Statement, StatementKind},
6        preprocessor::module::Module,
7        shared::{duration::Duration, value::Value},
8        store::global::GlobalStore,
9    },
10    utils::logger::Logger,
11};
12
13pub fn resolve_trigger(
14    stmt: &Statement,
15    entity: &str,
16    duration: &mut Duration,
17    _effects: Option<Value>,
18    module: &Module,
19    path: &str,
20    global_store: &GlobalStore,
21) -> Statement {
22    let logger = Logger::new();
23
24    let mut final_duration = duration.clone();
25
26    // Duration resolution
27    if let Duration::Identifier(ident) = duration {
28        if let Some(val) = resolve_identifier(ident, module, global_store) {
29            match val {
30                Value::Number(n) => {
31                    final_duration = Duration::Number(n);
32                }
33                Value::String(s) => {
34                    final_duration = Duration::Identifier(s);
35                }
36                Value::Identifier(s) if s == "auto" => {
37                    final_duration = Duration::Auto;
38                }
39                _ => {}
40            }
41        }
42    }
43
44    // Params value resolution
45    let final_value = match &stmt.value {
46        Value::Identifier(ident) => {
47            println!("Resolving identifier: {}", ident);
48
49            resolve_identifier(ident, module, global_store).unwrap_or_else(|| {
50                logger.log_error_with_stacktrace(
51                    &format!("'{path}': value identifier '{ident}' not found"),
52                    &format!("{}:{}:{}", module.path, stmt.line, stmt.column),
53                );
54                Value::Null
55            })
56        }
57        Value::Map(map) => {
58            let mut resolved_map = HashMap::new();
59            for (k, v) in map {
60                let resolved = match v {
61                    Value::Identifier(id) => {
62                        resolve_identifier(id, module, global_store).unwrap_or(Value::Null)
63                    }
64                    other => other.clone(),
65                };
66                resolved_map.insert(k.clone(), resolved);
67            }
68            Value::Map(resolved_map)
69        }
70        other => other.clone(),
71    };
72
73    Statement {
74        kind: StatementKind::Trigger {
75            entity: entity.to_string(),
76            duration: final_duration.clone(),
77            effects: Some(final_value.clone()),
78        },
79        value: Value::Null,
80        line: stmt.line,
81        column: stmt.column,
82        indent: stmt.indent,
83    }
84}
85
86fn resolve_identifier(ident: &str, module: &Module, global_store: &GlobalStore) -> Option<Value> {
87    if let Some(val) = module.variable_table.get(ident) {
88        return Some(resolve_value(val, module, global_store));
89    }
90
91    for (_, other_mod) in &global_store.modules {
92        if let Some(val) = other_mod.variable_table.get(ident) {
93            return Some(resolve_value(val, other_mod, global_store));
94        }
95    }
96
97    None
98}
99
100fn resolve_value(val: &Value, module: &Module, global_store: &GlobalStore) -> Value {
101    match val {
102        Value::Identifier(inner) => resolve_identifier(inner, module, global_store)
103            .unwrap_or(Value::Identifier(inner.clone())),
104        Value::Map(map) => {
105            let mut resolved = HashMap::new();
106            for (k, v) in map {
107                resolved.insert(k.clone(), resolve_value(v, module, global_store));
108            }
109            Value::Map(resolved)
110        }
111        other => other.clone(),
112    }
113}