@devaloop/devalang 0.0.1-alpha.12 → 0.0.1-alpha.13

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 (62) hide show
  1. package/Cargo.toml +54 -53
  2. package/README.md +1 -14
  3. package/docs/CHANGELOG.md +26 -0
  4. package/docs/TODO.md +1 -1
  5. package/examples/index.deva +10 -13
  6. package/out-tsc/bin/devalang.exe +0 -0
  7. package/package.json +1 -1
  8. package/project-version.json +3 -3
  9. package/rust/cli/build.rs +25 -2
  10. package/rust/cli/check.rs +26 -3
  11. package/rust/cli/play.rs +1 -1
  12. package/rust/core/audio/engine.rs +126 -73
  13. package/rust/core/audio/interpreter/call.rs +72 -47
  14. package/rust/core/audio/interpreter/condition.rs +14 -12
  15. package/rust/core/audio/interpreter/driver.rs +84 -127
  16. package/rust/core/audio/interpreter/function.rs +21 -0
  17. package/rust/core/audio/interpreter/load.rs +1 -1
  18. package/rust/core/audio/interpreter/loop_.rs +24 -18
  19. package/rust/core/audio/interpreter/mod.rs +2 -1
  20. package/rust/core/audio/interpreter/sleep.rs +0 -6
  21. package/rust/core/audio/interpreter/spawn.rs +78 -60
  22. package/rust/core/audio/interpreter/trigger.rs +157 -70
  23. package/rust/core/audio/loader/trigger.rs +37 -4
  24. package/rust/core/audio/player.rs +20 -10
  25. package/rust/core/audio/renderer.rs +24 -25
  26. package/rust/core/debugger/mod.rs +2 -0
  27. package/rust/core/debugger/module.rs +47 -0
  28. package/rust/core/debugger/store.rs +25 -11
  29. package/rust/core/error/mod.rs +6 -0
  30. package/rust/core/lexer/handler/driver.rs +23 -1
  31. package/rust/core/lexer/handler/identifier.rs +1 -0
  32. package/rust/core/lexer/handler/mod.rs +1 -0
  33. package/rust/core/lexer/handler/parenthesis.rs +41 -0
  34. package/rust/core/lexer/token.rs +3 -0
  35. package/rust/core/parser/driver.rs +3 -1
  36. package/rust/core/parser/handler/dot.rs +64 -127
  37. package/rust/core/parser/handler/identifier/call.rs +69 -22
  38. package/rust/core/parser/handler/identifier/function.rs +92 -0
  39. package/rust/core/parser/handler/identifier/let_.rs +13 -19
  40. package/rust/core/parser/handler/identifier/mod.rs +1 -0
  41. package/rust/core/parser/handler/identifier/spawn.rs +74 -27
  42. package/rust/core/parser/statement.rs +16 -4
  43. package/rust/core/preprocessor/loader.rs +45 -29
  44. package/rust/core/preprocessor/module.rs +3 -1
  45. package/rust/core/preprocessor/processor.rs +26 -1
  46. package/rust/core/preprocessor/resolver/call.rs +61 -84
  47. package/rust/core/preprocessor/resolver/condition.rs +11 -6
  48. package/rust/core/preprocessor/resolver/driver.rs +52 -6
  49. package/rust/core/preprocessor/resolver/function.rs +78 -0
  50. package/rust/core/preprocessor/resolver/group.rs +43 -13
  51. package/rust/core/preprocessor/resolver/let_.rs +7 -10
  52. package/rust/core/preprocessor/resolver/mod.rs +2 -1
  53. package/rust/core/preprocessor/resolver/spawn.rs +64 -30
  54. package/rust/core/preprocessor/resolver/trigger.rs +7 -3
  55. package/rust/core/preprocessor/resolver/value.rs +10 -1
  56. package/rust/core/shared/value.rs +4 -1
  57. package/rust/core/store/function.rs +34 -0
  58. package/rust/core/store/global.rs +9 -10
  59. package/rust/core/store/mod.rs +2 -1
  60. package/rust/core/store/variable.rs +6 -0
  61. package/rust/lib.rs +10 -7
  62. package/rust/utils/mod.rs +45 -1
@@ -1,11 +1,10 @@
1
1
  use std::{ collections::HashMap, fs::File, io::BufReader, path::Path };
