1use mumu::{
4 parser::interpreter::{DynamicFnInfo, Interpreter},
5 parser::types::{FunctionValue, Value},
6};
7use std::sync::{Arc, Mutex};
8
9#[cfg(not(target_arch = "wasm32"))]
10use std::ffi::{c_void, CStr};
11
12mod arb;
13mod sqrt;
14mod unary;
15mod partials;
16mod rotate_point;
17mod srand;
18
19use arb::math_arb_bridge;
20use sqrt::math_sqrt_bridge;
21use unary::*;
22use partials::*;
23use rotate_point::math_rotate_point_bridge;
24use srand::math_srand_bridge;
25
26const VALUE_TO_STRING_RECURSION_LIMIT: usize = 32;
28
29pub fn value_to_string(val: &Value) -> String {
32 value_to_string_with_depth(val, 0)
33}
34
35fn value_to_string_with_depth(val: &Value, depth: usize) -> String {
36 if depth > VALUE_TO_STRING_RECURSION_LIMIT {
37 return "<recursion>".to_string();
38 }
39 match val {
40 Value::Int(x) => x.to_string(),
41 Value::IntArray(xs) => format!("{:?}", xs),
42 Value::Int2DArray(rows) => format!("{:?}", rows),
43 Value::Float(f) => f.to_string(),
44 Value::FloatArray(ff) => format!("{:?}", ff),
45 Value::Float2DArray(rows) => format!("{:?}", rows),
46 Value::StrArray(ss) => format!("{:?}", ss),
47 Value::KeyedArray(map) => {
48 let mut s = String::from("{ ");
49 let mut first = true;
50 for (k, v) in map.iter() {
51 if !first {
52 s.push_str(", ");
53 }
54 first = false;
55 s.push_str(k);
56 s.push_str(": ");
57 s.push_str(&value_to_string_with_depth(v, depth + 1));
58 }
59 s.push_str(" }");
60 s
61 }
62 Value::KeyedError(map) => {
64 let msg = map.get("message").and_then(|v| {
65 if let Value::SingleString(s) = v { Some(s.as_str()) } else { None }
66 }).unwrap_or("");
67 let line = map.get("line").and_then(|v| {
68 if let Value::Int(i) = v { Some(*i) } else { None }
69 }).unwrap_or(0);
70 let col = map.get("col").and_then(|v| {
71 if let Value::Int(i) = v { Some(*i) } else { None }
72 }).unwrap_or(0);
73
74 if !msg.is_empty() {
75 if line > 0 || col > 0 {
76 format!("Error{{ line:{}, col:{}, message:\"{}\" }}", line, col, msg)
77 } else {
78 format!("Error{{ message:\"{}\" }}", msg)
79 }
80 } else {
81 format!("Error{{ …{} keys… }}", map.len())
82 }
83 }
84 Value::Function(_) => "[Function]".to_string(),
85 Value::Bool(b) => b.to_string(),
86 Value::BoolArray(bb) => format!("{:?}", bb),
87 Value::Placeholder => "_".to_string(),
88 Value::SingleString(s) => format!("\"{}\"", s), Value::Long(l) => l.to_string(),
90 Value::Stream(sh) => format!("<Stream id={}, label={}>", sh.stream_id, sh.label),
91 Value::Iterator(_) => "[Iterator]".to_string(),
92 Value::Tensor(_) => "[Tensor]".to_string(),
93 Value::MixedArray(items) => {
94 let inner = items
95 .iter()
96 .map(|v| value_to_string_with_depth(v, depth + 1))
97 .collect::<Vec<_>>()
98 .join(", ");
99 format!("[{}]", inner)
100 }
101 Value::Ref(arc_mutex) => {
102 value_to_string_with_depth(&arc_mutex.lock().unwrap(), depth + 1)
104 }
105 Value::Undefined => "undefined".to_string(),
106 Value::Regex(rx) => format!("Regex(/{}{}/)", rx.pattern, rx.flags),
107 }
108}
109
110pub fn register_all(interp: &mut Interpreter) {
113 macro_rules! reg {
114 ($name:expr, $f:expr) => {{
115 let func = Arc::new(Mutex::new($f));
116 interp.register_dynamic_function_ex($name, DynamicFnInfo::new(func.clone(), false));
117 interp.set_variable($name, Value::Function(Box::new(FunctionValue::Named($name.into()))));
118 }};
119 }
120
121 reg!("math:plus", math_plus_bridge);
123 reg!("math:subtract", math_subtract_bridge);
124 reg!("math:multiply", math_multiply_bridge);
125 reg!("math:divide", math_divide_bridge);
126 reg!("math:pow", math_pow_bridge);
127 reg!("math:mod", math_mod_bridge);
128
129 reg!("math:atan2", math_atan2_bridge);
131 reg!("math:imul", math_imul_bridge);
132 reg!("math:max", math_max_bridge);
133 reg!("math:min", math_min_bridge);
134 reg!("math:hypot", math_hypot_bridge);
135
136 reg!("math:abs", math_abs_bridge);
138 reg!("math:acos", math_acos_bridge);
139 reg!("math:acosh", math_acosh_bridge);
140 reg!("math:asin", math_asin_bridge);
141 reg!("math:asinh", math_asinh_bridge);
142 reg!("math:atan", math_atan_bridge);
143 reg!("math:atanh", math_atanh_bridge);
144 reg!("math:cbrt", math_cbrt_bridge);
145 reg!("math:ceil", math_ceil_bridge);
146 reg!("math:clz32", math_clz32_bridge);
147 reg!("math:cos", math_cos_bridge);
148 reg!("math:cosh", math_cosh_bridge);
149 reg!("math:exp", math_exp_bridge);
150 reg!("math:expm1", math_expm1_bridge);
151 reg!("math:floor", math_floor_bridge);
152 reg!("math:fround", math_fround_bridge);
153 reg!("math:log", math_log_bridge);
154 reg!("math:log10", math_log10_bridge);
155 reg!("math:log1p", math_log1p_bridge);
156 reg!("math:log2", math_log2_bridge);
157 reg!("math:round", math_round_bridge);
158 reg!("math:sign", math_sign_bridge);
159 reg!("math:sin", math_sin_bridge);
160 reg!("math:sinh", math_sinh_bridge);
161 reg!("math:tan", math_tan_bridge);
162 reg!("math:tanh", math_tanh_bridge);
163 reg!("math:trunc", math_trunc_bridge);
164
165 reg!("math:sqrt", math_sqrt_bridge);
167 reg!("math:arb", math_arb_bridge);
168
169 reg!("math:rotate_point", math_rotate_point_bridge);
171
172 reg!("math:srand", math_srand_bridge);
174}
175
176#[cfg(not(target_arch = "wasm32"))]
179#[no_mangle]
180pub unsafe extern "C" fn Cargo_lock(
181 interp_ptr: *mut c_void,
182 extra_str: *const c_void,
183) -> i32 {
184 let interp = &mut *(interp_ptr as *mut Interpreter);
185
186 let verbose = interp.is_verbose();
187 if verbose && !extra_str.is_null() {
188 let c_str = CStr::from_ptr(extra_str as *const i8);
189 eprintln!(
190 "(math) cargo_lock => bridging => extra arg='{}'",
191 c_str.to_string_lossy()
192 );
193 }
194 if verbose {
195 eprintln!("(math) => registering math plugin bridges …");
196 }
197
198 register_all(interp);
200
201 if verbose {
202 eprintln!("(math) cargo_lock => done registering all bridging functions.");
203 }
204
205 0
206}