@devaloop/devalang 0.0.1-alpha.16-hotfix.3 → 0.0.1-alpha.18

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 (239) hide show
  1. package/.cargo/config.toml +2 -0
  2. package/.devalang +10 -10
  3. package/.github/workflows/ci.yml +0 -1
  4. package/Cargo.toml +18 -2
  5. package/README.md +82 -34
  6. package/docs/CHANGELOG.md +91 -0
  7. package/docs/ROADMAP.md +7 -4
  8. package/docs/TODO.md +1 -1
  9. package/examples/index.deva +55 -35
  10. package/examples/pattern.deva +5 -5
  11. package/out-tsc/bin/index.d.ts +2 -0
  12. package/out-tsc/core/functions/index.d.ts +37 -0
  13. package/out-tsc/core/functions/index.js +76 -0
  14. package/out-tsc/core/index.d.ts +6 -0
  15. package/out-tsc/core/index.js +22 -0
  16. package/out-tsc/core/types/index.d.ts +4 -0
  17. package/out-tsc/core/types/index.js +20 -0
  18. package/out-tsc/core/types/plugin.d.ts +18 -0
  19. package/out-tsc/core/types/plugin.js +2 -0
  20. package/out-tsc/core/types/result.d.ts +27 -0
  21. package/out-tsc/core/types/result.js +2 -0
  22. package/out-tsc/core/types/statement.d.ts +106 -0
  23. package/out-tsc/core/types/statement.js +2 -0
  24. package/out-tsc/core/types/value.d.ts +43 -0
  25. package/out-tsc/core/types/value.js +2 -0
  26. package/out-tsc/index.d.ts +7 -0
  27. package/out-tsc/index.js +41 -2
  28. package/out-tsc/pkg/devalang_core.d.ts +7 -0
  29. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
  30. package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
  31. package/out-tsc/scripts/copy-wasm-dts.js +73 -0
  32. package/out-tsc/scripts/postinstall.d.ts +1 -0
  33. package/out-tsc/scripts/postinstall.js +33 -23
  34. package/out-tsc/scripts/version/bump.d.ts +1 -0
  35. package/out-tsc/scripts/version/fetch.d.ts +1 -0
  36. package/out-tsc/scripts/version/index.d.ts +1 -0
  37. package/out-tsc/scripts/version/sync.d.ts +1 -0
  38. package/package.json +16 -4
  39. package/project-version.json +3 -3
  40. package/rust/cli/bank/api.rs +122 -0
  41. package/rust/cli/bank/commands.rs +275 -0
  42. package/rust/cli/bank/mod.rs +29 -0
  43. package/rust/cli/build/commands.rs +107 -0
  44. package/rust/cli/build/mod.rs +2 -0
  45. package/rust/cli/build/process.rs +146 -0
  46. package/rust/cli/{check.rs → check/mod.rs} +18 -31
  47. package/rust/cli/discover/commands.rs +253 -0
  48. package/rust/cli/discover/config.rs +111 -0
  49. package/rust/cli/discover/fs.rs +19 -0
  50. package/rust/cli/discover/install.rs +103 -0
  51. package/rust/cli/discover/metadata.rs +48 -0
  52. package/rust/cli/discover/mod.rs +5 -0
  53. package/rust/cli/{init.rs → init/commands.rs} +88 -87
  54. package/rust/cli/init/mod.rs +1 -0
  55. package/rust/cli/install/addon.rs +126 -0
  56. package/rust/cli/install/bank.rs +53 -0
  57. package/rust/cli/{install.rs → install/commands.rs} +9 -9
  58. package/rust/{installer → cli/install}/mod.rs +2 -3
  59. package/rust/cli/install/plugin.rs +61 -0
  60. package/rust/cli/{login.rs → login/commands.rs} +8 -11
  61. package/rust/cli/login/mod.rs +1 -0
  62. package/rust/cli/mod.rs +2 -2
  63. package/rust/cli/{driver.rs → parser.rs} +7 -2
  64. package/rust/cli/play/commands.rs +324 -0
  65. package/rust/cli/play/io.rs +17 -0
  66. package/rust/cli/play/mod.rs +5 -0
  67. package/rust/cli/play/process.rs +150 -0
  68. package/rust/cli/play/realtime.rs +91 -0
  69. package/rust/cli/play/utils.rs +23 -0
  70. package/rust/cli/{telemetry.rs → telemetry/commands.rs} +4 -4
  71. package/rust/cli/telemetry/event_creator.rs +80 -0
  72. package/rust/cli/telemetry/mod.rs +3 -0
  73. package/rust/cli/telemetry/send.rs +51 -0
  74. package/rust/cli/{template.rs → template/commands.rs} +1 -1
  75. package/rust/cli/template/mod.rs +1 -0
  76. package/rust/cli/{update.rs → update/commands.rs} +6 -6
  77. package/rust/cli/update/mod.rs +1 -0
  78. package/rust/config/driver.rs +57 -72
  79. package/rust/config/mod.rs +1 -2
  80. package/rust/config/ops.rs +26 -0
  81. package/rust/config/settings.rs +40 -42
  82. package/rust/core/audio/engine/helpers.rs +158 -0
  83. package/rust/core/audio/engine/mod.rs +7 -0
  84. package/rust/core/audio/engine/sample.rs +359 -0
  85. package/rust/core/audio/engine/synth.rs +325 -0
  86. package/rust/core/audio/evaluator.rs +68 -27
  87. package/rust/core/audio/interpreter/arrow_call.rs +113 -33
  88. package/rust/core/audio/interpreter/call.rs +232 -56
  89. package/rust/core/audio/interpreter/condition.rs +3 -2
  90. package/rust/core/audio/interpreter/driver.rs +206 -151
  91. package/rust/core/audio/interpreter/let_.rs +1 -1
  92. package/rust/core/audio/interpreter/load.rs +2 -1
  93. package/rust/core/audio/interpreter/loop_.rs +7 -6
  94. package/rust/core/audio/interpreter/sleep.rs +2 -1
  95. package/rust/core/audio/interpreter/spawn.rs +186 -54
  96. package/rust/core/audio/interpreter/tempo.rs +31 -10
  97. package/rust/core/audio/interpreter/trigger.rs +2 -2
  98. package/rust/core/audio/loader/trigger.rs +4 -7
  99. package/rust/core/audio/player.rs +6 -0
  100. package/rust/core/audio/renderer.rs +5 -7
  101. package/rust/core/audio/special/env.rs +3 -1
  102. package/rust/core/audio/special/math.rs +26 -6
  103. package/rust/core/audio/special/modulator.rs +2 -2
  104. package/rust/core/builder/mod.rs +9 -3
  105. package/rust/core/debugger/lexer.rs +1 -1
  106. package/rust/core/debugger/mod.rs +6 -0
  107. package/rust/core/debugger/module.rs +4 -4
  108. package/rust/core/debugger/preprocessor.rs +1 -1
  109. package/rust/core/debugger/store.rs +2 -2
  110. package/rust/core/error/mod.rs +189 -0
  111. package/rust/core/lexer/driver.rs +61 -0
  112. package/rust/core/lexer/handler/arrow.rs +1 -1
  113. package/rust/core/lexer/handler/at.rs +1 -1
  114. package/rust/core/lexer/handler/brace.rs +2 -2
  115. package/rust/core/lexer/handler/colon.rs +1 -1
  116. package/rust/core/lexer/handler/comment.rs +1 -1
  117. package/rust/core/lexer/handler/dot.rs +1 -1
  118. package/rust/core/lexer/handler/driver.rs +1 -1
  119. package/rust/core/lexer/handler/identifier.rs +4 -3
  120. package/rust/core/lexer/handler/mod.rs +1 -2
  121. package/rust/core/lexer/handler/number.rs +1 -1
  122. package/rust/core/lexer/handler/operator.rs +1 -1
  123. package/rust/core/lexer/handler/parenthesis.rs +2 -2
  124. package/rust/core/lexer/handler/slash.rs +1 -1
  125. package/rust/core/lexer/handler/string.rs +1 -1
  126. package/rust/core/lexer/mod.rs +1 -52
  127. package/rust/core/lexer/token.rs +91 -97
  128. package/rust/core/mod.rs +0 -1
  129. package/rust/core/parser/driver.rs +78 -22
  130. package/rust/core/parser/handler/arrow_call.rs +28 -8
  131. package/rust/core/parser/handler/at.rs +55 -21
  132. package/rust/core/parser/handler/bank.rs +14 -4
  133. package/rust/core/parser/handler/condition.rs +6 -3
  134. package/rust/core/parser/handler/dot.rs +5 -3
  135. package/rust/core/parser/handler/identifier/automate.rs +13 -16
  136. package/rust/core/parser/handler/identifier/call.rs +4 -4
  137. package/rust/core/parser/handler/identifier/emit.rs +9 -5
  138. package/rust/core/parser/handler/identifier/function.rs +20 -7
  139. package/rust/core/parser/handler/identifier/group.rs +11 -7
  140. package/rust/core/parser/handler/identifier/let_.rs +24 -9
  141. package/rust/core/parser/handler/identifier/mod.rs +6 -5
  142. package/rust/core/parser/handler/identifier/on.rs +16 -7
  143. package/rust/core/parser/handler/identifier/print.rs +6 -9
  144. package/rust/core/parser/handler/identifier/sleep.rs +12 -5
  145. package/rust/core/parser/handler/identifier/spawn.rs +4 -4
  146. package/rust/core/parser/handler/identifier/synth.rs +79 -9
  147. package/rust/core/parser/handler/loop_.rs +38 -13
  148. package/rust/core/parser/handler/mod.rs +1 -0
  149. package/rust/core/parser/handler/pattern.rs +74 -0
  150. package/rust/core/parser/handler/tempo.rs +9 -5
  151. package/rust/core/parser/mod.rs +0 -1
  152. package/rust/core/parser/statement.rs +6 -137
  153. package/rust/core/plugin/loader.rs +41 -27
  154. package/rust/core/plugin/runner.rs +68 -17
  155. package/rust/core/preprocessor/loader.rs +181 -99
  156. package/rust/core/preprocessor/processor.rs +9 -9
  157. package/rust/core/preprocessor/resolver/bank.rs +6 -8
  158. package/rust/core/preprocessor/resolver/call.rs +47 -23
  159. package/rust/core/preprocessor/resolver/condition.rs +6 -8
  160. package/rust/core/preprocessor/resolver/driver.rs +28 -28
  161. package/rust/core/preprocessor/resolver/function.rs +6 -6
  162. package/rust/core/preprocessor/resolver/group.rs +6 -8
  163. package/rust/core/preprocessor/resolver/loop_.rs +8 -10
  164. package/rust/core/preprocessor/resolver/mod.rs +1 -0
  165. package/rust/core/preprocessor/resolver/pattern.rs +75 -0
  166. package/rust/core/preprocessor/resolver/spawn.rs +45 -22
  167. package/rust/core/preprocessor/resolver/synth.rs +6 -8
  168. package/rust/core/preprocessor/resolver/tempo.rs +6 -8
  169. package/rust/core/preprocessor/resolver/trigger.rs +22 -19
  170. package/rust/core/preprocessor/resolver/value.rs +99 -4
  171. package/rust/core/store/export.rs +28 -28
  172. package/rust/core/store/function.rs +6 -0
  173. package/rust/core/store/global.rs +7 -1
  174. package/rust/core/store/import.rs +28 -28
  175. package/rust/core/store/variable.rs +16 -2
  176. package/rust/core/utils/mod.rs +0 -1
  177. package/rust/lib.rs +102 -9
  178. package/rust/main.rs +159 -45
  179. package/rust/types/Cargo.toml +11 -0
  180. package/rust/types/src/addons.rs +55 -0
  181. package/rust/types/src/ast.rs +202 -0
  182. package/rust/types/src/config.rs +74 -0
  183. package/rust/types/src/lib.rs +12 -0
  184. package/rust/types/src/telemetry.rs +85 -0
  185. package/rust/utils/Cargo.toml +26 -0
  186. package/rust/utils/{error.rs → src/error.rs} +186 -200
  187. package/rust/utils/src/file.rs +94 -0
  188. package/rust/utils/src/first_usage.rs +97 -0
  189. package/rust/utils/{mod.rs → src/lib.rs} +1 -1
  190. package/rust/utils/{logger.rs → src/logger.rs} +17 -12
  191. package/rust/utils/src/path.rs +88 -0
  192. package/rust/utils/src/signature.rs +41 -0
  193. package/rust/utils/{spinner.rs → src/spinner.rs} +3 -5
  194. package/rust/utils/src/version.rs +27 -0
  195. package/rust/utils/{watcher.rs → src/watcher.rs} +13 -1
  196. package/rust/web/cdn.rs +34 -0
  197. package/templates/minimal/README.md +98 -54
  198. package/templates/welcome/README.md +98 -54
  199. package/templates/welcome/src/index.deva +56 -8
  200. package/templates/welcome/src/variables.deva +2 -4
  201. package/tests/rust/TODO.md +0 -0
  202. package/tests/typescript/index.spec.ts +136 -0
  203. package/tests/typescript/playhead.spec.ts +36 -0
  204. package/tests/typescript/render_e2e.spec.ts +77 -0
  205. package/tsconfig.json +1 -1
  206. package/typescript/core/functions/index.ts +83 -0
  207. package/typescript/core/index.ts +6 -0
  208. package/typescript/core/types/index.ts +4 -0
  209. package/typescript/core/types/plugin.ts +19 -0
  210. package/typescript/core/types/result.ts +29 -0
  211. package/typescript/core/types/statement.ts +47 -0
  212. package/typescript/core/types/value.ts +29 -0
  213. package/typescript/index.ts +7 -2
  214. package/typescript/pkg/devalang_core.d.ts +4 -0
  215. package/typescript/scripts/copy-wasm-dts.ts +41 -0
  216. package/rust/cli/bank.rs +0 -462
  217. package/rust/cli/build.rs +0 -252
  218. package/rust/cli/play.rs +0 -1123
  219. package/rust/common/cdn.rs +0 -5
  220. package/rust/config/loader.rs +0 -165
  221. package/rust/config/stats.rs +0 -257
  222. package/rust/core/audio/engine.rs +0 -696
  223. package/rust/core/shared/bank.rs +0 -21
  224. package/rust/core/shared/duration.rs +0 -9
  225. package/rust/core/shared/mod.rs +0 -3
  226. package/rust/core/shared/value.rs +0 -35
  227. package/rust/core/utils/validation.rs +0 -35
  228. package/rust/installer/addon.rs +0 -84
  229. package/rust/installer/bank.rs +0 -62
  230. package/rust/installer/plugin.rs +0 -54
  231. package/rust/installer/utils.rs +0 -56
  232. package/rust/utils/file.rs +0 -38
  233. package/rust/utils/first_usage.rs +0 -83
  234. package/rust/utils/signature.rs +0 -19
  235. package/rust/utils/telemetry.rs +0 -292
  236. package/rust/utils/version.rs +0 -15
  237. /package/rust/{common → web}/api.rs +0 -0
  238. /package/rust/{common → web}/mod.rs +0 -0
  239. /package/rust/{common → web}/sso.rs +0 -0