2
2
  use hound::{ SampleFormat, WavSpec, WavWriter };
3
3
  use rodio::{ Decoder, Source };
4
-
5
4
  use crate::core::{
6
5
  shared::value::Value,
7
6
  store::variable::VariableTable,
8
- utils::path::{ normalize_path, resolve_relative_path },
7
+ utils::path::normalize_path,
9
8
  };
10
9
 
11
10
  const SAMPLE_RATE: u32 = 44100;
@@ -14,7 +13,6 @@ const CHANNELS: u16 = 2;
14
13
  #[derive(Debug, Clone, PartialEq)]
15
14
  pub struct AudioEngine {
16
15
  pub volume: f32,
17
- pub variables: VariableTable,
18
16
  pub buffer: Vec<i16>,
19
17
  pub module_name: String,
20
18
  }
@@ -24,7 +22,6 @@ impl AudioEngine {
24
22
  AudioEngine {
25
23
  volume: 1.0,
26
24
  buffer: vec![],
27
- variables: VariableTable::new(),
28
25
  module_name,
29
26
  }
30
27
  }
@@ -57,12 +54,10 @@ impl AudioEngine {
57
54
 
58
55
  if self.buffer.iter().all(|&s| s == 0) {
59
56
  self.buffer = other.buffer;
60
- self.variables.variables.extend(other.variables.variables);
61
57
  return;
62
58
  }
63
59
 
64
60
  self.mix(&other);
65
- self.variables.variables.extend(other.variables.variables);
66
61
  }
67
62
 
68
63
  pub fn set_duration(&mut self, duration_secs: f32) {
@@ -73,10 +68,6 @@ impl AudioEngine {
73
68
  }
74
69
  }
75
70
 
