@devaloop/devalang 0.0.1-alpha.14 → 0.0.1-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/.devalang +10 -8
  2. package/.github/workflows/ci.yml +92 -0
  3. package/Cargo.toml +60 -58
  4. package/README.md +32 -15
  5. package/docs/CHANGELOG.md +93 -1
  6. package/docs/CONTRIBUTING.md +101 -1
  7. package/docs/ROADMAP.md +2 -2
  8. package/docs/TODO.md +1 -1
  9. package/examples/automation.deva +42 -0
  10. package/examples/bank.deva +4 -4
  11. package/examples/events.deva +12 -0
  12. package/examples/function.deva +4 -4
  13. package/examples/index.deva +39 -25
  14. package/examples/loop.deva +5 -11
  15. package/examples/pattern.deva +8 -0
  16. package/examples/plugin.deva +16 -0
  17. package/examples/variables.deva +1 -1
  18. package/out-tsc/bin/index.js +51 -7
  19. package/out-tsc/index.js +3 -1
  20. package/out-tsc/scripts/postbuild.js +9 -10
  21. package/out-tsc/scripts/postinstall.js +49 -0
  22. package/package.json +12 -4
  23. package/project-version.json +3 -3
  24. package/rust/cli/bank.rs +462 -456
  25. package/rust/cli/build.rs +252 -199
  26. package/rust/cli/check.rs +221 -180
  27. package/rust/cli/driver.rs +297 -292
  28. package/rust/cli/generator.rs +1 -0
  29. package/rust/cli/init.rs +87 -79
  30. package/rust/cli/install.rs +35 -32
  31. package/rust/cli/login.rs +127 -134
  32. package/rust/cli/mod.rs +13 -11
  33. package/rust/cli/play.rs +1123 -218
  34. package/rust/cli/telemetry.rs +19 -0
  35. package/rust/cli/template.rs +69 -57
  36. package/rust/cli/update.rs +6 -4
  37. package/rust/common/api.rs +5 -8
  38. package/rust/common/cdn.rs +3 -6
  39. package/rust/common/mod.rs +3 -3
  40. package/rust/common/sso.rs +3 -6
  41. package/rust/config/driver.rs +118 -94
  42. package/rust/config/loader.rs +165 -156
  43. package/rust/config/mod.rs +4 -2
  44. package/rust/config/settings.rs +91 -0
  45. package/rust/config/stats.rs +257 -0
  46. package/rust/core/audio/engine.rs +696 -518
  47. package/rust/core/audio/evaluator.rs +263 -31
  48. package/rust/core/audio/interpreter/arrow_call.rs +198 -161
  49. package/rust/core/audio/interpreter/automate.rs +18 -0
  50. package/rust/core/audio/interpreter/call.rs +98 -95
  51. package/rust/core/audio/interpreter/condition.rs +70 -71
  52. package/rust/core/audio/interpreter/driver.rs +487 -198
  53. package/rust/core/audio/interpreter/function.rs +26 -21
  54. package/rust/core/audio/interpreter/let_.rs +38 -19
  55. package/rust/core/audio/interpreter/load.rs +18 -18
  56. package/rust/core/audio/interpreter/loop_.rs +113 -73
  57. package/rust/core/audio/interpreter/mod.rs +14 -13
  58. package/rust/core/audio/interpreter/sleep.rs +27 -30
  59. package/rust/core/audio/interpreter/spawn.rs +105 -102
  60. package/rust/core/audio/interpreter/tempo.rs +19 -16
  61. package/rust/core/audio/interpreter/trigger.rs +239 -210
  62. package/rust/core/audio/loader/mod.rs +1 -1
  63. package/rust/core/audio/loader/trigger.rs +100 -97
  64. package/rust/core/audio/mod.rs +7 -6
  65. package/rust/core/audio/player.rs +64 -64
  66. package/rust/core/audio/renderer.rs +56 -53
  67. package/rust/core/audio/special/easing.rs +189 -0
  68. package/rust/core/audio/special/env.rs +43 -0
  69. package/rust/core/audio/special/math.rs +102 -0
  70. package/rust/core/audio/special/mod.rs +9 -0
  71. package/rust/core/audio/special/modulator.rs +143 -0
  72. package/rust/core/builder/mod.rs +80 -85
  73. package/rust/core/debugger/lexer.rs +27 -27
  74. package/rust/core/debugger/mod.rs +24 -23
  75. package/rust/core/debugger/module.rs +55 -47
  76. package/rust/core/debugger/preprocessor.rs +27 -27
  77. package/rust/core/debugger/store.rs +40 -39
  78. package/rust/core/error/mod.rs +80 -66
  79. package/rust/core/lexer/handler/arrow.rs +82 -31
  80. package/rust/core/lexer/handler/at.rs +21 -21
  81. package/rust/core/lexer/handler/brace.rs +41 -41
  82. package/rust/core/lexer/handler/colon.rs +21 -21
  83. package/rust/core/lexer/handler/comment.rs +30 -30
  84. package/rust/core/lexer/handler/dot.rs +21 -21
  85. package/rust/core/lexer/handler/driver.rs +337 -263
  86. package/rust/core/lexer/handler/identifier.rs +46 -42
  87. package/rust/core/lexer/handler/indent.rs +66 -66
  88. package/rust/core/lexer/handler/mod.rs +16 -16
  89. package/rust/core/lexer/handler/newline.rs +23 -23
  90. package/rust/core/lexer/handler/number.rs +31 -31
  91. package/rust/core/lexer/handler/operator.rs +46 -44
  92. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  93. package/rust/core/lexer/handler/slash.rs +21 -21
  94. package/rust/core/lexer/handler/string.rs +63 -63
  95. package/rust/core/lexer/mod.rs +54 -51
  96. package/rust/core/lexer/token.rs +97 -91
  97. package/rust/core/mod.rs +11 -11
  98. package/rust/core/parser/driver.rs +513 -408
  99. package/rust/core/parser/handler/arrow_call.rs +233 -211
  100. package/rust/core/parser/handler/at.rs +245 -162
  101. package/rust/core/parser/handler/bank.rs +94 -69
  102. package/rust/core/parser/handler/condition.rs +80 -74
  103. package/rust/core/parser/handler/dot.rs +143 -135
  104. package/rust/core/parser/handler/identifier/automate.rs +257 -0
  105. package/rust/core/parser/handler/identifier/call.rs +91 -88
  106. package/rust/core/parser/handler/identifier/emit.rs +66 -0
  107. package/rust/core/parser/handler/identifier/function.rs +100 -92
  108. package/rust/core/parser/handler/identifier/group.rs +85 -75
  109. package/rust/core/parser/handler/identifier/let_.rs +158 -127
  110. package/rust/core/parser/handler/identifier/mod.rs +54 -52
  111. package/rust/core/parser/handler/identifier/on.rs +98 -0
  112. package/rust/core/parser/handler/identifier/print.rs +52 -0
  113. package/rust/core/parser/handler/identifier/sleep.rs +36 -33
  114. package/rust/core/parser/handler/identifier/spawn.rs +91 -88
  115. package/rust/core/parser/handler/identifier/synth.rs +65 -65
  116. package/rust/core/parser/handler/loop_.rs +170 -72
  117. package/rust/core/parser/handler/mod.rs +8 -8
  118. package/rust/core/parser/handler/tempo.rs +53 -47
  119. package/rust/core/parser/mod.rs +4 -4
  120. package/rust/core/parser/statement.rs +142 -108
  121. package/rust/core/plugin/loader.rs +123 -48
  122. package/rust/core/plugin/mod.rs +2 -1
  123. package/rust/core/plugin/runner.rs +296 -0
  124. package/rust/core/preprocessor/loader.rs +515 -326
  125. package/rust/core/preprocessor/mod.rs +4 -4
  126. package/rust/core/preprocessor/module.rs +60 -58
  127. package/rust/core/preprocessor/processor.rs +99 -101
  128. package/rust/core/preprocessor/resolver/bank.rs +51 -49
  129. package/rust/core/preprocessor/resolver/call.rs +100 -100
  130. package/rust/core/preprocessor/resolver/condition.rs +97 -97
  131. package/rust/core/preprocessor/resolver/driver.rs +310 -278
  132. package/rust/core/preprocessor/resolver/function.rs +69 -78
  133. package/rust/core/preprocessor/resolver/group.rs +96 -91
  134. package/rust/core/preprocessor/resolver/let_.rs +32 -28
  135. package/rust/core/preprocessor/resolver/loop_.rs +320 -91
  136. package/rust/core/preprocessor/resolver/mod.rs +15 -15
  137. package/rust/core/preprocessor/resolver/spawn.rs +76 -92
  138. package/rust/core/preprocessor/resolver/synth.rs +56 -50
  139. package/rust/core/preprocessor/resolver/tempo.rs +50 -49
  140. package/rust/core/preprocessor/resolver/trigger.rs +113 -116
  141. package/rust/core/preprocessor/resolver/value.rs +81 -87
  142. package/rust/core/shared/bank.rs +1 -1
  143. package/rust/core/shared/duration.rs +9 -9
  144. package/rust/core/shared/mod.rs +3 -3
  145. package/rust/core/shared/value.rs +35 -32
  146. package/rust/core/store/function.rs +34 -34
  147. package/rust/core/store/global.rs +55 -38
  148. package/rust/core/store/mod.rs +5 -5
  149. package/rust/core/store/variable.rs +37 -34
  150. package/rust/core/utils/mod.rs +2 -2
  151. package/rust/core/utils/path.rs +37 -31
  152. package/rust/core/utils/validation.rs +35 -37
  153. package/rust/installer/addon.rs +84 -80
  154. package/rust/installer/bank.rs +62 -65
  155. package/rust/installer/mod.rs +5 -5
  156. package/rust/installer/plugin.rs +54 -55
  157. package/rust/installer/utils.rs +56 -56
  158. package/rust/lib.rs +156 -164
  159. package/rust/main.rs +250 -145
  160. package/rust/utils/error.rs +200 -0
  161. package/rust/utils/file.rs +38 -35
  162. package/rust/utils/first_usage.rs +76 -0
  163. package/rust/utils/logger.rs +195 -139
  164. package/rust/utils/mod.rs +9 -50
  165. package/rust/utils/signature.rs +19 -17
  166. package/rust/utils/spinner.rs +22 -19
  167. package/rust/utils/telemetry.rs +292 -0
  168. package/rust/utils/watcher.rs +34 -33
  169. package/templates/minimal/README.md +97 -121
  170. package/templates/welcome/README.md +97 -121
  171. package/typescript/bin/index.ts +19 -5
  172. package/typescript/index.ts +3 -1
  173. package/typescript/scripts/postbuild.ts +10 -6
  174. package/typescript/scripts/postinstall.ts +56 -0
  175. package/typescript/scripts/version/bump.ts +0 -1
  176. package/typescript/scripts/version/index.ts +0 -1
  177. package/out-tsc/bin/devalang.exe +0 -0
