use mumu::parser::types::Value;
use mumu::parser::interpreter::Interpreter;
use crate::apply::apply_n_ary_function_value;
use super::common::{is_placeholder, make_two_arg_partial};
pub fn array_partition_bridge(interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
match args.len() {
2 => {
let pred_fn = &args[0];
let arr = &args[1];
let pred_pl = is_placeholder(pred_fn);
let arr_pl = is_placeholder(arr);
if !pred_pl && !arr_pl {
do_partition(interp, pred_fn.clone(), arr.clone())
} else {
Ok(make_two_arg_partial(
do_partition,
if pred_pl { None } else { Some(pred_fn.clone()) },
if arr_pl { None } else { Some(arr.clone()) },
"array-transform-partition-partial",
))
}
}
1 => Ok(make_two_arg_partial(
do_partition,
Some(args[0].clone()),
None,
"array-transform-partition-partial",
)),
0 => Ok(make_two_arg_partial(
do_partition,
None,
None,
"array-transform-partition-partial",
)),
n => Err(format!(
"array:partition => expects 2 arguments (fn, array), got {}",
n
)),
}
}
fn do_partition(
interp: &mut Interpreter,
pred_fn_val: Value,
arr_val: Value,
) -> Result<Value, String> {
let pred_fn = match pred_fn_val {
Value::Function(f) => f,
other => {
return Err(format!(
"array:partition => first argument must be a function, got {:?}",
other
))
}
};
match arr_val {
Value::IntArray(xs) => {
let mut yes: Vec<i32> = Vec::new();
let mut no: Vec<i32> = Vec::new();
for v in xs {
match apply_n_ary_function_value(interp, pred_fn.clone(), vec![Value::Int(v)]) {
Ok(Value::Bool(true)) => yes.push(v),
_ => no.push(v),
}
}
Ok(Value::MixedArray(vec![Value::IntArray(yes), Value::IntArray(no)]))
}
Value::FloatArray(xs) => {
let mut yes: Vec<f64> = Vec::new();
let mut no: Vec<f64> = Vec::new();
for v in xs {
match apply_n_ary_function_value(interp, pred_fn.clone(), vec![Value::Float(v)]) {
Ok(Value::Bool(true)) => yes.push(v),
_ => no.push(v),
}
}
Ok(Value::MixedArray(vec![Value::FloatArray(yes), Value::FloatArray(no)]))
}
Value::StrArray(xs) => {
let mut yes: Vec<String> = Vec::new();
let mut no: Vec<String> = Vec::new();
for s in xs {
match apply_n_ary_function_value(interp, pred_fn.clone(), vec![Value::SingleString(s.clone())]) {
Ok(Value::Bool(true)) => yes.push(s),
_ => no.push(s),
}
}
Ok(Value::MixedArray(vec![Value::StrArray(yes), Value::StrArray(no)]))
}
Value::BoolArray(xs) => {
let mut yes: Vec<bool> = Vec::new();
let mut no: Vec<bool> = Vec::new();
for b in xs {
match apply_n_ary_function_value(interp, pred_fn.clone(), vec![Value::Bool(b)]) {
Ok(Value::Bool(true)) => yes.push(b),
_ => no.push(b),
}
}
Ok(Value::MixedArray(vec![Value::BoolArray(yes), Value::BoolArray(no)]))
}
Value::MixedArray(xs) => {
let mut yes = Vec::new();
let mut no = Vec::new();
for v in xs {
match apply_n_ary_function_value(interp, pred_fn.clone(), vec![v.clone()]) {
Ok(Value::Bool(true)) => yes.push(v),
_ => no.push(v),
}
}
Ok(Value::MixedArray(vec![Value::MixedArray(yes), Value::MixedArray(no)]))
}
other => Err(format!("array:partition => unsupported array type: {:?}", other)),
}
}