use crate::apply::apply_n_ary_function_value;
use mumu::parser::types::Value;
use mumu::parser::interpreter::Interpreter;
use super::common::{is_placeholder, make_two_arg_partial};
pub fn array_drop_while_bridge(interp: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
match args.len() {
0 => Ok(make_two_arg_partial(do_drop_while, None, None, "array-transform-drop_while-partial")),
1 => {
if is_placeholder(&args[0]) {
Ok(make_two_arg_partial(do_drop_while, None, None, "array-transform-drop_while-partial"))
} else {
Ok(make_two_arg_partial(do_drop_while, Some(args[0].clone()), None, "array-transform-drop_while-partial"))
}
}
2 => {
let a1_pl = is_placeholder(&args[0]);
let a2_pl = is_placeholder(&args[1]);
if !a1_pl && !a2_pl {
do_drop_while(interp, args[0].clone(), args[1].clone())
} else {
Ok(make_two_arg_partial(
do_drop_while,
if a1_pl { None } else { Some(args[0].clone()) },
if a2_pl { None } else { Some(args[1].clone()) },
"array-transform-drop_while-partial"
))
}
}
_ => Err("array:drop_while expects 2 arguments (fn, array)".to_string()),
}
}
fn do_drop_while(interp: &mut Interpreter, pred: Value, arr: Value) -> Result<Value, String> {
let pred_fn = match pred {
Value::Function(fb) => fb,
_ => return Err("array:drop_while => first argument must be a function".to_string()),
};
match arr {
Value::IntArray(xs) => {
let mut out: Vec<i32> = Vec::new();
let mut skipping = true;
for v in xs {
if skipping {
let ret = apply_n_ary_function_value(interp, pred_fn.clone(), vec![Value::Int(v)]);
match ret {
Ok(Value::Bool(true)) => continue,
_ => {
skipping = false;
out.push(v);
}
}
} else {
out.push(v);
}
}
Ok(Value::IntArray(out))
}
Value::FloatArray(xs) => {
let mut out: Vec<f64> = Vec::new();
let mut skipping = true;
for v in xs {
if skipping {
let ret = apply_n_ary_function_value(interp, pred_fn.clone(), vec![Value::Float(v)]);
match ret {
Ok(Value::Bool(true)) => continue,
_ => {
skipping = false;
out.push(v);
}
}
} else {
out.push(v);
}
}
Ok(Value::FloatArray(out))
}
Value::StrArray(xs) => {
let mut out: Vec<String> = Vec::new();
let mut skipping = true;
for s in xs {
if skipping {
let ret = apply_n_ary_function_value(interp, pred_fn.clone(), vec![Value::SingleString(s.clone())]);
match ret {
Ok(Value::Bool(true)) => continue,
_ => {
skipping = false;
out.push(s);
}
}
} else {
out.push(s);
}
}
Ok(Value::StrArray(out))
}
Value::BoolArray(xs) => {
let mut out: Vec<bool> = Vec::new();
let mut skipping = true;
for b in xs {
if skipping {
let ret = apply_n_ary_function_value(interp, pred_fn.clone(), vec![Value::Bool(b)]);
match ret {
Ok(Value::Bool(true)) => continue,
_ => {
skipping = false;
out.push(b);
}
}
} else {
out.push(b);
}
}
Ok(Value::BoolArray(out))
}
Value::MixedArray(xs) => {
let mut out = Vec::new();
let mut skipping = true;
for v in xs {
if skipping {
let ret = apply_n_ary_function_value(interp, pred_fn.clone(), vec![v.clone()]);
match ret {
Ok(Value::Bool(true)) => continue,
_ => {
skipping = false;
out.push(v);
}
}
} else {
out.push(v);
}
}
Ok(Value::MixedArray(out))
}
other => Err(format!("array:drop_while => second argument must be array, got {:?}", other)),
}
}