devalang_core/core/preprocessor/resolver/
trigger.rs1use 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 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 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}