devalang_core/core/preprocessor/resolver/
trigger.rs

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