use mumu::parser::types::Value;
use mumu::parser::interpreter::Interpreter;
use std::sync::{Arc, Mutex};
pub fn array_prop_bridge(
_interp: &mut Interpreter,
args: Vec<Value>
) -> Result<Value, String> {
match args.len() {
0 => Ok(make_prop_partial(None, None)),
1 => match &args[0] {
Value::KeyedArray(_) => Ok(make_prop_partial(None, Some(args[0].clone()))),
Value::Placeholder => Ok(make_prop_partial(None, None)),
_ => Ok(make_prop_partial(Some(args[0].clone()), None)),
},
2 => {
let a1_pl = matches!(&args[0], Value::Placeholder);
let a2_pl = matches!(&args[1], Value::Placeholder);
if a1_pl && a2_pl {
return Ok(make_prop_partial(None, None));
}
if a1_pl {
return Ok(make_prop_partial(None, Some(args[1].clone())));
}
if a2_pl {
return Ok(make_prop_partial(Some(args[0].clone()), None));
}
do_prop_lookup(&args[0], &args[1])
}
_ => Err("array:prop expects at most two arguments".to_string()),
}
}
fn make_prop_partial(
key_opt: Option<Value>,
arr_opt: Option<Value>
) -> Value {
use mumu::parser::types::FunctionValue::RustClosure;
let closure = move |_interp: &mut Interpreter, new_args: Vec<Value>| {
let mut k = key_opt.clone();
let mut a = arr_opt.clone();
for arg in new_args {
if k.is_none() && !matches!(arg, Value::Placeholder) {
k = Some(arg);
continue;
}
if a.is_none() && !matches!(arg, Value::Placeholder) {
a = Some(arg);
continue;
}
return Err("array:prop partial expects only a missing key or object".to_string());
}
if k.is_some() && a.is_some() {
do_prop_lookup(&k.unwrap(), &a.unwrap())
} else {
Ok(make_prop_partial(k, a))
}
};
Value::Function(Box::new(RustClosure(
"array:prop-partial".to_string(),
Arc::new(Mutex::new(closure)),
0,
)))
}
fn do_prop_lookup(key_val: &Value, arr_val: &Value) -> Result<Value, String> {
let key = match key_val {
Value::SingleString(s) => s,
Value::StrArray(ss) if ss.len() == 1 => &ss[0],
_ => return Err("array:prop expects a string key as the first argument".to_string()),
};
match arr_val {
Value::KeyedArray(map) => map.get(key).cloned().ok_or_else(|| format!("Key '{}' not found", key)),
_ => Err("array:prop expects keyed array as the second argument".to_string()),
}
}