mumu-array 0.1.2

Array tools plugin for the MuMu/Lava language
Documentation
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:dropWhile 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()),
    };
    let xs = match arr {
        Value::IntArray(xs) => xs.into_iter().map(Value::Int).collect(),
        Value::FloatArray(xs) => xs.into_iter().map(Value::Float).collect(),
        Value::StrArray(xs) => xs.into_iter().map(Value::SingleString).collect(),
        Value::BoolArray(xs) => xs.into_iter().map(Value::Bool).collect(),
        Value::MixedArray(xs) => xs,
        _ => return Err("array:drop_while => second argument must be array".to_string()),
    };
    let mut result = Vec::new();
    let mut skipping = true;
    for v in xs {
        if skipping {
            let ret = mumu::parser::interpreter::apply_n_ary_function_value(interp, pred_fn.clone(), vec![v.clone()]);
            match ret {
                Ok(Value::Bool(true)) => continue,
                Ok(Value::Bool(false)) => {
                    skipping = false;
                    result.push(v);
                }
                _ => result.push(v),
            }
        } else {
            result.push(v);
        }
    }
    Ok(Value::MixedArray(result))
}