use mumu::{
parser::interpreter::{DynamicFnInfo, Interpreter},
parser::types::{FunctionValue, Value},
};
use std::{
ffi::{c_void, CStr},
sync::{Arc, Mutex},
};
mod arb;
mod sqrt;
mod unary;
mod partials;
mod rotate_point;
mod srand;
use arb::math_arb_bridge;
use sqrt::math_sqrt_bridge;
use unary::*;
use partials::*;
use rotate_point::math_rotate_point_bridge;
use srand::math_srand_bridge;
const VALUE_TO_STRING_RECURSION_LIMIT: usize = 32;
pub fn value_to_string(val: &Value) -> String {
value_to_string_with_depth(val, 0)
}
fn value_to_string_with_depth(val: &Value, depth: usize) -> String {
if depth > VALUE_TO_STRING_RECURSION_LIMIT {
return "<recursion>".to_string();
}
match val {
Value::Int(x) => x.to_string(),
Value::IntArray(xs) => format!("{:?}", xs),
Value::Int2DArray(rows) => format!("{:?}", rows),
Value::Float(f) => f.to_string(),
Value::FloatArray(ff) => format!("{:?}", ff),
Value::Float2DArray(rows) => format!("{:?}", rows),
Value::StrArray(ss) => format!("{:?}", ss),
Value::KeyedArray(map) => {
let mut s = String::from("{ ");
let mut first = true;
for (k, v) in map.iter() {
if !first {
s.push_str(", ");
}
first = false;
s.push_str(k);
s.push_str(": ");
s.push_str(&value_to_string_with_depth(v, depth + 1));
}
s.push_str(" }");
s
}
Value::Function(_) => "[Function]".to_string(),
Value::Bool(b) => b.to_string(),
Value::BoolArray(bb) => format!("{:?}", bb),
Value::Placeholder => "_".to_string(),
Value::SingleString(s) => format!("\"{}\"", s), Value::Long(l) => l.to_string(),
Value::Stream(sh) => format!("<Stream id={}, label={}>", sh.stream_id, sh.label),
Value::Iterator(_) => "[Iterator]".to_string(),
Value::Tensor(_) => "[Tensor]".to_string(),
Value::MixedArray(items) => {
let inner = items
.iter()
.map(|v| value_to_string_with_depth(v, depth + 1))
.collect::<Vec<_>>()
.join(", ");
format!("[{}]", inner)
}
Value::Ref(arc_mutex) => {
value_to_string_with_depth(&arc_mutex.lock().unwrap(), depth + 1)
}
Value::Undefined => "undefined".to_string(),
Value::Regex(rx) => format!("Regex(/{}{}/)", rx.pattern, rx.flags),
}
}
pub fn register_all(interp: &mut Interpreter) {
macro_rules! reg {
($name:expr, $f:expr) => {{
let func = Arc::new(Mutex::new($f));
interp.register_dynamic_function_ex($name, DynamicFnInfo::new(func.clone(), false));
interp.set_variable($name, Value::Function(Box::new(FunctionValue::Named($name.into()))));
}};
}
reg!("math:plus", math_plus_bridge);
reg!("math:subtract", math_subtract_bridge);
reg!("math:multiply", math_multiply_bridge);
reg!("math:divide", math_divide_bridge);
reg!("math:pow", math_pow_bridge);
reg!("math:mod", math_mod_bridge);
reg!("math:atan2", math_atan2_bridge);
reg!("math:imul", math_imul_bridge);
reg!("math:max", math_max_bridge);
reg!("math:min", math_min_bridge);
reg!("math:hypot", math_hypot_bridge);
reg!("math:abs", math_abs_bridge);
reg!("math:acos", math_acos_bridge);
reg!("math:acosh", math_acosh_bridge);
reg!("math:asin", math_asin_bridge);
reg!("math:asinh", math_asinh_bridge);
reg!("math:atan", math_atan_bridge);
reg!("math:atanh", math_atanh_bridge);
reg!("math:cbrt", math_cbrt_bridge);
reg!("math:ceil", math_ceil_bridge);
reg!("math:clz32", math_clz32_bridge);
reg!("math:cos", math_cos_bridge);
reg!("math:cosh", math_cosh_bridge);
reg!("math:exp", math_exp_bridge);
reg!("math:expm1", math_expm1_bridge);
reg!("math:floor", math_floor_bridge);
reg!("math:fround", math_fround_bridge);
reg!("math:log", math_log_bridge);
reg!("math:log10", math_log10_bridge);
reg!("math:log1p", math_log1p_bridge);
reg!("math:log2", math_log2_bridge);
reg!("math:round", math_round_bridge);
reg!("math:sign", math_sign_bridge);
reg!("math:sin", math_sin_bridge);
reg!("math:sinh", math_sinh_bridge);
reg!("math:tan", math_tan_bridge);
reg!("math:tanh", math_tanh_bridge);
reg!("math:trunc", math_trunc_bridge);
reg!("math:sqrt", math_sqrt_bridge);
reg!("math:arb", math_arb_bridge);
reg!("math:rotate_point", math_rotate_point_bridge);
reg!("math:srand", math_srand_bridge);
}
#[cfg(feature = "host")]
#[no_mangle]
pub unsafe extern "C" fn Cargo_lock(
interp_ptr: *mut c_void,
extra_str: *const c_void,
) -> i32 {
let interp = &mut *(interp_ptr as *mut Interpreter);
let verbose = interp.is_verbose();
if verbose && !extra_str.is_null() {
let c_str = CStr::from_ptr(extra_str as *const i8);
eprintln!(
"(math) cargo_lock => bridging => extra arg='{}'",
c_str.to_string_lossy()
);
}
if verbose {
eprintln!("(math) => registering math plugin bridges …");
}
register_all(interp);
if verbose {
eprintln!("(math) cargo_lock => done registering all bridging functions.");
}
0
}