devalang_wasm/engine/audio/interpreter/statements/
loop_.rs1use crate::engine::audio::interpreter::driver::AudioInterpreter;
2use crate::language::syntax::ast::{Statement, Value};
3use anyhow::Result;
5
6impl AudioInterpreter {
7 pub fn execute_loop(&mut self, count: &Value, body: &[Statement]) -> Result<()> {
9 let loop_count = match count {
11 Value::Number(n) => (*n) as usize,
12 Value::Identifier(ident) => {
13 if let Some(Value::Number(n)) = self.variables.get(ident) {
15 *n as usize
16 } else {
17 anyhow::bail!("❌ Loop iterator '{}' must be a number", ident);
18 }
19 }
20 _ => {
21 anyhow::bail!("❌ Loop iterator must be a number, found: {:?}", count);
22 }
23 };
24
25 for _iteration in 0..loop_count {
27 self.collect_events(body)?;
28 }
29
30 Ok(())
31 }
32
33 pub fn execute_for(
35 &mut self,
36 variable: &str,
37 iterable: &Value,
38 body: &[Statement],
39 ) -> Result<()> {
40 let items = match iterable {
42 Value::Array(arr) => arr.clone(),
43 Value::Identifier(ident) => {
44 if let Some(Value::Array(arr)) = self.variables.get(ident) {
46 arr.clone()
47 } else {
48 anyhow::bail!("❌ For iterable '{}' must be an array", ident);
49 }
50 }
51 Value::Range { start, end } => {
52 let start_val = match start.as_ref() {
54 Value::Number(n) => *n as i32,
55 _ => anyhow::bail!("❌ Range start must be a number"),
56 };
57 let end_val = match end.as_ref() {
58 Value::Number(n) => *n as i32,
59 _ => anyhow::bail!("❌ Range end must be a number"),
60 };
61
62 (start_val..=end_val)
64 .map(|i| Value::Number(i as f32))
65 .collect()
66 }
67 _ => {
68 anyhow::bail!(
69 "❌ For iterable must be an array or range, found: {:?}",
70 iterable
71 );
72 }
73 };
74
75 for (_idx, item) in items.iter().enumerate() {
77 let old_value = self.variables.insert(variable.to_string(), item.clone());
79
80 self.collect_events(body)?;
82
83 match old_value {
85 Some(val) => self.variables.insert(variable.to_string(), val),
86 None => self.variables.remove(variable),
87 };
88 }
89
90 Ok(())
91 }
92}