use anyhow::Result;
use crate::engine::audio::interpreter::driver::AudioInterpreter;
use crate::language::syntax::ast::{Statement, StatementKind, Value};
#[test]
fn test_break_in_loop_exits_early() -> Result<()> {
let mut interp = AudioInterpreter::new(44100);
let print_stmt = Statement::print("tick", 1, 1);
let break_stmt = Statement::new(StatementKind::Break, Value::Null, 0, 2, 1);
let break_only = Statement::new(StatementKind::Break, Value::Null, 0, 10, 1);
interp.collect_events(&[break_only])?;
assert!(
interp.break_flag,
"break did not set break_flag when executed standalone"
);
interp.break_flag = false;
let direct_print = Statement::print("tick", 1, 1);
let direct_break = Statement::new(StatementKind::Break, Value::Null, 0, 11, 1);
interp.events.logs.clear();
interp.collect_events(&[direct_print.clone(), direct_break.clone()])?;
assert!(
interp.break_flag,
"break in direct body did not set break_flag"
);
assert_eq!(
interp.events.logs.len(),
1,
"expected one log from direct body execution"
);
interp.break_flag = false;
interp.events.logs.clear();
let loop_stmt = Statement::new(
StatementKind::Loop {
count: Value::Number(10.0),
body: vec![print_stmt, break_stmt],
},
Value::Null,
0,
1,
1,
);
interp.collect_events(&[loop_stmt])?;
assert!(
interp.events.logs.len() >= 1,
"expected at least one log event"
);
assert!(
interp.events.logs.len() < 10,
"break did not exit loop as expected"
);
Ok(())
}
#[test]
fn test_function_return_sets_return_variable() -> Result<()> {
let mut interp = AudioInterpreter::new(44100);
let ret_stmt = Statement::new(
StatementKind::Return {
value: Some(Box::new(Value::Number(42.0))),
},
Value::Null,
0,
2,
1,
);
let func_stmt = Statement::new(
StatementKind::Function {
name: "myfunc".to_string(),
parameters: vec![],
body: vec![ret_stmt],
},
Value::Null,
0,
1,
1,
);
let call_stmt = Statement::new(
StatementKind::Call {
name: "myfunc".to_string(),
args: vec![],
},
Value::Null,
0,
3,
1,
);
interp.collect_events(&[func_stmt, call_stmt])?;
if let Some(val) = interp.variables.get("__return") {
match val {
Value::Number(n) => assert_eq!(*n, 42.0),
other => panic!("unexpected return type: {:?}", other),
}
} else {
panic!("__return not set by function call");
}
Ok(())
}