use mumu::parser::types::Value;
pub fn is_placeholder(v: &Value) -> bool {
match v {
Value::Placeholder => true,
Value::SingleString(s) if s == "_" => true,
Value::StrArray(ss) if ss.len() == 1 && ss[0] == "_" => true,
_ => false,
}
}
use mumu::parser::types::FunctionValue::RustClosure;
use std::sync::{Arc, Mutex};
pub fn make_one_arg_partial(
finalize_fn: fn(Vec<Value>) -> Result<Value, String>,
known_opt: Option<Value>
) -> Value {
let closure = move |_interp: &mut mumu::parser::interpreter::Interpreter, new_args: Vec<Value>| {
let mut current_known = known_opt.clone();
for arg in new_args {
if current_known.is_none() {
if is_placeholder(&arg) {} else { current_known = Some(arg); }
continue;
}
return Err("string => partial => too many arguments".to_string());
}
if let Some(real_val) = current_known {
finalize_fn(vec![real_val])
} else {
Ok(make_one_arg_partial(finalize_fn, current_known))
}
};
Value::Function(Box::new(RustClosure(
"string-1arg-partial".to_string(),
Arc::new(Mutex::new(closure)),
0,
)))
}
pub fn make_two_arg_partial(
finalize_fn: fn(Vec<Value>) -> Result<Value, String>,
a_opt: Option<Value>,
b_opt: Option<Value>,
) -> Value {
let closure = move |_interp: &mut mumu::parser::interpreter::Interpreter, new_args: Vec<Value>| {
let mut aa = a_opt.clone();
let mut bb = b_opt.clone();
for arg in new_args {
if aa.is_none() {
if is_placeholder(&arg) {} else { aa = Some(arg); }
continue;
}
if bb.is_none() {
if is_placeholder(&arg) {} else { bb = Some(arg); }
continue;
}
return Err("string => partial => too many arguments".to_string());
}
if aa.is_some() && bb.is_some() {
finalize_fn(vec![aa.as_ref().unwrap().clone(), bb.as_ref().unwrap().clone()])
} else {
Ok(make_two_arg_partial(finalize_fn, aa, bb))
}
};
Value::Function(Box::new(RustClosure(
"string-2arg-partial".to_string(),
Arc::new(Mutex::new(closure)),
0,
)))
}
pub fn make_three_arg_partial(
finalize_fn: fn(Vec<Value>) -> Result<Value, String>,
a_opt: Option<Value>,
b_opt: Option<Value>,
c_opt: Option<Value>,
) -> Value {
let closure = move |_interp: &mut mumu::parser::interpreter::Interpreter, new_args: Vec<Value>| {
let mut aa = a_opt.clone();
let mut bb = b_opt.clone();
let mut cc = c_opt.clone();
for arg in new_args {
if aa.is_none() {
if is_placeholder(&arg) {} else { aa = Some(arg); }
continue;
}
if bb.is_none() {
if is_placeholder(&arg) {} else { bb = Some(arg); }
continue;
}
if cc.is_none() {
if is_placeholder(&arg) {} else { cc = Some(arg); }
continue;
}
return Err("string => partial => too many arguments".to_string());
}
if aa.is_some() && bb.is_some() && cc.is_some() {
finalize_fn(vec![
aa.as_ref().unwrap().clone(),
bb.as_ref().unwrap().clone(),
cc.as_ref().unwrap().clone(),
])
} else {
Ok(make_three_arg_partial(finalize_fn, aa, bb, cc))
}
};
Value::Function(Box::new(RustClosure(
"string-3arg-partial".to_string(),
Arc::new(Mutex::new(closure)),
0,
)))
}