use mumu::parser::types::{Value, FunctionValue};
use mumu::parser::interpreter::Interpreter;
use std::sync::{Arc, Mutex};
pub fn math_srand_bridge(
_interp: &mut Interpreter,
args: Vec<Value>
) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:srand => expected 1 argument (int/long/float seed), got {}", args.len()));
}
let seed = match &args[0] {
Value::Int(i) => *i as u64,
Value::Long(l) => *l as u64,
Value::Float(f) => *f as u64,
other => return Err(format!("math:srand => seed must be int/long/float, got {:?}", other)),
};
let rng = Arc::new(Mutex::new(SmallPrng::new(seed)));
let closure_rng = rng.clone();
let closure = move |_interp: &mut Interpreter, _args: Vec<Value>| {
let mut rng = closure_rng.lock().unwrap();
let next = rng.next_u32();
Ok(Value::Int(next as i32))
};
Ok(Value::Function(Box::new(FunctionValue::RustClosure(
"math:srand".to_string(),
Arc::new(Mutex::new(closure)),
0,
))))
}
struct SmallPrng {
state: u64,
}
impl SmallPrng {
fn new(seed: u64) -> Self {
SmallPrng { state: seed | 1 }
}
fn next_u32(&mut self) -> u32 {
let mut x = self.state;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
self.state = x;
(x & 0xFFFF_FFFF) as u32
}
}