1use crate::core::{
2 parser::statement::{Statement, StatementKind},
3 preprocessor::{
4 loader::ModuleLoader,
5 module::Module,
6 resolver::{
7 bank::resolve_bank, call::resolve_call, condition::resolve_condition,
8 function::resolve_function, group::resolve_group, let_::resolve_let,
9 loop_::resolve_loop, pattern::resolve_pattern, spawn::resolve_spawn,
10 tempo::resolve_tempo, trigger::resolve_trigger,
11 },
12 },
13 store::global::GlobalStore,
14};
15use devalang_types::Value;
16use devalang_utils::logger::LogLevel;
17use devalang_utils::logger::Logger;
18use std::collections::HashMap;
19
20pub fn resolve_all_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
21 for _module in global_store.clone().modules.values_mut() {
22 resolve_imports(module_loader, global_store);
23 }
24}
25
26pub fn resolve_statement(
27 stmt: &Statement,
28 module: &Module,
29 path: &str,
30 global_store: &mut GlobalStore,
31) -> Statement {
32 match &stmt.kind {
33 StatementKind::On { event, args, body } => {
34 let resolved_body: Vec<Statement> = body
35 .iter()
36 .map(|s| resolve_statement(s, module, path, global_store))
37 .collect();
38 Statement {
39 kind: StatementKind::On {
40 event: event.clone(),
41 args: args.clone(),
42 body: resolved_body,
43 },
44 value: resolve_value(&stmt.value, module, global_store),
45 ..stmt.clone()
46 }
47 }
48 StatementKind::Emit { event, payload: _ } => Statement {
49 kind: StatementKind::Emit {
50 event: event.clone(),
51 payload: Some(resolve_value(&stmt.value, module, global_store)),
52 },
53 value: resolve_value(&stmt.value, module, global_store),
54 ..stmt.clone()
55 },
56 StatementKind::Trigger {
57 entity,
58 duration,
59 effects,
60 } => resolve_trigger(
61 stmt,
62 entity,
63 &mut duration.clone(),
64 effects.clone(),
65 module,
66 path,
67 global_store,
68 ),
69 StatementKind::If => resolve_condition(stmt, module, path, global_store),
70 StatementKind::Group => resolve_group(stmt, module, path, global_store),
71 StatementKind::Pattern { .. } => resolve_pattern(stmt, module, path, global_store),
72 StatementKind::Call { name, args } => {
73 resolve_call(stmt, name.clone(), args.clone(), module, path, global_store)
74 }
75 StatementKind::Spawn { name, args } => {
76 resolve_spawn(stmt, name.clone(), args.clone(), module, path, global_store)
77 }
78 StatementKind::Bank { .. } => resolve_bank(stmt, module, path, global_store),
79 StatementKind::Tempo => resolve_tempo(stmt, module, path, global_store),
80 StatementKind::Loop => resolve_loop(stmt, module, path, global_store),
81 StatementKind::Let { name, .. } => resolve_let(stmt, name, module, path, global_store),
82
83 _ => {
84 let resolved_value = resolve_value(&stmt.value, module, global_store);
85
86 Statement {
87 value: resolved_value,
88 ..stmt.clone()
89 }
90 }
91 }
92}
93
94fn resolve_value(value: &Value, module: &Module, global_store: &mut GlobalStore) -> Value {
95 let logger = Logger::new();
96 match value {
97 Value::Identifier(name) => {
98 if let Some(original_val) = module.variable_table.get(name) {
99 return resolve_value(original_val, module, global_store);
100 }
101
102 if let Some(export_val) = find_export_value(name, global_store) {
103 return resolve_value(&export_val, module, global_store);
104 }
105
106 Value::Identifier(name.clone())
108 }
109
110 Value::String(s) => Value::String(s.clone()),
111
112 Value::Beat(beat_str) => {
113 logger.log_message(
114 LogLevel::Warning,
115 &format!("[warn] '{:?}': unresolved beat '{}'", module.path, beat_str),
116 );
117 Value::Beat(beat_str.clone())
118 }
119
120 Value::Map(map) => {
121 let mut resolved = HashMap::new();
122 for (k, v) in map {
123 resolved.insert(k.clone(), resolve_value(v, module, global_store));
124 }
125 Value::Map(resolved)
126 }
127
128 Value::Block(stmts) => {
129 let resolved_stmts = stmts
130 .iter()
131 .map(|stmt| resolve_statement(stmt, module, &module.path, global_store))
132 .collect();
133 Value::Block(resolved_stmts)
134 }
135
136 other => other.clone(),
137 }
138}
139
140fn find_export_value(name: &str, global_store: &GlobalStore) -> Option<Value> {
141 for module in global_store.modules.values() {
142 if let Some(val) = module.export_table.get_export(name) {
143 return Some(val.clone());
144 }
145 }
146 None
147}
148
149pub fn resolve_imports(_module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
150 let logger = Logger::new();
151 for (module_path, module) in global_store.clone().modules.iter_mut() {
152 for (name, source_path) in &module.import_table.imports {
153 match source_path {
154 Value::String(source_path) => {
155 if let Some(source_module) = global_store.modules.get(source_path) {
156 if let Some(value) = source_module.export_table.get_export(name) {
157 module.variable_table.set(name.clone(), value.clone());
158 } else {
159 logger.log_message(LogLevel::Warning, &format!("[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"));
160 }
161 } else {
162 logger.log_message(
163 LogLevel::Warning,
164 &format!(
165 "[warn] '{module_path}': cannot find source module '{source_path}'"
166 ),
167 );
168 }
169 }
170 _ => {
171 logger.log_message(
172 LogLevel::Warning,
173 &format!(
174 "[warn] '{module_path}': expected string for import source, found {:?}",
175 source_path
176 ),
177 );
178 }
179 }
180 }
181 }
182}
183
184pub fn resolve_and_flatten_all_modules(
185 global_store: &mut GlobalStore,
186) -> HashMap<String, Vec<Statement>> {
187 let logger = Logger::new();
188 let snapshot = global_store.clone();
189
190 for (module_path, module) in global_store.modules.iter_mut() {
192 for (name, source_path) in &module.import_table.imports {
193 if let Value::String(source_path_str) = source_path {
194 match snapshot.modules.get(source_path_str) {
195 Some(source_module) => {
196 if let Some(value) = source_module.export_table.get_export(name) {
197 module.variable_table.set(name.clone(), value.clone());
198 } else {
199 logger.log_error_with_stacktrace(
200 &format!("'{name}' not found in exports of '{source_path_str}'"),
201 module_path,
202 );
203 }
204 }
205 None => {
206 logger.log_error_with_stacktrace(
207 &format!("Cannot find source module '{source_path_str}'"),
208 module_path,
209 );
210 }
211 }
212 } else {
213 logger.log_error_with_stacktrace(
214 &format!("Expected string for import source, found {:?}", source_path),
215 module_path,
216 );
217 }
218 }
219 }
220
221 let mut resolved_map: HashMap<String, Vec<Statement>> = HashMap::new();
223 for (path, module) in global_store.modules.clone() {
224 let mut resolved = Vec::new();
225
226 for stmt in &module.statements {
227 let stmt = stmt.clone();
228
229 match &stmt.kind {
230 StatementKind::Let { name } => {
231 let resolved_stmt = resolve_let(&stmt, name, &module, &path, global_store);
232 resolved.push(resolved_stmt);
233 }
234
235 StatementKind::Trigger {
236 entity,
237 duration,
238 effects,
239 } => {
240 let resolved_stmt = resolve_trigger(
241 &stmt,
242 entity.as_str(),
243 &mut duration.clone(),
244 effects.clone(),
245 &module,
246 &path,
247 global_store,
248 );
249 resolved.push(resolved_stmt);
250 }
251
252 StatementKind::Loop => {
253 let resolved_stmt = resolve_loop(&stmt, &module, &path, global_store);
254 resolved.push(resolved_stmt);
255 }
256
257 StatementKind::Bank { .. } => {
258 let resolved_stmt = resolve_bank(&stmt, &module, &path, global_store);
259 resolved.push(resolved_stmt);
260 }
261
262 StatementKind::Tempo => {
263 let resolved_stmt = resolve_tempo(&stmt, &module, &path, global_store);
264 resolved.push(resolved_stmt);
265 }
266
267 StatementKind::Import { .. } | StatementKind::Export { .. } => {
268 resolved.push(stmt.clone());
269 }
270
271 StatementKind::Call { name, args } => {
272 let resolved_stmt = resolve_call(
273 &stmt,
274 name.clone(),
275 args.clone(),
276 &module,
277 &path,
278 global_store,
279 );
280 resolved.push(resolved_stmt);
281 }
282
283 StatementKind::Spawn { name, args } => {
284 let resolved_stmt = resolve_spawn(
285 &stmt,
286 name.clone(),
287 args.clone(),
288 &module,
289 &path,
290 global_store,
291 );
292 resolved.push(resolved_stmt);
293 }
294
295 StatementKind::Group => {
296 let resolved_stmt = resolve_group(&stmt, &module, &path, global_store);
297 resolved.push(resolved_stmt);
298 }
299
300 StatementKind::Pattern { .. } => {
301 let resolved_stmt = resolve_pattern(&stmt, &module, &path, global_store);
302 resolved.push(resolved_stmt);
303 }
304
305 StatementKind::Function {
306 name: _,
307 parameters: _,
308 body: _,
309 } => {
310 let resolved_function = resolve_function(&stmt, &module, &path, global_store);
311 resolved.push(resolved_function);
312 }
313
314 _ => {
315 resolved.push(stmt);
316 }
317 }
318 }
319
320 resolved_map.insert(path.clone(), resolved);
321 }
322
323 resolved_map
324}