76
- pub fn set_variables(&mut self, variables: VariableTable) {
77
- self.variables = variables;
78
- }
79
-
80
71
  pub fn generate_wav_file(&mut self, output_dir: &String) -> Result<(), String> {
81
72
  if self.buffer.len() % (CHANNELS as usize) != 0 {
82
73
  self.buffer.push(0);
@@ -168,79 +159,122 @@ impl AudioEngine {
168
159
  filepath: &str,
169
160
  time_secs: f32,
170
161
  dur_sec: f32,
171
- effects: Option<HashMap<String, Value>>
162
+ effects: Option<HashMap<String, Value>>,
163
+ variable_table: &VariableTable
172
164
  ) {
173
165
  if filepath.is_empty() {
174
166
  eprintln!("❌ Empty file path provided for audio sample.");
175
167
  return;
176
168
  }
177
169
 
170
+ let root = Path::new(env!("CARGO_MANIFEST_DIR"));
171
+ let module_root = Path::new(&self.module_name);
178
172
  let mut resolved_path = String::new();
179
173
 
180
- if filepath.starts_with("devalang://") {
181
- let root = Path::new(env!("CARGO_MANIFEST_DIR"));
182
- let parts = filepath.split("devalang://").collect::<Vec<&str>>();
183
- let object_parts = parts.get(1).unwrap_or(&"").split("/").collect::<Vec<&str>>();
184
- let object_type = object_parts.get(0).unwrap_or(&"").to_lowercase();
185
- let object_dir = object_parts.get(1).unwrap_or(&"").to_string();
186
- let object_name = object_parts.get(2).unwrap_or(&"").to_string();
174
+ // Get the variable path from the variable table
175
+ let mut var_path = filepath.to_string();
176
+ if let Some(Value::String(variable_path)) = variable_table.variables.get(filepath) {
177
+ var_path = variable_path.clone();
178
+ } else if let Some(Value::Sample(sample_path)) = variable_table.variables.get(filepath) {
179
+ var_path = sample_path.clone();
180
+ }
181
+
182
+ // If it's a namespace
183
+ if var_path.contains(".") {
184
+ let parts: Vec<&str> = var_path.trim_start_matches('.').split('.').collect();
185
+ if parts.len() == 2 {
186
+ let bank_name = parts[0];
187
+ let entity_name = parts[1];
188
+
189
+ // Verifies if the bank is declared
190
+ if !variable_table.variables.contains_key(bank_name) {
191
+ eprintln!(
192
+ "❌ Bank '{}' not declared. Please declare it first using : 'bank {}'",
193
+ bank_name,
194
+ bank_name
195
+ );
196
+ return;
197
+ }
187
198
 
188
- if object_type.contains("bank") {
189
199
  resolved_path = root
190
200
  .join(".deva")
191
201
  .join("bank")
192
- .join(object_dir)
193
- .join(format!("{}.wav", object_name))
194
- .to_str()
195
- .unwrap_or("")
202
+ .join(bank_name)
203
+ .join(format!("{}.wav", entity_name))
204
+ .to_string_lossy()
196
205
  .to_string();
197
206
  } else {
198
- eprintln!("❌ Unsupported devalang:// object type: {}", object_type);
207
+ eprintln!("❌ Invalid namespace format: {}", var_path);
199
208
  return;
200
209
  }
201
- } else {
202
- let module_path = &self.module_name;
203
- let root = Path::new(module_path).parent();
204
-
205
- if let Some(root_path) = root {
206
- resolved_path = root_path.join(filepath).to_str().unwrap_or("").to_string();
207
- } else {
208
- eprintln!("❌ Could not resolve root path for module: {}", module_path);
210
+ } else if var_path.starts_with("devalang://") {
211
+ let path_after_protocol = var_path.replace("devalang://", "");
212
+ let parts: Vec<&str> = path_after_protocol.split('/').collect();
213
+
214
+ if parts.len() < 3 {
215
+ eprintln!(
216
+ "❌ Invalid devalang:// path format. Expected devalang://<type>/<bank>/<entity>"
217
+ );
209
218
  return;
210
219
  }
220
+
221
+ let obj_type = parts[0];
222
+ let bank_name = parts[1];
223
+ let entity_name = parts[2];
224
+
225
+ resolved_path = root
226
+ .join(".deva")
227
+ .join(obj_type)
228
+ .join(bank_name)
229
+ .join(format!("{}.wav", entity_name))
230
+ .to_string_lossy()
231
+ .to_string();
232
+ } else {
233
+ // Else, resolve as a relative path
234
+ let entry_dir = module_root.parent().unwrap_or(root);
235
+ let absolute_path = root.join(entry_dir).join(&var_path);
236
+
237
+ resolved_path = normalize_path(absolute_path.to_string_lossy().to_string());
211
238
  }
212
239
 
240
+ // Verify if the file exists
213
241
  if !Path::new(&resolved_path).exists() {
214
242
  eprintln!("❌ Audio file not found at: {}", resolved_path);
215
243
  return;
216
244
  }
217
245
 
218
- let file = BufReader::new(
219
- File::open(&resolved_path).expect(&format!("Failed to open audio file {}", filepath))
220
- );
221
- let decoder = Decoder::new(file).expect("Failed to decode audio file");
246
+ let file = match File::open(&resolved_path) {
247
+ Ok(f) => BufReader::new(f),
248
+ Err(e) => {
249
+ eprintln!("Failed to open audio file {}: {}", resolved_path, e);
250
+ return;
251
+ }
252
+ };
253
+
254
+ let decoder = match Decoder::new(file) {
255
+ Ok(d) => d,
256
+ Err(e) => {
257
+ eprintln!("❌ Failed to decode audio file {}: {}", resolved_path, e);
258
+ return;
259
+ }
260
+ };
222
261
 
223
- // Mono or stereo reading possible here, we will duplicate in L/R
224
262
  let max_mono_samples = (dur_sec * (SAMPLE_RATE as f32)) as usize;
225
263
  let samples: Vec<i16> = decoder.convert_samples().take(max_mono_samples).collect();
226
264
 
227
265
  if samples.is_empty() {
228
- eprintln!("No samples found in the audio file: {}", filepath);
266
+ eprintln!("No samples read from {}", resolved_path);
229
267
  return;
230
268
  }
231
269
 
232
- // Pad the buffer to ensure it can accommodate the new samples
270
+ // Calculate buffer offset and size
233
271
  let offset = (time_secs * (SAMPLE_RATE as f32) * (CHANNELS as f32)) as usize;
234
272
  let required_len = offset + samples.len() * (CHANNELS as usize);
235
- let padded_required_len = if required_len % 2 == 1 {
236
- required_len + 1
237
- } else {
238
- required_len
239
- };
240
-
241
- self.buffer.resize(padded_required_len, 0);
273
+ if self.buffer.len() < required_len {
274
+ self.buffer.resize(required_len, 0);
275
+ }
242
276
 
243
- // Apply effects
277
+ // Apply effects and mix
244
278
  if let Some(effects_map) = effects {
245
279
  self.pad_samples(&samples, time_secs, Some(effects_map));
246
280
  } else {
@@ -263,8 +297,10 @@ impl AudioEngine {
263
297
  let mut fade_in = 0.0;
264
298
  let mut fade_out = 0.0;
265
299
  let mut pitch = 1.0;
266
- let mut drive = 0.0;
300
+ let mut drive = 0.0;
267
301
  let mut reverb = 0.0;
302
+ let mut delay = 0.0; // delay time in seconds
303
+ let delay_feedback = 0.35; // default feedback
268
304
 
269
305
  if let Some(map) = &effects_map {
270
306
  for (key, val) in map {
@@ -285,12 +321,14 @@ impl AudioEngine {
285
321
  pitch = *v;
286
322
  }
287
323
  ("drive", Value::Number(v)) => {
288
- // Drive effect can be implemented here if needed
289
324
  drive = *v;
290
325
  }
291
326
  ("reverb", Value::Number(v)) => {
292
327
  reverb = *v;
293
328
  }
329
+ ("delay", Value::Number(v)) => {
330
+ delay = *v;
331
+ }
294
332
  _ => eprintln!("⚠️ Unknown or invalid effect '{}'", key),
295
333
  }
296
334
  }
@@ -299,49 +337,64 @@ impl AudioEngine {
299
337
  let fade_in_samples = (fade_in * (SAMPLE_RATE as f32)) as usize;
300
338
  let fade_out_samples = (fade_out * (SAMPLE_RATE as f32)) as usize;
301
339
 
302
- for (i, &sample) in samples.iter().enumerate() {
303
- // Gain
304
- let mut adjusted = (sample as f32) * gain;
340
+ let delay_samples = if delay > 0.0 { (delay * (SAMPLE_RATE as f32)) as usize } else { 0 };
341
+ let mut delay_buffer: Vec<f32> = vec![0.0; total_samples + delay_samples];
305
342
 
306
- // Fade in
343
+ for i in 0..total_samples {
344
+ // PITCH FIRST
345
+ let pitch_index = if pitch != 1.0 { ((i as f32) / pitch) as usize } else { i };
346
+
347
+ let mut adjusted = if pitch_index < total_samples {
348
+ samples[pitch_index] as f32
349
+ } else {
350
+ 0.0
351
+ };
352
+
353
+ // GAIN
354
+ adjusted *= gain;
355
+
356
+ // FADE IN/OUT
307
357
  if fade_in_samples > 0 && i < fade_in_samples {
308
358
  adjusted *= (i as f32) / (fade_in_samples as f32);
309
359
  }
310
-
311
- // Fade out
312
360
  if fade_out_samples > 0 && i >= total_samples.saturating_sub(fade_out_samples) {
313
361
  adjusted *= ((total_samples - i) as f32) / (fade_out_samples as f32);
314
362
  }
315
363
 
316
- // Pitch adjustment
317
- if pitch != 1.0 {
318
- let pitch_adjusted_index = ((i as f32) / pitch) as usize;
319
- if pitch_adjusted_index < total_samples {
320
- adjusted = (samples[pitch_adjusted_index] as f32) * gain;
321
- } else {
322
- adjusted = 0.0; // Out of bounds, set to zero
323
- }
364
+ // DRIVE (soft)
365
+ if drive > 0.0 {
366
+ let normalized = adjusted / (i16::MAX as f32);
367
+ let pre_gain = (10f32).powf(drive / 20.0); // dB mapping
368
+ let driven = (normalized * pre_gain).tanh();
369
+ adjusted = driven * (i16::MAX as f32);
324
370
  }
325
371
 
326
- // Drive effect
327
- if drive > 0.0 {
328
- adjusted = adjusted.tanh() * (1.0 + drive);
372
+ // DELAY
373
+ if delay_samples > 0 && i >= delay_samples {
374
+ let echo = delay_buffer[i - delay_samples] * delay_feedback;
375
+ adjusted += echo;
376
+ }
377
+ if delay_samples > 0 {
378
+ delay_buffer[i] = adjusted;
329
379
  }
330
380
 
331
- // Reverb effect
381
+ // REVERB
332
382
  if reverb > 0.0 {
333
- let reverb_delay = (reverb * (SAMPLE_RATE as f32)) as usize;
383
+ let reverb_delay = (0.03 * (SAMPLE_RATE as f32)) as usize;
334
384
  if i >= reverb_delay {
335
- adjusted += self.buffer[offset + i - reverb_delay] as f32 * 0.5; // Simple feedback
385
+ adjusted += (self.buffer[offset + i - reverb_delay] as f32) * reverb;
336
386
  }
337
387
  }
338
388
 
339
- // Clamp
389
+ // CLAMP
340
390
  let adjusted_sample = adjusted.round().clamp(i16::MIN as f32, i16::MAX as f32) as i16;
341
391
 
342
- // Pan (L/R split)
343
- let left = ((adjusted_sample as f32) * (1.0 - pan.clamp(0.0, 1.0))) as i16;
344
- let right = ((adjusted_sample as f32) * (1.0 + pan.clamp(-1.0, 0.0)).abs()) as i16;
392
+ // PAN
393
+ let left_gain = 1.0 - pan.max(0.0); // Pan > 0 => reduce left
394
+ let right_gain = 1.0 + pan.min(0.0); // Pan < 0 => reduce right
395
+
396
+ let left = ((adjusted_sample as f32) * left_gain) as i16;
397
+ let right = ((adjusted_sample as f32) * right_gain) as i16;
345
398
 
346
399
  let left_pos = offset + i * 2;
347
400
  let right_pos = left_pos + 1;
@@ -1,70 +1,95 @@
1
1
  use crate::core::{
2
- audio::{ engine::AudioEngine, interpreter::{ driver::execute_audio_block } },
3
- parser::statement::{ Statement, StatementKind },
4
- shared::{ duration::Duration, value::Value },
5
- store::variable::VariableTable,
2
+ audio::{engine::AudioEngine, interpreter::driver::execute_audio_block},
3
+ parser::statement::{Statement, StatementKind},
4
+ shared::value::Value,
5
+ store::{function::FunctionTable, global::GlobalStore, variable::VariableTable},
6
6
  };
7
7
 
8
8
  pub fn interprete_call_statement(
9
9
  stmt: &Statement,
10
- audio_engine: AudioEngine,
11
- variable_table: VariableTable,
10
+ audio_engine: &mut AudioEngine,
11
+ variable_table: &VariableTable,
12
+ functions: &FunctionTable,
13
+ global_store: &GlobalStore,
12
14
  base_bpm: f32,
13
15
  base_duration: f32,
14
16
  max_end_time: f32,
15
17
  cursor_time: f32,
16
- all_statements: &Vec<Statement>
17
- ) -> (AudioEngine, f32, f32, f32) {
18
- match &stmt.value {
19
- Value::String(identifier) | Value::Identifier(identifier) => {
20
- if
21
- let Some(group_stmt) = all_statements
22
- .iter()
23
- .find(|s| {
24
- matches!(s.kind, StatementKind::Group) &&
25
- s.value.get("identifier") == Some(&Value::String(identifier.clone()))
26
- })
27
- {
28
- if let Some(Value::Block(block)) = group_stmt.value.get("body") {
29
- let (eng, _, end_time) = execute_audio_block(
30
- audio_engine,
31
- variable_table,
32
- block.clone(),
33
- base_bpm,
34
- base_duration,
35
- max_end_time,
36
- cursor_time
18
+ ) -> (f32, f32) {
19
+ match &stmt.kind {
20
+ StatementKind::Call { name, args } => {
21
+ // 1. Cas : fonction classique
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()
37
29
  );
38
- return (eng, max_end_time.max(end_time), end_time, cursor_time);
39
- } else {
40
- eprintln!("❌ Group '{}' found but no valid body block", identifier);
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());
41
36
  }
42
- } else {
43
- eprintln!("❌ Group '{}' not found in statements", identifier);
44
- }
45
- }
46
37
 
47
- Value::Map(map) => {
48
- if let Some(Value::Block(block)) = map.get("body") {
49
- let (eng, _, end_time) = execute_audio_block(
38
+ return execute_audio_block(
50
39
  audio_engine,
51
- variable_table,
52
- block.clone(),
40
+ global_store,
41
+ local_vars,
42
+ functions.clone(),
43
+ func.body.clone(),
53
44
  base_bpm,
54
45
  base_duration,
55
46
  max_end_time,
56
- cursor_time
47
+ cursor_time,
57
48
  );
58
- return (eng, max_end_time.max(end_time), end_time, cursor_time);
59
- } else {
60
- eprintln!("❌ Call map has no 'body' block");
61
49
  }
62
- }
63
50
 
64
- other => {
65
- eprintln!("❌ Invalid call statement: expected identifier or map, found {:?}", other);
51
+ // 2. Cas : group dans le scope local OU global
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.clone(),
61
+ base_bpm,
62
+ base_duration,
63
+ max_end_time,
64
+ cursor_time,
65
+ );
66
+ }
67
+ }
68
+ }
69
+
70
+ eprintln!("❌ Function or group '{}' not found", name);
66
71
  }
72
+
73
+ _ => eprintln!("❌ interprete_call_statement expected Call, got {:?}", stmt.kind),
67
74
  }
68
75
 
69
- (audio_engine, base_bpm, max_end_time, cursor_time)
76
+ (max_end_time, cursor_time)
77
+ }
78
+
79
+ fn find_group<'a>(
80
+ name: &str,
81
+ variable_table: &'a VariableTable,
82
+ global_store: &'a GlobalStore,
83
+ ) -> Option<&'a Statement> {
84
+ if let Some(Value::Statement(stmt_box)) = variable_table.get(name) {
85
+ if let StatementKind::Group = stmt_box.kind {
86
+ return Some(stmt_box);
87
+ }
88
+ }
89
+ if let Some(Value::Statement(stmt_box)) = global_store.variables.variables.get(name) {
90
+ if let StatementKind::Group = stmt_box.kind {
91
+ return Some(stmt_box);
92
+ }
93
+ }
94
+ None
70
95
  }
@@ -6,20 +6,20 @@ use crate::core::{
6
6
  },
7
7
  parser::statement::Statement,
8
8
  shared::value::Value,
9
- store::variable::VariableTable,
9
+ store::{ function::FunctionTable, global::GlobalStore, variable::VariableTable },
10
10
  };
11
11
 
12
12
  pub fn interprete_condition_statement(
13
13
  stmt: &Statement,
14
- audio_engine: AudioEngine,
15
- variable_table: VariableTable,
14
+ audio_engine: &mut AudioEngine,
15
+ global_store: &GlobalStore,
16
+ variable_table: &VariableTable,
17
+ functions_table: &FunctionTable,
16
18
  base_bpm: f32,
17
19
  base_duration: f32,
18
20
  max_end_time: f32,
19
21
  cursor_time: f32
20
- ) -> (AudioEngine, f32, f32) {
21
- let mut engine = audio_engine.clone();
22
- let mut vars = variable_table.clone();
22
+ ) -> (f32, f32) {
23
23
  let mut cur_time = cursor_time;
24
24
  let mut max_time = max_end_time;
25
25
 
@@ -32,23 +32,25 @@ pub fn interprete_condition_statement(
32
32
 
33
33
  let should_execute = match map.get("condition") {
34
34
  Some(Value::Boolean(b)) => *b,
35
- Some(Value::String(expr)) => evaluate_condition_string(expr, &vars),
35
+ Some(Value::String(expr)) => evaluate_condition_string(expr, &variable_table.clone()),
36
36
  Some(_) => false,
37
37
  None => true,
38
38
  };
39
39
 
40
40
  if should_execute {
41
41
  if let Some(Value::Block(block)) = map.get("body") {
42
- let (new_engine, _, new_max) = execute_audio_block(
43
- engine,
44
- vars,
42
+ let (new_max, cursor_time) = execute_audio_block(
43
+ audio_engine,
44
+ global_store,
45
+ variable_table.clone(),
46
+ functions_table.clone(),
45
47
  block.clone(),
46
48
  base_bpm,
47
49
  base_duration,
48
50
  max_time,
49
51
  cur_time
50
52
  );
51
- return (new_engine, new_max, new_max);
53
+ return (new_max, cursor_time);
52
54
  } else {
53
55
  break;
54
56
  }
@@ -65,5 +67,5 @@ pub fn interprete_condition_statement(
65
67
  }
66
68
  }
67
69
 
68
- (audio_engine, max_end_time, cursor_time)
70
+ (max_end_time, cursor_time)
69
71
  }