@devaloop/devalang 0.0.1-alpha.16-hotfix.1 → 0.0.1-alpha.17

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 (235) hide show
  1. package/.cargo/config.toml +2 -0
  2. package/.devalang +6 -10
  3. package/.github/workflows/ci.yml +19 -8
  4. package/Cargo.toml +18 -2
  5. package/README.md +80 -33
  6. package/docs/CHANGELOG.md +56 -0
  7. package/docs/ROADMAP.md +6 -3
  8. package/examples/index.deva +52 -35
  9. package/out-tsc/bin/index.d.ts +2 -0
  10. package/out-tsc/core/functions/index.d.ts +37 -0
  11. package/out-tsc/core/functions/index.js +76 -0
  12. package/out-tsc/core/index.d.ts +6 -0
  13. package/out-tsc/core/index.js +22 -0
  14. package/out-tsc/core/types/index.d.ts +4 -0
  15. package/out-tsc/core/types/index.js +20 -0
  16. package/out-tsc/core/types/plugin.d.ts +18 -0
  17. package/out-tsc/core/types/plugin.js +2 -0
  18. package/out-tsc/core/types/result.d.ts +27 -0
  19. package/out-tsc/core/types/result.js +2 -0
  20. package/out-tsc/core/types/statement.d.ts +106 -0
  21. package/out-tsc/core/types/statement.js +2 -0
  22. package/out-tsc/core/types/value.d.ts +43 -0
  23. package/out-tsc/core/types/value.js +2 -0
  24. package/out-tsc/index.d.ts +7 -0
  25. package/out-tsc/index.js +41 -2
  26. package/out-tsc/pkg/devalang_core.d.ts +7 -0
  27. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
  28. package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
  29. package/out-tsc/scripts/copy-wasm-dts.js +73 -0
  30. package/out-tsc/scripts/postinstall.d.ts +1 -0
  31. package/out-tsc/scripts/postinstall.js +33 -23
  32. package/out-tsc/scripts/version/bump.d.ts +1 -0
  33. package/out-tsc/scripts/version/fetch.d.ts +1 -0
  34. package/out-tsc/scripts/version/index.d.ts +1 -0
  35. package/out-tsc/scripts/version/sync.d.ts +1 -0
  36. package/package.json +16 -4
  37. package/project-version.json +3 -3
  38. package/rust/cli/bank/api.rs +122 -0
  39. package/rust/cli/bank/commands.rs +275 -0
  40. package/rust/cli/bank/mod.rs +29 -0
  41. package/rust/cli/build/commands.rs +97 -0
  42. package/rust/cli/build/mod.rs +2 -0
  43. package/rust/cli/build/process.rs +146 -0
  44. package/rust/cli/{check.rs → check/mod.rs} +18 -31
  45. package/rust/cli/discover/commands.rs +253 -0
  46. package/rust/cli/discover/config.rs +111 -0
  47. package/rust/cli/discover/fs.rs +19 -0
  48. package/rust/cli/discover/install.rs +103 -0
  49. package/rust/cli/discover/metadata.rs +48 -0
  50. package/rust/cli/discover/mod.rs +5 -0
  51. package/rust/cli/{init.rs → init/commands.rs} +88 -87
  52. package/rust/cli/init/mod.rs +1 -0
  53. package/rust/{installer → cli/install}/addon.rs +5 -9
  54. package/rust/cli/install/bank.rs +53 -0
  55. package/rust/cli/{install.rs → install/commands.rs} +9 -9
  56. package/rust/{installer → cli/install}/mod.rs +2 -3
  57. package/rust/cli/install/plugin.rs +61 -0
  58. package/rust/cli/{login.rs → login/commands.rs} +8 -11
  59. package/rust/cli/login/mod.rs +1 -0
  60. package/rust/cli/mod.rs +2 -3
  61. package/rust/cli/{driver.rs → parser.rs} +19 -2
  62. package/rust/cli/play/commands.rs +324 -0
  63. package/rust/cli/play/io.rs +17 -0
  64. package/rust/cli/play/mod.rs +5 -0
  65. package/rust/cli/play/process.rs +150 -0
  66. package/rust/cli/play/realtime.rs +91 -0
  67. package/rust/cli/play/utils.rs +23 -0
  68. package/rust/cli/telemetry/commands.rs +22 -0
  69. package/rust/cli/telemetry/event_creator.rs +80 -0
  70. package/rust/cli/telemetry/mod.rs +3 -0
  71. package/rust/cli/telemetry/send.rs +51 -0
  72. package/rust/cli/{template.rs → template/commands.rs} +1 -1
  73. package/rust/cli/template/mod.rs +1 -0
  74. package/rust/cli/{update.rs → update/commands.rs} +6 -6
  75. package/rust/cli/update/mod.rs +1 -0
  76. package/rust/config/driver.rs +57 -72
  77. package/rust/config/mod.rs +1 -2
  78. package/rust/config/ops.rs +26 -0
  79. package/rust/config/settings.rs +60 -50
  80. package/rust/core/audio/engine/helpers.rs +146 -0
  81. package/rust/core/audio/engine/mod.rs +7 -0
  82. package/rust/core/audio/engine/sample.rs +298 -0
  83. package/rust/core/audio/engine/synth.rs +310 -0
  84. package/rust/core/audio/evaluator.rs +15 -12
  85. package/rust/core/audio/interpreter/arrow_call.rs +99 -24
  86. package/rust/core/audio/interpreter/call.rs +81 -60
  87. package/rust/core/audio/interpreter/condition.rs +3 -2
  88. package/rust/core/audio/interpreter/driver.rs +206 -151
  89. package/rust/core/audio/interpreter/let_.rs +1 -1
  90. package/rust/core/audio/interpreter/load.rs +2 -1
  91. package/rust/core/audio/interpreter/loop_.rs +7 -6
  92. package/rust/core/audio/interpreter/sleep.rs +2 -1
  93. package/rust/core/audio/interpreter/spawn.rs +45 -57
  94. package/rust/core/audio/interpreter/tempo.rs +31 -10
  95. package/rust/core/audio/interpreter/trigger.rs +2 -2
  96. package/rust/core/audio/loader/trigger.rs +4 -7
  97. package/rust/core/audio/player.rs +6 -0
  98. package/rust/core/audio/renderer.rs +5 -7
  99. package/rust/core/audio/special/env.rs +3 -1
  100. package/rust/core/audio/special/math.rs +4 -4
  101. package/rust/core/audio/special/modulator.rs +2 -2
  102. package/rust/core/builder/mod.rs +9 -3
  103. package/rust/core/debugger/lexer.rs +1 -1
  104. package/rust/core/debugger/mod.rs +6 -0
  105. package/rust/core/debugger/module.rs +4 -4
  106. package/rust/core/debugger/preprocessor.rs +1 -1
  107. package/rust/core/debugger/store.rs +2 -2
  108. package/rust/core/error/mod.rs +189 -0
  109. package/rust/core/lexer/handler/arrow.rs +1 -1
  110. package/rust/core/lexer/handler/at.rs +1 -1
  111. package/rust/core/lexer/handler/brace.rs +2 -2
  112. package/rust/core/lexer/handler/colon.rs +1 -1
  113. package/rust/core/lexer/handler/comment.rs +1 -1
  114. package/rust/core/lexer/handler/dot.rs +1 -1
  115. package/rust/core/lexer/handler/driver.rs +1 -1
  116. package/rust/core/lexer/handler/identifier.rs +1 -1
  117. package/rust/core/lexer/handler/mod.rs +1 -2
  118. package/rust/core/lexer/handler/number.rs +1 -1
  119. package/rust/core/lexer/handler/operator.rs +1 -1
  120. package/rust/core/lexer/handler/parenthesis.rs +2 -2
  121. package/rust/core/lexer/handler/slash.rs +1 -1
  122. package/rust/core/lexer/handler/string.rs +1 -1
  123. package/rust/core/lexer/mod.rs +22 -12
  124. package/rust/core/lexer/token.rs +90 -97
  125. package/rust/core/mod.rs +0 -1
  126. package/rust/core/parser/driver.rs +66 -13
  127. package/rust/core/parser/handler/arrow_call.rs +28 -8
  128. package/rust/core/parser/handler/at.rs +55 -21
  129. package/rust/core/parser/handler/bank.rs +14 -4
  130. package/rust/core/parser/handler/condition.rs +6 -3
  131. package/rust/core/parser/handler/dot.rs +2 -1
  132. package/rust/core/parser/handler/identifier/automate.rs +13 -16
  133. package/rust/core/parser/handler/identifier/call.rs +4 -4
  134. package/rust/core/parser/handler/identifier/emit.rs +9 -5
  135. package/rust/core/parser/handler/identifier/function.rs +20 -7
  136. package/rust/core/parser/handler/identifier/group.rs +11 -7
  137. package/rust/core/parser/handler/identifier/let_.rs +24 -9
  138. package/rust/core/parser/handler/identifier/mod.rs +6 -5
  139. package/rust/core/parser/handler/identifier/on.rs +16 -7
  140. package/rust/core/parser/handler/identifier/print.rs +6 -9
  141. package/rust/core/parser/handler/identifier/sleep.rs +12 -5
  142. package/rust/core/parser/handler/identifier/spawn.rs +4 -4
  143. package/rust/core/parser/handler/identifier/synth.rs +79 -9
  144. package/rust/core/parser/handler/loop_.rs +39 -14
  145. package/rust/core/parser/handler/tempo.rs +9 -5
  146. package/rust/core/parser/mod.rs +0 -1
  147. package/rust/core/parser/statement.rs +6 -137
  148. package/rust/core/plugin/loader.rs +41 -27
  149. package/rust/core/plugin/runner.rs +68 -17
  150. package/rust/core/preprocessor/loader.rs +155 -33
  151. package/rust/core/preprocessor/processor.rs +2 -2
  152. package/rust/core/preprocessor/resolver/bank.rs +6 -8
  153. package/rust/core/preprocessor/resolver/call.rs +20 -24
  154. package/rust/core/preprocessor/resolver/condition.rs +6 -8
  155. package/rust/core/preprocessor/resolver/driver.rs +14 -16
  156. package/rust/core/preprocessor/resolver/function.rs +6 -6
  157. package/rust/core/preprocessor/resolver/group.rs +6 -8
  158. package/rust/core/preprocessor/resolver/loop_.rs +8 -10
  159. package/rust/core/preprocessor/resolver/spawn.rs +19 -23
  160. package/rust/core/preprocessor/resolver/synth.rs +6 -8
  161. package/rust/core/preprocessor/resolver/tempo.rs +6 -8
  162. package/rust/core/preprocessor/resolver/trigger.rs +22 -19
  163. package/rust/core/preprocessor/resolver/value.rs +99 -4
  164. package/rust/core/store/export.rs +28 -28
  165. package/rust/core/store/function.rs +6 -0
  166. package/rust/core/store/global.rs +7 -1
  167. package/rust/core/store/import.rs +28 -28
  168. package/rust/core/store/variable.rs +1 -1
  169. package/rust/core/utils/mod.rs +0 -1
  170. package/rust/lib.rs +102 -9
  171. package/rust/main.rs +156 -45
  172. package/rust/types/Cargo.toml +8 -0
  173. package/rust/types/src/addons.rs +55 -0
  174. package/rust/types/src/ast.rs +198 -0
  175. package/rust/types/src/config.rs +74 -0
  176. package/rust/types/src/lib.rs +12 -0
  177. package/rust/types/src/telemetry.rs +85 -0
  178. package/rust/utils/Cargo.toml +23 -0
  179. package/rust/utils/{error.rs → src/error.rs} +186 -200
  180. package/rust/utils/src/file.rs +94 -0
  181. package/rust/utils/src/first_usage.rs +97 -0
  182. package/rust/utils/{mod.rs → src/lib.rs} +1 -1
  183. package/rust/utils/{logger.rs → src/logger.rs} +17 -12
  184. package/rust/utils/src/path.rs +88 -0
  185. package/rust/utils/src/signature.rs +41 -0
  186. package/rust/utils/{spinner.rs → src/spinner.rs} +3 -5
  187. package/rust/utils/src/version.rs +27 -0
  188. package/rust/utils/{watcher.rs → src/watcher.rs} +13 -1
  189. package/rust/web/api.rs +5 -0
  190. package/rust/web/cdn.rs +34 -0
  191. package/templates/minimal/README.md +98 -54
  192. package/templates/welcome/README.md +98 -54
  193. package/templates/welcome/src/index.deva +56 -8
  194. package/templates/welcome/src/variables.deva +2 -4
  195. package/tests/rust/TODO.md +0 -0
  196. package/tests/typescript/index.spec.ts +136 -0
  197. package/tests/typescript/playhead.spec.ts +36 -0
  198. package/tests/typescript/render_e2e.spec.ts +77 -0
  199. package/tsconfig.json +1 -1
  200. package/typescript/core/functions/index.ts +83 -0
  201. package/typescript/core/index.ts +6 -0
  202. package/typescript/core/types/index.ts +4 -0
  203. package/typescript/core/types/plugin.ts +19 -0
  204. package/typescript/core/types/result.ts +29 -0
  205. package/typescript/core/types/statement.ts +47 -0
  206. package/typescript/core/types/value.ts +29 -0
  207. package/typescript/index.ts +7 -2
  208. package/typescript/pkg/devalang_core.d.ts +4 -0
  209. package/typescript/scripts/copy-wasm-dts.ts +41 -0
  210. package/typescript/scripts/postinstall.ts +45 -32
  211. package/rust/cli/bank.rs +0 -462
  212. package/rust/cli/build.rs +0 -252
  213. package/rust/cli/generator.rs +0 -1
  214. package/rust/cli/play.rs +0 -1123
  215. package/rust/cli/telemetry.rs +0 -19
  216. package/rust/common/api.rs +0 -5
  217. package/rust/common/cdn.rs +0 -5
  218. package/rust/config/loader.rs +0 -165
  219. package/rust/config/stats.rs +0 -257
  220. package/rust/core/audio/engine.rs +0 -696
  221. package/rust/core/shared/bank.rs +0 -21
  222. package/rust/core/shared/duration.rs +0 -9
  223. package/rust/core/shared/mod.rs +0 -3
  224. package/rust/core/shared/value.rs +0 -35
  225. package/rust/core/utils/validation.rs +0 -35
  226. package/rust/installer/bank.rs +0 -62
  227. package/rust/installer/plugin.rs +0 -54
  228. package/rust/installer/utils.rs +0 -56
  229. package/rust/utils/file.rs +0 -38
  230. package/rust/utils/first_usage.rs +0 -76
  231. package/rust/utils/signature.rs +0 -19
  232. package/rust/utils/telemetry.rs +0 -292
  233. package/rust/utils/version.rs +0 -15
  234. /package/rust/{common → web}/mod.rs +0 -0
  235. /package/rust/{common → web}/sso.rs +0 -0
