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, pattern::resolve_pattern, let_::resolve_let,
9 loop_::resolve_loop, spawn::resolve_spawn, tempo::resolve_tempo,
10 trigger::resolve_trigger,
11 },
12 },
13 store::global::GlobalStore,
14};
15use devalang_types::Value;
16use devalang_utils::logger::Logger;
17use devalang_utils::logger::LogLevel;
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(LogLevel::Warning, &format!("[warn] '{:?}': unresolved beat '{}'", module.path, beat_str));
114 Value::Beat(beat_str.clone())
115 }
116
117 Value::Map(map) => {
118 let mut resolved = HashMap::new();
119 for (k, v) in map {
120 resolved.insert(k.clone(), resolve_value(v, module, global_store));
121 }
122 Value::Map(resolved)
123 }
124
125 Value::Block(stmts) => {
126 let resolved_stmts = stmts
127 .iter()
128 .map(|stmt| resolve_statement(stmt, module, &module.path, global_store))
129 .collect();
130 Value::Block(resolved_stmts)
131 }
132
133 other => other.clone(),
134 }
135}
136
137fn find_export_value(name: &str, global_store: &GlobalStore) -> Option<Value> {
138 for module in global_store.modules.values() {
139 if let Some(val) = module.export_table.get_export(name) {
140 return Some(val.clone());
141 }
142 }
143 None
144}
145
146pub fn resolve_imports(_module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
147 let logger = Logger::new();
148 for (module_path, module) in global_store.clone().modules.iter_mut() {
149 for (name, source_path) in &module.import_table.imports {
150 match source_path {
151 Value::String(source_path) => {
152 if let Some(source_module) = global_store.modules.get(source_path) {
153 if let Some(value) = source_module.export_table.get_export(name) {
154 module.variable_table.set(name.clone(), value.clone());
155 } else {
156 logger.log_message(LogLevel::Warning, &format!("[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"));
157 }
158 } else {
159 logger.log_message(LogLevel::Warning, &format!("[warn] '{module_path}': cannot find source module '{source_path}'"));
160 }
161 }
162 _ => {
163 logger.log_message(LogLevel::Warning, &format!("[warn] '{module_path}': expected string for import source, found {:?}", source_path));
164 }
165 }
166 }
167 }
168}
169
170pub fn resolve_and_flatten_all_modules(
171 global_store: &mut GlobalStore,
172) -> HashMap<String, Vec<Statement>> {
173 let logger = Logger::new();
174 let snapshot = global_store.clone();
175
176 for (module_path, module) in global_store.modules.iter_mut() {
178 for (name, source_path) in &module.import_table.imports {
179 if let Value::String(source_path_str) = source_path {
180 match snapshot.modules.get(source_path_str) {
181 Some(source_module) => {
182 if let Some(value) = source_module.export_table.get_export(name) {
183 module.variable_table.set(name.clone(), value.clone());
184 } else {
185 logger.log_error_with_stacktrace(
186 &format!("'{name}' not found in exports of '{source_path_str}'"),
187 module_path,
188 );
189 }
190 }
191 None => {
192 logger.log_error_with_stacktrace(
193 &format!("Cannot find source module '{source_path_str}'"),
194 module_path,
195 );
196 }
197 }
198 } else {
199 logger.log_error_with_stacktrace(
200 &format!("Expected string for import source, found {:?}", source_path),
201 module_path,
202 );
203 }
204 }
205 }
206
207 let mut resolved_map: HashMap<String, Vec<Statement>> = HashMap::new();
209 for (path, module) in global_store.modules.clone() {
210 let mut resolved = Vec::new();
211
212 for stmt in &module.statements {
213 let stmt = stmt.clone();
214
215 match &stmt.kind {
216 StatementKind::Let { name } => {
217 let resolved_stmt = resolve_let(&stmt, name, &module, &path, global_store);
218 resolved.push(resolved_stmt);
219 }
220
221 StatementKind::Trigger {
222 entity,
223 duration,
224 effects,
225 } => {
226 let resolved_stmt = resolve_trigger(
227 &stmt,
228 entity.as_str(),
229 &mut duration.clone(),
230 effects.clone(),
231 &module,
232 &path,
233 global_store,
234 );
235 resolved.push(resolved_stmt);
236 }
237
238 StatementKind::Loop => {
239 let resolved_stmt = resolve_loop(&stmt, &module, &path, global_store);
240 resolved.push(resolved_stmt);
241 }
242
243 StatementKind::Bank { .. } => {
244 let resolved_stmt = resolve_bank(&stmt, &module, &path, global_store);
245 resolved.push(resolved_stmt);
246 }
247
248 StatementKind::Tempo => {
249 let resolved_stmt = resolve_tempo(&stmt, &module, &path, global_store);
250 resolved.push(resolved_stmt);
251 }
252
253 StatementKind::Import { .. } | StatementKind::Export { .. } => {
254 resolved.push(stmt.clone());
255 }
256
257 StatementKind::Call { name, args } => {
258 let resolved_stmt = resolve_call(
259 &stmt,
260 name.clone(),
261 args.clone(),
262 &module,
263 &path,
264 global_store,
265 );
266 resolved.push(resolved_stmt);
267 }
268
269 StatementKind::Spawn { name, args } => {
270 let resolved_stmt = resolve_spawn(
271 &stmt,
272 name.clone(),
273 args.clone(),
274 &module,
275 &path,
276 global_store,
277 );
278 resolved.push(resolved_stmt);
279 }
280
281 StatementKind::Group => {
282 let resolved_stmt = resolve_group(&stmt, &module, &path, global_store);
283 resolved.push(resolved_stmt);
284 }
285
286 StatementKind::Pattern { .. } => {
287 let resolved_stmt = resolve_pattern(&stmt, &module, &path, global_store);
288 resolved.push(resolved_stmt);
289 }
290
291 StatementKind::Function {
292 name: _,
293 parameters: _,
294 body: _,
295 } => {
296 let resolved_function = resolve_function(&stmt, &module, &path, global_store);
297 resolved.push(resolved_function);
298 }
299
300 _ => {
301 resolved.push(stmt);
302 }
303 }
304 }
305
306 resolved_map.insert(path.clone(), resolved);
307 }
308
309 resolved_map
310}