devalang_wasm/engine/audio/interpreter/statements/
loop_.rs

1use crate::engine::audio::interpreter::driver::AudioInterpreter;
2use crate::language::syntax::ast::{Statement, Value};
3/// Loop and For statement execution
4use anyhow::Result;
5
6impl AudioInterpreter {
7    /// Execute a Loop statement (repeat N times)
8    pub fn execute_loop(&mut self, count: &Value, body: &[Statement]) -> Result<()> {
9        // Extract loop count
10        let loop_count = match count {
11            Value::Number(n) => *n as usize,
12            Value::Identifier(ident) => {
13                // Try to get variable value
14                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        println!("🔁 Loop: {} iterations", loop_count);
26
27        // Execute body N times
28        for iteration in 0..loop_count {
29            if iteration > 0 && iteration % 10 == 0 {
30                println!("  └─ Iteration {}/{}", iteration, loop_count);
31            }
32            self.collect_events(body)?;
33        }
34
35        Ok(())
36    }
37
38    /// Execute a For statement (foreach item in array/range)
39    pub fn execute_for(
40        &mut self,
41        variable: &str,
42        iterable: &Value,
43        body: &[Statement],
44    ) -> Result<()> {
45        // Extract items to iterate over
46        let items = match iterable {
47            Value::Array(arr) => arr.clone(),
48            Value::Identifier(ident) => {
49                // Try to get variable value
50                if let Some(Value::Array(arr)) = self.variables.get(ident) {
51                    arr.clone()
52                } else {
53                    anyhow::bail!("❌ For iterable '{}' must be an array", ident);
54                }
55            }
56            Value::Range { start, end } => {
57                // Generate range [start..end]
58                let start_val = match start.as_ref() {
59                    Value::Number(n) => *n as i32,
60                    _ => anyhow::bail!("❌ Range start must be a number"),
61                };
62                let end_val = match end.as_ref() {
63                    Value::Number(n) => *n as i32,
64                    _ => anyhow::bail!("❌ Range end must be a number"),
65                };
66
67                // Create array from range
68                (start_val..=end_val)
69                    .map(|i| Value::Number(i as f32))
70                    .collect()
71            }
72            _ => {
73                anyhow::bail!(
74                    "❌ For iterable must be an array or range, found: {:?}",
75                    iterable
76                );
77            }
78        };
79
80        println!("🔄 For: {} in {} items", variable, items.len());
81
82        // Execute body for each item
83        for (idx, item) in items.iter().enumerate() {
84            // Set loop variable
85            let old_value = self.variables.insert(variable.to_string(), item.clone());
86
87            if idx < 5 || (idx + 1) == items.len() {
88                // Show first 5 and last iteration
89                println!("  └─ {} = {:?}", variable, item);
90            } else if idx == 5 {
91                println!("  └─ ... ({} more items)", items.len() - 6);
92            }
93
94            // Execute body
95            self.collect_events(body)?;
96
97            // Restore old value or remove
98            match old_value {
99                Some(val) => self.variables.insert(variable.to_string(), val),
100                None => self.variables.remove(variable),
101            };
102        }
103
104        Ok(())
105    }
106}