@@ -1,9 +1,10 @@
1
1
  use crate::core::{
2
2
  audio::engine::AudioEngine,
3
3
  parser::statement::{Statement, StatementKind},
4
- shared::value::Value,
5
- store::variable::VariableTable,
4
+ plugin::runner::WasmPluginRunner,
5
+ store::{global::GlobalStore, variable::VariableTable},
6
6
  };
7
+ use devalang_types::Value;
7
8
 
8
9
  use std::collections::HashMap;
9
10
 
@@ -11,6 +12,7 @@ pub fn interprete_call_arrow_statement(
11
12
  stmt: &Statement,
12
13
  audio_engine: &mut AudioEngine,
13
14
  variable_table: &VariableTable,
15
+ global_store: &GlobalStore,
14
16
  base_bpm: f32,
15
17
  base_duration: f32,
16
18
  max_end_time: &mut f32,
@@ -53,11 +55,14 @@ pub fn interprete_call_arrow_statement(
53
55
  return (*max_end_time, cursor_copy);
54
56
  };
55
57
 
56
- let Some(Value::String(waveform)) = value_map.get("waveform") else {
57
- println!("❌ Missing or invalid 'waveform' in synth '{}'.", target);
58
- return (*max_end_time, cursor_copy);
58
+ let waveform_str = match value_map.get("waveform") {
59
+ Some(Value::String(s)) => s.clone(),
60
+ Some(Value::Identifier(s)) => s.clone(),
61
+ _ => {
62
+ println!("? Missing or invalid 'waveform' in synth '{}'.", target);
63
+ return (*max_end_time, cursor_copy);
64
+ }
59
65
  };
60
-
61
66
  let Some(Value::Map(params)) = value_map.get("parameters") else {
62
67
  println!("❌ Missing or invalid 'parameters' in synth '{}'.", target);
63
68
  return (*max_end_time, cursor_copy);
@@ -73,7 +78,7 @@ pub fn interprete_call_arrow_statement(
73
78
  .filter(|arg| !matches!(arg, Value::Unknown))
74
79
  .collect();
75
80
 
76
- let Some(Value::Identifier(note_name)) = filtered_args.get(0).map(|v| (*v).clone())
81
+ let Some(Value::Identifier(note_name)) = filtered_args.first().map(|v| (*v).clone())
77
82
  else {
78
83
  println!(
79
84
  "❌ Invalid or missing argument for 'note' method on '{}'.",
@@ -84,13 +89,10 @@ pub fn interprete_call_arrow_statement(
84
89
 
85
90
  let mut note_params = HashMap::new();
86
91
  if let Some(arg1) = filtered_args.get(1) {
87
- match (*arg1).clone() {
88
- Value::Map(map) => {
89
- for (key, value) in map {
90
- note_params.insert(key, value);
91
- }
92
+ if let Value::Map(map) = (*arg1).clone() {
93
+ for (key, value) in map {
94
+ note_params.insert(key, value);
92
95
  }
93
- _ => {}
94
96
  }
95
97
  }
96
98
 
@@ -134,16 +136,89 @@ pub fn interprete_call_arrow_statement(
134
136
  _ => None,
135
137
  };
136
138
 
137
- audio_engine.insert_note(
138
- waveform.clone(),
139
- final_freq,
140
- amp_note,
141
- start_time * 1000.0,
142
- duration_ms,
143
- synth_params,
144
- note_params,
145
- automation,
146
- );
139
+ // If waveform references a plugin alias (e.g., alias.synth), use the WASM plugin runner
140
+ if waveform_str.contains('.') && waveform_str.ends_with(".synth") {
141
+ let alias = waveform_str.split('.').next().unwrap_or("");
142
+ if let Some(Value::String(uri)) = variable_table.get(alias) {
143
+ if let Some(id) = uri.strip_prefix("devalang://plugin/") {
144
+ let mut parts = id.split('.');
145
+ let author = parts.next().unwrap_or("");
146
+ let name = parts.next().unwrap_or("");
147
+ let key = format!("{}:{}", author, name);
148
+ if let Some((_info, wasm_bytes)) = global_store.plugins.get(&key) {
149
+ // Prepare buffer (stereo f32)
150
+ let sample_rate = 44100.0_f32;
151
+ let total_samples = ((duration_ms / 1000.0) * sample_rate) as usize;
152
+ let channels = 2usize;
153
+ let start_index = ((start_time * sample_rate) as usize) * channels;
154
+ let required_len = start_index + total_samples * channels;
155
+ if audio_engine.buffer.len() < required_len {
156
+ audio_engine.buffer.resize(required_len, 0);
157
+ }
158
+ let mut fbuf = vec![0.0f32; total_samples * channels];
159
+ let runner = WasmPluginRunner::new();
160
+ let mut params_num: std::collections::HashMap<String, f32> =
161
+ std::collections::HashMap::new();
162
+ let mut params_str: std::collections::HashMap<String, String> =
163
+ std::collections::HashMap::new();
164
+ for (k, v) in synth_params.iter() {
165
+ match v {
166
+ Value::Number(n) => {
167
+ params_num.insert(k.clone(), *n);
168
+ }
169
+ Value::String(s) => {
170
+ params_str.insert(k.clone(), s.clone());
171
+ }
172
+ Value::Identifier(s) => {
173
+ params_str.insert(k.clone(), s.clone());
174
+ }
175
+ _ => {}
176
+ }
177
+ }
178
+ let _ = runner.render_note_with_params_in_place(
179
+ wasm_bytes,
180
+ &mut fbuf,
181
+ None,
182
+ final_freq,
183
+ amp_note,
184
+ duration_ms as i32,
185
+ 44100,
186
+ 2,
187
+ &params_num,
188
+ Some(&params_str),
189
+ );
190
+ for (i, sample) in
191
+ fbuf.iter().enumerate().take(total_samples * channels)
192
+ {
193
+ let s = (sample.clamp(-1.0, 1.0) * (i16::MAX as f32)) as i16;
194
+ let idx = start_index + i;
195
+ audio_engine.buffer[idx] =
196
+ audio_engine.buffer[idx].saturating_add(s);
197
+ }
198
+ } else {
199
+ println!(
200
+ "? Plugin bytes not found for key '{}' (alias '{}').",
201
+ key, alias
202
+ );
203
+ }
204
+ } else {
205
+ println!("? Invalid plugin URI in alias '{}': {}", alias, uri);
206
+ }
207
+ } else {
208
+ println!("? Plugin alias '{}' not found in variable table.", alias);
209
+ }
210
+ } else {
211
+ audio_engine.insert_note(
212
+ waveform_str.clone(),
213
+ final_freq,
214
+ amp_note,
215
+ start_time * 1000.0,
216
+ duration_ms,
217
+ synth_params,
218
+ note_params,
219
+ automation,
220
+ );
221
+ }
147
222
 
148
223
  *max_end_time = (*max_end_time).max(end_time);
149
224
 
@@ -181,7 +256,7 @@ fn extract_f32(map: &HashMap<String, Value>, key: &str, base_bpm: f32) -> Option
181
256
  }
182
257
 
183
258
  fn note_to_freq(note: &str) -> f32 {
184
- let notes = vec![
259
+ let notes = [
185
260
  "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",
186
261
  ];
187
262
 
@@ -1,7 +1,8 @@
1
+ use devalang_types::Value;
2
+
1
3
  use crate::core::{
2
4
  audio::{engine::AudioEngine, interpreter::driver::execute_audio_block},
3
5
  parser::statement::{Statement, StatementKind},
4
- shared::value::Value,
5
6
  store::{function::FunctionTable, global::GlobalStore, variable::VariableTable},
6
7
  };
7
8
 
@@ -16,83 +17,103 @@ pub fn interprete_call_statement(
16
17
  max_end_time: f32,
17
18
  cursor_time: f32,
18
19
  ) -> (f32, f32) {
19
- match &stmt.kind {
20
- StatementKind::Call { name, args } => {
21
- // Classic function call case
22
- if let Some(func) = functions.functions.get(name) {
23
- if func.parameters.len() != args.len() {
24
- eprintln!(
25
- "❌ Function '{}' expects {} args, got {}",
26
- name,
27
- func.parameters.len(),
28
- args.len()
29
- );
30
- return (max_end_time, cursor_time);
31
- }
32
-
33
- let mut local_vars = VariableTable::with_parent(variable_table.clone());
34
- for (param, arg) in func.parameters.iter().zip(args) {
35
- local_vars.set(param.clone(), arg.clone());
36
- }
37
-
38
- return execute_audio_block(
39
- audio_engine,
40
- global_store,
41
- local_vars,
42
- functions.clone(),
43
- &func.body,
44
- base_bpm,
45
- base_duration,
46
- max_end_time,
47
- cursor_time,
20
+ if let StatementKind::Call { name, args } = &stmt.kind {
21
+ // Classic function call case
22
+ if let Some(func) = functions.functions.get(name) {
23
+ // function found
24
+ if func.parameters.len() != args.len() {
25
+ eprintln!(
26
+ "❌ Function '{}' expects {} args, got {}",
27
+ name,
28
+ func.parameters.len(),
29
+ args.len()
48
30
  );
31
+ return (max_end_time, cursor_time);
49
32
  }
50
33
 
51
- // Group case
52
- if let Some(group_stmt) = find_group(name, variable_table, global_store) {
53
- if let Value::Map(map) = &group_stmt.value {
54
- if let Some(Value::Block(body)) = map.get("body") {
55
- return execute_audio_block(
56
- audio_engine,
57
- global_store,
58
- variable_table.clone(),
59
- functions.clone(),
60
- &body,
61
- base_bpm,
62
- base_duration,
63
- max_end_time,
64
- cursor_time,
65
- );
66
- }
67
- }
34
+ let mut local_vars = VariableTable::with_parent(variable_table.clone());
35
+ for (param, arg) in func.parameters.iter().zip(args) {
36
+ local_vars.set(param.clone(), arg.clone());
68
37
  }
69
38
 
70
- eprintln!("❌ Function or group '{}' not found", name);
39
+ return execute_audio_block(
40
+ audio_engine,
41
+ global_store,
42
+ local_vars,
43
+ functions.clone(),
44
+ &func.body,
45
+ base_bpm,
46
+ base_duration,
47
+ max_end_time,
48
+ cursor_time,
49
+ );
50
+ }
51
+
52
+ // Group case
53
+ if let Some(group_stmt) = find_group(name, variable_table, global_store) {
54
+ // group found
55
+ if let Value::Map(map) = &group_stmt.value {
56
+ if let Some(Value::Block(body)) = map.get("body") {
57
+ return execute_audio_block(
58
+ audio_engine,
59
+ global_store,
60
+ variable_table.clone(),
61
+ functions.clone(),
62
+ body,
63
+ base_bpm,
64
+ base_duration,
65
+ max_end_time,
66
+ cursor_time,
67
+ );
68
+ }
69
+ }
71
70
  }
72
71
 
73
- _ => eprintln!(
74
- "❌ interprete_call_statement expected Call, got {:?}",
75
- stmt.kind
76
- ),
72
+ // Function or group not found; keep as debug-free fail path
77
73
  }
78
74
 
79
75
  (max_end_time, cursor_time)
80
76
  }
81
77
 
82
- fn find_group<'a>(
78
+ fn find_group(
83
79
  name: &str,
84
- variable_table: &'a VariableTable,
85
- global_store: &'a GlobalStore,
86
- ) -> Option<&'a Statement> {
80
+ variable_table: &VariableTable,
81
+ global_store: &GlobalStore,
82
+ ) -> Option<Statement> {
83
+ use crate::core::parser::statement::Statement;
84
+ use crate::core::parser::statement::StatementKind;
85
+
87
86
  if let Some(Value::Statement(stmt_box)) = variable_table.get(name) {
88
87
  if let StatementKind::Group = stmt_box.kind {
89
- return Some(stmt_box);
88
+ return Some(*stmt_box.clone());
90
89
  }
91
90
  }
92
- if let Some(Value::Statement(stmt_box)) = global_store.variables.variables.get(name) {
93
- if let StatementKind::Group = stmt_box.kind {
94
- return Some(stmt_box);
91
+
92
+ if let Some(val) = global_store.variables.variables.get(name) {
93
+ match val {
94
+ Value::Statement(stmt_box) => {
95
+ if let StatementKind::Group = stmt_box.kind {
96
+ return Some(*stmt_box.clone());
97
+ }
98
+ }
99
+ Value::Map(map) => {
100
+ // Try to rebuild a Group statement from the stored map
101
+ if let (Some(Value::String(_id)), Some(Value::Block(_body))) =
102
+ (map.get("identifier"), map.get("body"))
103
+ {
104
+ let stmt = Statement {
105
+ kind: StatementKind::Group,
106
+ value: Value::Map(map.clone()),
107
+ indent: 0,
108
+ line: 0,
109
+ column: 0,
110
+ };
111
+ return Some(stmt);
112
+ }
113
+ }
114
+ _ => {}
95
115
  }
96
116
  }
117
+
97
118
  None
98
119
  }
@@ -1,10 +1,11 @@
1
+ use devalang_types::Value;
2
+
1
3
  use crate::core::{
2
4
  audio::{
3
5
  engine::AudioEngine, evaluator::evaluate_condition_string,
4
6
  interpreter::driver::execute_audio_block,
5
7
  },
6
8
  parser::statement::Statement,
7
- shared::value::Value,
8
9
  store::{function::FunctionTable, global::GlobalStore, variable::VariableTable},
9
10
  };
10
11
 
@@ -43,7 +44,7 @@ pub fn interprete_condition_statement(
43
44
  global_store,
44
45
  variable_table.clone(),
45
46
  functions_table.clone(),
46
- &block,
47
+ block,
47
48
  base_bpm,
48
49
  base_duration,
49
50
  max_time,