@@ -1,278 +1,310 @@
1
- use std::collections::HashMap;
2
- use 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
-
27
- pub 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
-
33
- pub 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
-
72
- fn 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
- eprintln!("⚠️ Unresolved identifier '{}'", name);
84
- Value::Null
85
- }
86
-
87
- Value::Beat(beat_str) => {
88
- println!("[warn] '{:?}': unresolved beat '{}'", module.path, beat_str);
89
- Value::Beat(beat_str.clone())
90
- }
91
-
92
- Value::Map(map) => {
93
- let mut resolved = HashMap::new();
94
- for (k, v) in map {
95
- resolved.insert(k.clone(), resolve_value(v, module, global_store));
96
- }
97
- Value::Map(resolved)
98
- }
99
-
100
- Value::Block(stmts) => {
101
- let resolved_stmts = stmts
102
- .iter()
103
- .map(|stmt| resolve_statement(stmt, module, &module.path, global_store))
104
- .collect();
105
- Value::Block(resolved_stmts)
106
- }
107
-
108
- other => other.clone(),
109
- }
110
- }
111
-
112
- fn find_export_value(name: &str, global_store: &GlobalStore) -> Option<Value> {
113
- for (_path, module) in &global_store.modules {
114
- if let Some(val) = module.export_table.get_export(name) {
115
- return Some(val.clone());
116
- }
117
- }
118
- None
119
- }
120
-
121
- pub fn resolve_imports(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
122
- for (module_path, module) in global_store.clone().modules.iter_mut() {
123
- for (name, source_path) in &module.import_table.imports {
124
- match source_path {
125
- Value::String(source_path) => {
126
- if let Some(source_module) = global_store.modules.get(source_path) {
127
- if let Some(value) = source_module.export_table.get_export(name) {
128
- module.variable_table.set(name.clone(), value.clone());
129
- } else {
130
- println!(
131
- "[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"
132
- );
133
- }
134
- } else {
135
- println!(
136
- "[warn] '{module_path}': cannot find source module '{source_path}'"
137
- );
138
- }
139
- }
140
- _ => {
141
- println!(
142
- "[warn] '{module_path}': expected string for import source, found {:?}",
143
- source_path
144
- );
145
- }
146
- }
147
- }
148
- }
149
- }
150
-
151
- pub fn resolve_and_flatten_all_modules(
152
- global_store: &mut GlobalStore
153
- ) -> HashMap<String, Vec<Statement>> {
154
- let logger = Logger::new();
155
- let snapshot = global_store.clone();
156
-
157
- // 1. Imports resolution
158
- for (module_path, module) in global_store.modules.iter_mut() {
159
- for (name, source_path) in &module.import_table.imports {
160
- if let Value::String(source_path_str) = source_path {
161
- match snapshot.modules.get(source_path_str) {
162
- Some(source_module) => {
163
- if let Some(value) = source_module.export_table.get_export(name) {
164
- module.variable_table.set(name.clone(), value.clone());
165
- } else {
166
- logger.log_error_with_stacktrace(
167
- &format!("'{name}' not found in exports of '{source_path_str}'"),
168
- module_path
169
- );
170
- }
171
- }
172
- None => {
173
- logger.log_error_with_stacktrace(
174
- &format!("Cannot find source module '{source_path_str}'"),
175
- module_path
176
- );
177
- }
178
- }
179
- } else {
180
- logger.log_error_with_stacktrace(
181
- &format!("Expected string for import source, found {:?}", source_path),
182
- module_path
183
- );
184
- }
185
- }
186
- }
187
-
188
- // 2. Statements resolution
189
- let mut resolved_map: HashMap<String, Vec<Statement>> = HashMap::new();
190
- for (path, module) in global_store.modules.clone() {
191
- let mut resolved = Vec::new();
192
-
193
- for stmt in &module.statements {
194
- let stmt = stmt.clone();
195
-
196
- match &stmt.kind {
197
- StatementKind::Let { name } => {
198
- let resolved_stmt = resolve_let(&stmt, name, &module, &path, global_store);
199
- resolved.push(resolved_stmt);
200
- }
201
-
202
- StatementKind::Trigger { entity, duration, effects } => {
203
- let resolved_stmt = resolve_trigger(
204
- &stmt,
205
- entity.as_str(),
206
- &mut duration.clone(),
207
- effects.clone(),
208
- &module,
209
- &path,
210
- global_store
211
- );
212
- resolved.push(resolved_stmt);
213
- }
214
-
215
- StatementKind::Loop => {
216
- let resolved_stmt = resolve_loop(&stmt, &module, &path, global_store);
217
- resolved.push(resolved_stmt);
218
- }
219
-
220
- StatementKind::Bank => {
221
- let resolved_stmt = resolve_bank(&stmt, &module, &path, global_store);
222
- resolved.push(resolved_stmt);
223
- }
224
-
225
- StatementKind::Tempo => {
226
- let resolved_stmt = resolve_tempo(&stmt, &module, &path, global_store);
227
- resolved.push(resolved_stmt);
228
- }
229
-
230
- StatementKind::Import { .. } | StatementKind::Export { .. } => {
231
- resolved.push(stmt.clone());
232
- }
233
-
234
- StatementKind::Call { name, args } => {
235
- let resolved_stmt = resolve_call(
236
- &stmt,
237
- name.clone(),
238
- args.clone(),
239
- &module,
240
- &path,
241
- global_store
242
- );
243
- resolved.push(resolved_stmt);
244
- }
245
-
246
- StatementKind::Spawn { name, args } => {
247
- let resolved_stmt = resolve_spawn(
248
- &stmt,
249
- name.clone(),
250
- args.clone(),
251
- &module,
252
- &path,
253
- global_store
254
- );
255
- resolved.push(resolved_stmt);
256
- }
257
-
258
- StatementKind::Group => {
259
- let resolved_stmt = resolve_group(&stmt, &module, &path, global_store);
260
- resolved.push(resolved_stmt);
261
- }
262
-
263
- StatementKind::Function { name, parameters, body } => {
264
- let resolved_function = resolve_function(&stmt, &module, &path, global_store);
265
- resolved.push(resolved_function);
266
- }
267
-
268
- _ => {
269
- resolved.push(stmt);
270
- }
271
- }
272
- }
273
-
274
- resolved_map.insert(path.clone(), resolved);
275
- }
276
-
277
- resolved_map
278
- }
1
+ use crate::{
2
+ core::{
3
+ parser::statement::{Statement, StatementKind},
4
+ preprocessor::{
5
+ loader::ModuleLoader,
6
+ module::Module,
7
+ resolver::{
8
+ bank::resolve_bank, call::resolve_call, condition::resolve_condition,
9
+ function::resolve_function, group::resolve_group, let_::resolve_let,
10
+ loop_::resolve_loop, spawn::resolve_spawn, tempo::resolve_tempo,
11
+ trigger::resolve_trigger,
12
+ },
13
+ },
14
+ shared::value::Value,
15
+ store::global::GlobalStore,
16
+ },
17
+ utils::logger::Logger,
18
+ };
19
+ use std::collections::HashMap;
20
+
21
+ pub fn resolve_all_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
22
+ for _module in global_store.clone().modules.values_mut() {
23
+ resolve_imports(module_loader, global_store);
24
+ }
25
+ }
26
+
27
+ pub fn resolve_statement(
28
+ stmt: &Statement,
29
+ module: &Module,
30
+ path: &str,
31
+ global_store: &mut GlobalStore,
32
+ ) -> Statement {
33
+ match &stmt.kind {
34
+ StatementKind::On { event, args, body } => {
35
+ let resolved_body: Vec<Statement> = body
36
+ .iter()
37
+ .map(|s| resolve_statement(s, module, path, global_store))
38
+ .collect();
39
+ Statement {
40
+ kind: StatementKind::On {
41
+ event: event.clone(),
42
+ args: args.clone(),
43
+ body: resolved_body,
44
+ },
45
+ value: resolve_value(&stmt.value, module, global_store),
46
+ ..stmt.clone()
47
+ }
48
+ }
49
+ StatementKind::Emit { event, payload: _ } => Statement {
50
+ kind: StatementKind::Emit {
51
+ event: event.clone(),
52
+ payload: Some(resolve_value(&stmt.value, module, global_store)),
53
+ },
54
+ value: resolve_value(&stmt.value, module, global_store),
55
+ ..stmt.clone()
56
+ },
57
+ StatementKind::Trigger {
58
+ entity,
59
+ duration,
60
+ effects,
61
+ } => resolve_trigger(
62
+ stmt,
63
+ entity,
64
+ &mut duration.clone(),
65
+ effects.clone(),
66
+ module,
67
+ path,
68
+ global_store,
69
+ ),
70
+ StatementKind::If => resolve_condition(stmt, module, path, global_store),
71
+ StatementKind::Group => resolve_group(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
+
94
+ fn resolve_value(value: &Value, module: &Module, global_store: &mut GlobalStore) -> Value {
95
+ match value {
96
+ Value::Identifier(name) => {
97
+ if let Some(original_val) = module.variable_table.get(name) {
98
+ return resolve_value(original_val, module, global_store);
99
+ }
100
+
101
+ if let Some(export_val) = find_export_value(name, global_store) {
102
+ return resolve_value(&export_val, module, global_store);
103
+ }
104
+
105
+ // Leave unresolved identifiers as-is; they might be runtime-bound (e.g., foreach vars)
106
+ Value::Identifier(name.clone())
107
+ }
108
+
109
+ Value::String(s) => Value::String(s.clone()),
110
+
111
+ Value::Beat(beat_str) => {
112
+ println!("[warn] '{:?}': unresolved beat '{}'", module.path, beat_str);
113
+ Value::Beat(beat_str.clone())
114
+ }
115
+
116
+ Value::Map(map) => {
117
+ let mut resolved = HashMap::new();
118
+ for (k, v) in map {
119
+ resolved.insert(k.clone(), resolve_value(v, module, global_store));
120
+ }
121
+ Value::Map(resolved)
122
+ }
123
+
124
+ Value::Block(stmts) => {
125
+ let resolved_stmts = stmts
126
+ .iter()
127
+ .map(|stmt| resolve_statement(stmt, module, &module.path, global_store))
128
+ .collect();
129
+ Value::Block(resolved_stmts)
130
+ }
131
+
132
+ other => other.clone(),
133
+ }
134
+ }
135
+
136
+ fn find_export_value(name: &str, global_store: &GlobalStore) -> Option<Value> {
137
+ for (_path, module) in &global_store.modules {
138
+ if let Some(val) = module.export_table.get_export(name) {
139
+ return Some(val.clone());
140
+ }
141
+ }
142
+ None
143
+ }
144
+
145
+ pub fn resolve_imports(_module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
146
+ for (module_path, module) in global_store.clone().modules.iter_mut() {
147
+ for (name, source_path) in &module.import_table.imports {
148
+ match source_path {
149
+ Value::String(source_path) => {
150
+ if let Some(source_module) = global_store.modules.get(source_path) {
151
+ if let Some(value) = source_module.export_table.get_export(name) {
152
+ module.variable_table.set(name.clone(), value.clone());
153
+ } else {
154
+ println!(
155
+ "[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"
156
+ );
157
+ }
158
+ } else {
159
+ println!(
160
+ "[warn] '{module_path}': cannot find source module '{source_path}'"
161
+ );
162
+ }
163
+ }
164
+ _ => {
165
+ println!(
166
+ "[warn] '{module_path}': expected string for import source, found {:?}",
167
+ source_path
168
+ );
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }
174
+
175
+ pub fn resolve_and_flatten_all_modules(
176
+ global_store: &mut GlobalStore,
177
+ ) -> HashMap<String, Vec<Statement>> {
178
+ let logger = Logger::new();
179
+ let snapshot = global_store.clone();
180
+
181
+ // 1. Imports resolution
182
+ for (module_path, module) in global_store.modules.iter_mut() {
183
+ for (name, source_path) in &module.import_table.imports {
184
+ if let Value::String(source_path_str) = source_path {
185
+ match snapshot.modules.get(source_path_str) {
186
+ Some(source_module) => {
187
+ if let Some(value) = source_module.export_table.get_export(name) {
188
+ module.variable_table.set(name.clone(), value.clone());
189
+ } else {
190
+ logger.log_error_with_stacktrace(
191
+ &format!("'{name}' not found in exports of '{source_path_str}'"),
192
+ module_path,
193
+ );
194
+ }
195
+ }
196
+ None => {
197
+ logger.log_error_with_stacktrace(
198
+ &format!("Cannot find source module '{source_path_str}'"),
199
+ module_path,
200
+ );
201
+ }
202
+ }
203
+ } else {
204
+ logger.log_error_with_stacktrace(
205
+ &format!("Expected string for import source, found {:?}", source_path),
206
+ module_path,
207
+ );
208
+ }
209
+ }
210
+ }
211
+
212
+ // 2. Statements resolution
213
+ let mut resolved_map: HashMap<String, Vec<Statement>> = HashMap::new();
214
+ for (path, module) in global_store.modules.clone() {
215
+ let mut resolved = Vec::new();
216
+
217
+ for stmt in &module.statements {
218
+ let stmt = stmt.clone();
219
+
220
+ match &stmt.kind {
221
+ StatementKind::Let { name } => {
222
+ let resolved_stmt = resolve_let(&stmt, name, &module, &path, global_store);
223
+ resolved.push(resolved_stmt);
224
+ }
225
+
226
+ StatementKind::Trigger {
227
+ entity,
228
+ duration,
229
+ effects,
230
+ } => {
231
+ let resolved_stmt = resolve_trigger(
232
+ &stmt,
233
+ entity.as_str(),
234
+ &mut duration.clone(),
235
+ effects.clone(),
236
+ &module,
237
+ &path,
238
+ global_store,
239
+ );
240
+ resolved.push(resolved_stmt);
241
+ }
242
+
243
+ StatementKind::Loop => {
244
+ let resolved_stmt = resolve_loop(&stmt, &module, &path, global_store);
245
+ resolved.push(resolved_stmt);
246
+ }
247
+
248
+ StatementKind::Bank { .. } => {
249
+ let resolved_stmt = resolve_bank(&stmt, &module, &path, global_store);
250
+ resolved.push(resolved_stmt);
251
+ }
252
+
253
+ StatementKind::Tempo => {
254
+ let resolved_stmt = resolve_tempo(&stmt, &module, &path, global_store);
255
+ resolved.push(resolved_stmt);
256
+ }
257
+
258
+ StatementKind::Import { .. } | StatementKind::Export { .. } => {
259
+ resolved.push(stmt.clone());
260
+ }
261
+
262
+ StatementKind::Call { name, args } => {
263
+ let resolved_stmt = resolve_call(
264
+ &stmt,
265
+ name.clone(),
266
+ args.clone(),
267
+ &module,
268
+ &path,
269
+ global_store,
270
+ );
271
+ resolved.push(resolved_stmt);
272
+ }
273
+
274
+ StatementKind::Spawn { name, args } => {
275
+ let resolved_stmt = resolve_spawn(
276
+ &stmt,
277
+ name.clone(),
278
+ args.clone(),
279
+ &module,
280
+ &path,
281
+ global_store,
282
+ );
283
+ resolved.push(resolved_stmt);
284
+ }
285
+
286
+ StatementKind::Group => {
287
+ let resolved_stmt = resolve_group(&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
+ }