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_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) { aa = Some(arg); }
continue;
}
if bb.is_none() {
if !is_placeholder(&arg) { bb = Some(arg); }
continue;
}
return Err("regex => partial => too many arguments".to_string());
}
if aa.is_some() && bb.is_some() {
finalize_fn(vec![aa.unwrap(), bb.unwrap()])
} else {
Ok(make_two_arg_partial(finalize_fn, aa, bb))
}
};
Value::Function(Box::new(RustClosure(
"regex-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) { aa = Some(arg); }
continue;
}
if bb.is_none() {
if !is_placeholder(&arg) { bb = Some(arg); }
continue;
}
if cc.is_none() {
if !is_placeholder(&arg) { cc = Some(arg); }
continue;
}
return Err("regex => partial => too many arguments".to_string());
}
if aa.is_some() && bb.is_some() && cc.is_some() {
finalize_fn(vec![aa.unwrap(), bb.unwrap(), cc.unwrap()])
} else {
Ok(make_three_arg_partial(finalize_fn, aa, bb, cc))
}
};
Value::Function(Box::new(RustClosure(
"regex-3arg-partial".to_string(),
Arc::new(Mutex::new(closure)),
0,
)))
}