mumu-regex 0.1.1

Regex tools plugin for the Lava language
Documentation
// src/common.rs

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};

/// Make a closure for partial application of two-argument functions (arity-2)
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,
    )))
}

/// Make a closure for partial application of three-argument functions (arity-3)
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,
    )))
}