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