use core_mumu::{
parser::{
interpreter::apply::apply_n_ary_function_value,
types::Value,
},
Interpreter,
};
use std::sync::Mutex;
use lazy_static::lazy_static;
pub struct LoopTask {
pub id: i32,
pub callback: Value,
pub canceled: bool,
}
lazy_static! {
pub static ref LOOP_TASKS: Mutex<Vec<LoopTask>> = Mutex::new(Vec::new());
static ref NEXT_LOOP_ID: Mutex<i32> = Mutex::new(4000);
}
pub fn event_loop_bridge(
interp: &mut Interpreter,
mut args: Vec<Value>
) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!(
"event:loop ⇒ expected exactly 1 argument (callback), got {}",
args.len()
));
}
let cb = args.remove(0);
if !matches!(cb, Value::Function(_)) {
return Err(format!(
"event:loop ⇒ argument must be a Function(...), got {:?}",
cb
));
}
let mut id_lock = NEXT_LOOP_ID.lock().unwrap();
let id = *id_lock;
*id_lock += 1;
drop(id_lock);
LOOP_TASKS.lock().unwrap().push(LoopTask {
id,
callback: cb,
canceled: false,
});
if interp.is_verbose() {
eprintln!("[event:loop] ⇒ registered LoopTask id={}", id);
}
Ok(Value::Int(id))
}
pub fn execute_loop_callbacks(interp: &mut Interpreter) -> usize {
let mut tasks = LOOP_TASKS.lock().unwrap();
let mut count = 0;
for task in tasks.iter_mut() {
if task.canceled {
continue;
}
if let Value::Function(f) = &task.callback {
let _ = apply_n_ary_function_value(interp, f.clone(), vec![]);
}
count += 1;
}
count
}
pub fn stop_loop_task_by_id(id: i32) {
let mut tasks = LOOP_TASKS.lock().unwrap();
for task in tasks.iter_mut() {
if task.id == id {
task.canceled = true;
break;
}
}
}