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