@@ -1,25 +1,23 @@
1
+ #[cfg(feature = "cli")]
1
2
  use crate::core::preprocessor::resolver::driver::{
2
- resolve_all_modules, resolve_and_flatten_all_modules,
3
+ resolve_all_modules,
4
+ resolve_and_flatten_all_modules,
3
5
  };
6
+ #[cfg(feature = "cli")]
4
7
  use crate::core::utils::path::resolve_relative_path;
5
- use crate::{
6
- config::loader::load_config,
7
- core::{
8
- error::ErrorHandler,
9
- lexer::{Lexer, token::Token},
10
- parser::{
11
- driver::Parser,
12
- statement::{Statement, StatementKind},
13
- },
14
- plugin::loader::load_plugin,
15
- preprocessor::{module::Module, processor::process_modules},
16
- shared::{bank::BankFile, value::Value},
17
- store::global::GlobalStore,
18
- utils::path::normalize_path,
19
- },
20
- utils::logger::Logger,
8
+ #[cfg_attr(not(feature = "cli"), allow(unused_imports))]
9
+ use crate::core::{
10
+ error::ErrorHandler,
11
+ lexer::{ token::Token, driver::Lexer },
12
+ parser::{ driver::Parser, statement::{ Statement, StatementKind } },
13
+ plugin::loader::load_plugin,
14
+ preprocessor::{ module::Module, processor::process_modules },
15
+ store::global::GlobalStore,
16
+ utils::path::normalize_path,
21
17
  };
22
- use std::{collections::HashMap, path::Path};
18
+ use devalang_types::{ BankFile, Value };
19
+ use devalang_utils::logger::{ LogLevel, Logger };
20
+ use std::{ collections::HashMap, path::Path };
23
21
 
24
22
  pub struct ModuleLoader {
25
23
  pub entry: String,
@@ -38,7 +36,7 @@ impl ModuleLoader {
38
36
  Self {
39
37
  entry: entry.to_string(),
40
38
  output: output.to_string(),
41
- base_dir: base_dir,
39
+ base_dir,
42
40
  }
43
41
  }
44
42
 
@@ -46,13 +44,16 @@ impl ModuleLoader {
46
44
  entry_path: &str,
47
45
  output_path: &str,
48
46
  content: &str,
49
- global_store: &mut GlobalStore,
47
+ global_store: &mut GlobalStore
50
48
  ) -> Self {
51
49
  let normalized_entry_path = normalize_path(entry_path);
52
50
 
53
- let mut module = Module::new(&entry_path);
51
+ let mut module = Module::new(entry_path);
54
52
  module.content = content.to_string();
55
53
 
54
+ // Insert a module stub containing the provided content into the
55
+ // global store. This is used by the WASM APIs and tests which
56
+ // operate on in-memory sources instead of files on disk.
56
57
  global_store.insert_module(normalized_entry_path.to_string(), module);
57
58
 
58
59
  Self {
@@ -64,18 +65,16 @@ impl ModuleLoader {
64
65
 
65
66
  pub fn extract_statements_map(
66
67
  &self,
67
- global_store: &GlobalStore,
68
+ global_store: &GlobalStore
68
69
  ) -> HashMap<String, Vec<Statement>> {
69
- global_store
70
- .modules
70
+ global_store.modules
71
71
  .iter()
72
72
  .map(|(path, module)| (path.clone(), module.statements.clone()))
73
73
  .collect()
74
74
  }
75
75
 
76
76
  pub fn load_single_module(&self, global_store: &mut GlobalStore) -> Result<Module, String> {
77
- let mut module = global_store
78
- .modules
77
+ let mut module = global_store.modules
79
78
  .remove(&self.entry)
80
79
  .ok_or_else(|| format!("Module not found in store for path: {}", self.entry))?;
81
80
 
@@ -102,9 +101,7 @@ impl ModuleLoader {
102
101
  self.load_plugin_and_register(&mut module, &plugin_name, &alias, global_store);
103
102
  }
104
103
 
105
- global_store
106
- .modules
107
- .insert(self.entry.clone(), module.clone());
104
+ global_store.modules.insert(self.entry.clone(), module.clone());
108
105
 
109
106
  // SECTION Error handling
110
107
  let mut error_handler = ErrorHandler::new();
@@ -116,8 +113,7 @@ impl ModuleLoader {
116
113
  pub fn load_wasm_module(&self, global_store: &mut GlobalStore) -> Result<(), String> {
117
114
  // Step one : Load the module from the global store
118
115
  let module = {
119
- let module_ref = global_store
120
- .modules
116
+ let module_ref = global_store.modules
121
117
  .get(&self.entry)
122
118
  .ok_or_else(|| format!("❌ Module not found for path: {}", self.entry))?;
123
119
 
@@ -145,6 +141,15 @@ impl ModuleLoader {
145
141
  return Err(format!("Failed to inject bank triggers: {}", e));
146
142
  }
147
143
 
144
+ // Insert the updated module into the global store before processing so
145
+ // process_modules can operate on it and populate variable_table, imports,
146
+ // and other derived structures.
147
+ global_store.modules.insert(self.entry.clone(), updated_module.clone());
148
+
149
+ // Process modules to populate module.variable_table, import/export tables,
150
+ // and other derived structures so runtime execution can resolve groups/synths.
151
+ process_modules(self, global_store);
152
+
148
153
  for (plugin_name, alias) in self.extract_plugin_uses(&updated_module.statements) {
149
154
  self.load_plugin_and_register(&mut updated_module, &plugin_name, &alias, global_store);
150
155
  }
@@ -153,10 +158,24 @@ impl ModuleLoader {
153
158
  let mut error_handler = ErrorHandler::new();
154
159
  error_handler.detect_from_statements(&mut parser, &updated_module.statements);
155
160
 
156
- // Final step : insert the updated module back into the global store
157
- global_store
158
- .modules
159
- .insert(self.entry.clone(), updated_module);
161
+ // Final step : also expose module-level variables and functions into the global store
162
+ // so runtime evaluation (render_audio) can find group/synth definitions.
163
+ // Use the module instance that was actually processed by `process_modules`
164
+ // (it lives in `global_store.modules`) because `updated_module` is a local
165
+ // clone and won't contain the mutations applied by `process_modules`.
166
+ if let Some(stored_module) = global_store.modules.get(&self.entry) {
167
+ global_store.variables.variables.extend(stored_module.variable_table.variables.clone());
168
+ global_store.functions.functions.extend(stored_module.function_table.functions.clone());
169
+ } else {
170
+ // Fallback to the local updated_module if for any reason the module
171
+ // wasn't inserted into the store (defensive programming).
172
+ global_store.variables.variables.extend(
173
+ updated_module.variable_table.variables.clone()
174
+ );
175
+ global_store.functions.functions.extend(
176
+ updated_module.function_table.functions.clone()
177
+ );
178
+ }
160
179
 
161
180
  Ok(())
162
181
  }
@@ -164,7 +183,7 @@ impl ModuleLoader {
164
183
  #[cfg(feature = "cli")]
165
184
  pub fn load_all_modules(
166
185
  &self,
167
- global_store: &mut GlobalStore,
186
+ global_store: &mut GlobalStore
168
187
  ) -> (HashMap<String, Vec<Token>>, HashMap<String, Vec<Statement>>) {
169
188
  // SECTION Load the entry module and its dependencies
170
189
  let tokens_by_module = self.load_module_recursively(&self.entry, global_store);
@@ -183,7 +202,7 @@ impl ModuleLoader {
183
202
  fn load_module_recursively(
184
203
  &self,
185
204
  raw_path: &str,
186
- global_store: &mut GlobalStore,
205
+ global_store: &mut GlobalStore
187
206
  ) -> HashMap<String, Vec<Token>> {
188
207
  let path = normalize_path(raw_path);
189
208
 
@@ -193,7 +212,14 @@ impl ModuleLoader {
193
212
  }
194
213
 
195
214
  let lexer = Lexer::new();
196
- let tokens = lexer.lex_tokens(&path);
215
+ let tokens = match lexer.lex_tokens(&path) {
216
+ Ok(t) => t,
217
+ Err(e) => {
218
+ let logger = Logger::new();
219
+ logger.log_message(LogLevel::Error, &format!("Failed to lex '{}': {}", path, e));
220
+ return HashMap::new();
221
+ }
222
+ };
197
223
 
198
224
  let mut parser = Parser::new();
199
225
  parser.set_current_module(path.clone());
@@ -217,14 +243,8 @@ impl ModuleLoader {
217
243
  }
218
244
 
219
245
  // Inject module variables and functions into global store
220
- global_store
221
- .variables
222
- .variables
223
- .extend(module.variable_table.variables.clone());
224
- global_store
225
- .functions
226
- .functions
227
- .extend(module.function_table.functions.clone());
246
+ global_store.variables.variables.extend(module.variable_table.variables.clone());
247
+ global_store.functions.functions.extend(module.function_table.functions.clone());
228
248
 
229
249
  // Inject the module into the global store
230
250
  global_store.insert_module(path.clone(), module);
@@ -249,8 +269,7 @@ impl ModuleLoader {
249
269
  }
250
270
 
251
271
  // Return tokens per module
252
- global_store
253
- .modules
272
+ global_store.modules
254
273
  .iter()
255
274
  .map(|(p, m)| (p.clone(), m.tokens.clone()))
256
275
  .collect()
@@ -262,16 +281,12 @@ impl ModuleLoader {
262
281
  let current_module = match global_store.modules.get(path) {
263
282
  Some(module) => module,
264
283
  None => {
265
- eprintln!(
266
- "[warn] Cannot resolve imports: module '{}' not found in store",
267
- path
268
- );
284
+ eprintln!("[warn] Cannot resolve imports: module '{}' not found in store", path);
269
285
  return;
270
286
  }
271
287
  };
272
288
 
273
- current_module
274
- .statements
289
+ current_module.statements
275
290
  .iter()
276
291
  .filter_map(|stmt| {
277
292
  if let StatementKind::Import { source, .. } = &stmt.kind {
@@ -293,57 +308,64 @@ impl ModuleLoader {
293
308
  &self,
294
309
  module: &mut Module,
295
310
  bank_name: &str,
296
- alias_override: Option<String>,
311
+ alias_override: Option<String>
297
312
  ) -> Result<Module, String> {
298
- let default_alias = bank_name.split('.').last().unwrap_or(bank_name).to_string();
313
+ let default_alias = bank_name.split('.').next_back().unwrap_or(bank_name).to_string();
299
314
  let alias_ref = alias_override.as_deref().unwrap_or(&default_alias);
300
315
 
301
- let bank_path = Path::new("./.deva/bank").join(bank_name);
316
+ let bank_path = match devalang_utils::path::get_deva_dir() {
317
+ Ok(dir) => dir.join("banks").join(bank_name),
318
+ Err(_) => Path::new("./.deva").join("banks").join(bank_name),
319
+ };
302
320
  let bank_toml_path = bank_path.join("bank.toml");
303
321
 
304
322
  if !bank_toml_path.exists() {
305
323
  return Ok(module.clone());
306
324
  }
307
325
 
308
- let content = std::fs::read_to_string(&bank_toml_path)
326
+ let content = std::fs
327
+ ::read_to_string(&bank_toml_path)
309
328
  .map_err(|e| format!("Failed to read '{}': {}", bank_toml_path.display(), e))?;
310
329
 
311
- let parsed_bankfile: BankFile = toml::from_str(&content)
330
+ let parsed_bankfile: BankFile = toml
331
+ ::from_str(&content)
312
332
  .map_err(|e| format!("Failed to parse '{}': {}", bank_toml_path.display(), e))?;
313
333
 
314
334
  let mut bank_map = HashMap::new();
315
335
 
316
336
  for bank_trigger in parsed_bankfile.triggers.unwrap_or_default() {
317
- let trigger_name = bank_trigger.name.clone().replace("./", "");
318
- let bank_trigger_path = format!("devalang://bank/{}/{}", bank_name, trigger_name);
337
+ // Use the configured path from the bank file as the entity reference so
338
+ // that bank entries can point to files or nested paths. Clean common
339
+ // local prefixes like "./" to keep the URI tidy.
340
+ let entity_ref = bank_trigger.path.clone().replace("\\", "/").replace("./", "");
341
+ let bank_trigger_path = format!("devalang://bank/{}/{}", bank_name, entity_ref);
319
342
 
320
- bank_map.insert(
321
- bank_trigger.name.clone(),
322
- Value::String(bank_trigger_path.clone()),
323
- );
343
+ // Keep the trigger key as declared (bank_trigger.name) but expose its
344
+ // value as a devalang://bank URI pointing to the configured path.
345
+ bank_map.insert(bank_trigger.name.clone(), Value::String(bank_trigger_path.clone()));
324
346
 
325
347
  if module.variable_table.variables.contains_key(alias_ref) {
326
348
  eprintln!(
327
349
  "⚠️ Trigger '{}' already defined in module '{}', skipping injection.",
328
- alias_ref, module.path
350
+ alias_ref,
351
+ module.path
329
352
  );
330
353
  continue;
331
354
  }
332
355
 
333
356
  module.variable_table.set(
334
357
  format!("{}.{}", alias_ref, bank_trigger.name),
335
- Value::String(bank_trigger_path.clone()),
358
+ Value::String(bank_trigger_path.clone())
336
359
  );
337
360
  }
338
361
 
339
362
  // Inject the map under the bank name
340
- module
341
- .variable_table
342
- .set(alias_ref.to_string(), Value::Map(bank_map));
363
+ module.variable_table.set(alias_ref.to_string(), Value::Map(bank_map));
343
364
 
344
365
  Ok(module.clone())
345
366
  }
346
367
 
368
+ #[cfg_attr(not(feature = "cli"), allow(dead_code))]
347
369
  fn extract_bank_decls(&self, statements: &[Statement]) -> Vec<(String, Option<String>)> {
348
370
  let mut banks = Vec::new();
349
371
 
@@ -371,7 +393,7 @@ impl ModuleLoader {
371
393
  if let StatementKind::Use { name, alias } = &stmt.kind {
372
394
  let alias_name = alias
373
395
  .clone()
374
- .unwrap_or_else(|| name.split('.').last().unwrap_or(name).to_string());
396
+ .unwrap_or_else(|| name.split('.').next_back().unwrap_or(name).to_string());
375
397
  plugins.push((name.clone(), alias_name));
376
398
  }
377
399
  }
@@ -384,7 +406,7 @@ impl ModuleLoader {
384
406
  module: &mut Module,
385
407
  plugin_name: &str,
386
408
  alias: &str,
387
- global_store: &mut GlobalStore,
409
+ global_store: &mut GlobalStore
388
410
  ) {
389
411
  // plugin_name expected format: "author.name"
390
412
  let mut parts = plugin_name.split('.');
@@ -403,10 +425,7 @@ impl ModuleLoader {
403
425
  }
404
426
  };
405
427
  if parts.next().is_some() {
406
- eprintln!(
407
- "Invalid plugin name '{}': expected <author>.<name>",
408
- plugin_name
409
- );
428
+ eprintln!("Invalid plugin name '{}': expected <author>.<name>", plugin_name);
410
429
  return;
411
430
  }
412
431
 
@@ -415,16 +434,19 @@ impl ModuleLoader {
415
434
  let expected_uri = format!("devalang://plugin/{}.{}", author, name);
416
435
 
417
436
  // Detect local presence (preferred and legacy layouts)
418
- let root = Path::new("./.deva");
419
- let plugin_dir_preferred = root.join("plugin").join(format!("{}.{}", author, name));
437
+ let root = match devalang_utils::path::get_deva_dir() {
438
+ Ok(dir) => dir,
439
+ Err(_) => Path::new("./.deva").to_path_buf(),
440
+ };
441
+ let plugin_dir_preferred = root.join("plugins").join(format!("{}.{}", author, name));
420
442
  let toml_path_preferred = plugin_dir_preferred.join("plugin.toml");
421
- let plugin_dir_fallback = root.join("plugin").join(author).join(name);
443
+ let plugin_dir_fallback = root.join("plugins").join(author).join(name);
422
444
  let toml_path_fallback = plugin_dir_fallback.join("plugin.toml");
423
445
  let exists_locally = toml_path_preferred.exists() || toml_path_fallback.exists();
424
446
 
425
447
  if exists_locally {
426
448
  // Load config and verify plugin is declared
427
- let cfg_opt = load_config(None);
449
+ let cfg_opt = crate::config::ops::load_config(None);
428
450
  let mut declared = false;
429
451
  if let Some(cfg) = cfg_opt {
430
452
  if let Some(list) = cfg.plugins {
@@ -435,8 +457,7 @@ impl ModuleLoader {
435
457
  // Inject a single, clear error into the module so it is reported once by the error handler
436
458
  module.statements.push(Statement {
437
459
  kind: StatementKind::Error {
438
- message: "plugin present in local files but missing in .devalang config"
439
- .to_string(),
460
+ message: "plugin present in local files but missing in .devalang config".to_string(),
440
461
  },
441
462
  value: Value::Null,
442
463
  indent: 0,
@@ -450,15 +471,16 @@ impl ModuleLoader {
450
471
  match load_plugin(author, name) {
451
472
  Ok((info, wasm)) => {
452
473
  let uri = format!("devalang://plugin/{}.{}", author, name);
453
- global_store
454
- .plugins
455
- .insert(format!("{}:{}", author, name), (info, wasm));
474
+ global_store.plugins.insert(format!("{}:{}", author, name), (info, wasm));
456
475
  // Set alias to URI, and inject exported variables
457
- module
458
- .variable_table
459
- .set(alias.to_string(), Value::String(uri.clone()));
460
- if let Some((plugin_info, _)) =
461
- global_store.plugins.get(&format!("{}:{}", author, name))
476
+ module.variable_table.set(alias.to_string(), Value::String(uri.clone()));
477
+ // Also expose alias at global level so runtime can resolve it
478
+ global_store.variables.set(alias.to_string(), Value::String(uri.clone()));
479
+
480
+ if
481
+ let Some((plugin_info, _)) = global_store.plugins.get(
482
+ &format!("{}:{}", author, name)
483
+ )
462
484
  {
463
485
  for exp in &plugin_info.exports {
464
486
  match exp.kind.as_str() {
@@ -467,18 +489,18 @@ impl ModuleLoader {
467
489
  if let Ok(n) = s.parse::<f32>() {
468
490
  module.variable_table.set(
469
491
  format!("{}.{}", alias, exp.name),
470
- Value::Number(n),
492
+ Value::Number(n)
471
493
  );
472
494
  }
473
495
  } else if let Some(toml::Value::Integer(i)) = &exp.default {
474
496
  module.variable_table.set(
475
497
  format!("{}.{}", alias, exp.name),
476
- Value::Number(*i as f32),
498
+ Value::Number(*i as f32)
477
499
  );
478
500
  } else if let Some(toml::Value::Float(f)) = &exp.default {
479
501
  module.variable_table.set(
480
502
  format!("{}.{}", alias, exp.name),
481
- Value::Number(*f as f32),
503
+ Value::Number(*f as f32)
482
504
  );
483
505
  }
484
506
  }
@@ -486,25 +508,85 @@ impl ModuleLoader {
486
508
  if let Some(toml::Value::String(s)) = &exp.default {
487
509
  module.variable_table.set(
488
510
  format!("{}.{}", alias, exp.name),
489
- Value::String(s.clone()),
511
+ Value::String(s.clone())
490
512
  );
491
513
  }
492
514
  }
493
515
  "bool" => {
494
516
  if let Some(toml::Value::Boolean(b)) = &exp.default {
495
- module
496
- .variable_table
497
- .set(format!("{}.{}", alias, exp.name), Value::Boolean(*b));
517
+ module.variable_table.set(
518
+ format!("{}.{}", alias, exp.name),
519
+ Value::Boolean(*b)
520
+ );
498
521
  }
499
522
  }
500
523
  "synth" => {
501
524
  // Provide a discoverable marker: alias.<synthName> resolves to alias.synthName waveform string
502
525
  module.variable_table.set(
503
526
  format!("{}.{}", alias, exp.name),
504
- Value::String(format!("{}.{}", alias, exp.name)),
527
+ Value::String(format!("{}.{}", alias, exp.name))
505
528
  );
506
529
  }
507
- _ => {}
530
+ _ => {
531
+ // Fallback: if default is present, map it to a Value dynamically
532
+ if let Some(def) = &exp.default {
533
+ let val = match def {
534
+ toml::Value::String(s) => Value::String(s.clone()),
535
+ toml::Value::Integer(i) => Value::Number(*i as f32),
536
+ toml::Value::Float(f) => Value::Number(*f as f32),
537
+ toml::Value::Boolean(b) => Value::Boolean(*b),
538
+ toml::Value::Array(arr) =>
539
+ Value::Array(
540
+ arr
541
+ .iter()
542
+ .map(|v| {
543
+ match v {
544
+ toml::Value::String(s) => {
545
+ Value::String(s.clone())
546
+ }
547
+ toml::Value::Integer(i) => {
548
+ Value::Number(*i as f32)
549
+ }
550
+ toml::Value::Float(f) => {
551
+ Value::Number(*f as f32)
552
+ }
553
+ toml::Value::Boolean(b) =>
554
+ Value::Boolean(*b),
555
+ _ => Value::Null,
556
+ }
557
+ })
558
+ .collect()
559
+ ),
560
+ toml::Value::Table(t) => {
561
+ let mut m = std::collections::HashMap::new();
562
+ for (k, v) in t.iter() {
563
+ let vv = match v {
564
+ toml::Value::String(s) => {
565
+ Value::String(s.clone())
566
+ }
567
+ toml::Value::Integer(i) => {
568
+ Value::Number(*i as f32)
569
+ }
570
+ toml::Value::Float(f) => {
571
+ Value::Number(*f as f32)
572
+ }
573
+ toml::Value::Boolean(b) => Value::Boolean(*b),
574
+ _ => Value::Null,
575
+ };
576
+ m.insert(k.clone(), vv);
577
+ }
578
+ Value::Map(m)
579
+ }
580
+ _ => Value::Null,
581
+ };
582
+ if val != Value::Null {
583
+ module.variable_table.set(
584
+ format!("{}.{}", alias, exp.name),
585
+ val
586
+ );
587
+ }
588
+ }
589
+ }
508
590
  }
509
591
  }
510
592
  }
@@ -3,18 +3,21 @@ use std::{collections::HashMap, path::Path};
3
3
  use crate::core::{
4
4
  parser::statement::StatementKind,
5
5
  preprocessor::loader::ModuleLoader,
6
- shared::value::Value,
7
6
  store::global::GlobalStore,
8
7
  utils::path::{normalize_path, resolve_relative_path},
9
8
  };
9
+ use devalang_types::Value;
10
10
 
11
11
  pub fn process_modules(_module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
12
12
  for module in global_store.modules.values_mut() {
13
+ let logger = devalang_utils::logger::Logger::new();
14
+ use devalang_utils::logger::LogLevel;
15
+
13
16
  for stmt in &module.statements {
14
17
  match &stmt.kind {
15
18
  StatementKind::Let { name } => {
16
19
  if let Value::Null = stmt.value {
17
- eprintln!("Variable '{}' is declared but not initialized.", name);
20
+ logger.log_message(LogLevel::Error, &format!("Variable '{}' is declared but not initialized.", name));
18
21
 
19
22
  module.variable_table.variables.insert(
20
23
  name.clone(),
@@ -25,15 +28,12 @@ pub fn process_modules(_module_loader: &ModuleLoader, global_store: &mut GlobalS
25
28
  }
26
29
 
27
30
  if module.variable_table.get(name).is_some() {
28
- eprintln!("Variable '{}' is already defined in this scope.", name);
31
+ logger.log_message(LogLevel::Error, &format!("Variable '{}' is already defined in this scope.", name));
29
32
  continue;
30
33
  }
31
34
 
32
35
  if let Some(module_variable) = module.variable_table.variables.get(name) {
33
- eprintln!(
34
- "❌ Variable '{}' is already defined globally with value: {:?}",
35
- name, module_variable
36
- );
36
+ logger.log_message(LogLevel::Error, &format!("Variable '{}' is already defined globally with value: {:?}", name, module_variable));
37
37
  continue;
38
38
  }
39
39
 
@@ -46,7 +46,7 @@ pub fn process_modules(_module_loader: &ModuleLoader, global_store: &mut GlobalS
46
46
  StatementKind::Load { source, alias } => {
47
47
  let module_dir = Path::new(&module.path).parent().unwrap_or(Path::new(""));
48
48
 
49
- let resolved_path = normalize_path(&module_dir.join(source));
49
+ let resolved_path = normalize_path(module_dir.join(source));
50
50
 
51
51
  module
52
52
  .variable_table
@@ -87,7 +87,7 @@ pub fn process_modules(_module_loader: &ModuleLoader, global_store: &mut GlobalS
87
87
  .variable_table
88
88
  .set(name.to_string(), Value::Map(stored_map));
89
89
  } else {
90
- eprintln!("Invalid group definition: {:?}", stmt.value);
90
+ logger.log_message(LogLevel::Error, &format!("Invalid group definition: {:?}", stmt.value));
91
91
  }
92
92
  }
93
93
  }
@@ -1,12 +1,10 @@
1
- use crate::{
2
- core::{
3
- parser::statement::{Statement, StatementKind},
4
- preprocessor::module::Module,
5
- shared::value::Value,
6
- store::global::GlobalStore,
7
- },
8
- utils::logger::Logger,
1
+ use crate::core::{
2
+ parser::statement::{Statement, StatementKind},
3
+ preprocessor::module::Module,
4
+ store::global::GlobalStore,
9
5
  };
6
+ use devalang_types::Value;
7
+ use devalang_utils::logger::Logger;
10
8
 
11
9
  pub fn resolve_bank(
12
10
  stmt: &Statement,