use mumu::parser::interpreter::Interpreter;
use mumu::parser::types::Value;
fn coerce_single_to_f64(arg: Value, func_name: &str) -> Result<f64, String> {
match arg {
Value::Int(i) => Ok(i as f64),
Value::Long(l) => Ok(l as f64),
Value::Float(ff) => Ok(ff),
other => Err(format!("{} => argument must be numeric, got {:?}", func_name, other)),
}
}
pub fn math_abs_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:abs => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:abs")?;
Ok(Value::Float(x.abs()))
}
pub fn math_acos_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:acos => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:acos")?;
Ok(Value::Float(x.acos()))
}
pub fn math_acosh_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:acosh => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:acosh")?;
Ok(Value::Float(x.acosh()))
}
pub fn math_asin_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:asin => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:asin")?;
Ok(Value::Float(x.asin()))
}
pub fn math_asinh_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:asinh => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:asinh")?;
Ok(Value::Float(x.asinh()))
}
pub fn math_atan_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:atan => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:atan")?;
Ok(Value::Float(x.atan()))
}
pub fn math_atanh_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:atanh => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:atanh")?;
Ok(Value::Float(x.atanh()))
}
pub fn math_cbrt_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:cbrt => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:cbrt")?;
Ok(Value::Float(x.cbrt()))
}
pub fn math_ceil_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:ceil => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:ceil")?;
let c = x.ceil();
if c.is_finite() && c == c.trunc() && c >= (i32::MIN as f64) && c <= (i32::MAX as f64) {
Ok(Value::Int(c as i32))
} else {
Ok(Value::Float(c))
}
}
pub fn math_clz32_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:clz32 => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:clz32")?;
let as_u32 = x as u32;
let result = as_u32.leading_zeros() as i32;
Ok(Value::Int(result))
}
pub fn math_cos_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:cos => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:cos")?;
Ok(Value::Float(x.cos()))
}
pub fn math_cosh_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:cosh => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:cosh")?;
Ok(Value::Float(x.cosh()))
}
pub fn math_exp_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:exp => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:exp")?;
Ok(Value::Float(x.exp()))
}
pub fn math_expm1_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:expm1 => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:expm1")?;
Ok(Value::Float(x.exp_m1()))
}
pub fn math_floor_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:floor => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:floor")?;
let c = x.floor();
if c.is_finite() && c == c.trunc() && c >= (i32::MIN as f64) && c <= (i32::MAX as f64) {
Ok(Value::Int(c as i32))
} else {
Ok(Value::Float(c))
}
}
pub fn math_fround_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:fround => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:fround")?;
let as_f32 = x as f32;
Ok(Value::Float(as_f32 as f64))
}
pub fn math_log_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:log => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:log")?;
Ok(Value::Float(x.ln()))
}
pub fn math_log10_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:log10 => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:log10")?;
Ok(Value::Float(x.log10()))
}
pub fn math_log1p_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:log1p => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:log1p")?;
Ok(Value::Float(x.ln_1p()))
}
pub fn math_log2_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:log2 => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:log2")?;
Ok(Value::Float(x.log2()))
}
pub fn math_round_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:round => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:round")?;
let r = x.round();
if r.is_finite() && r == r.trunc() && r >= (i32::MIN as f64) && r <= (i32::MAX as f64) {
Ok(Value::Int(r as i32))
} else {
Ok(Value::Float(r))
}
}
pub fn math_sign_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:sign => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:sign")?;
let s = if x > 0.0 {
1
} else if x < 0.0 {
-1
} else {
0
};
Ok(Value::Int(s))
}
pub fn math_sin_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:sin => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:sin")?;
Ok(Value::Float(x.sin()))
}
pub fn math_sinh_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:sinh => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:sinh")?;
Ok(Value::Float(x.sinh()))
}
pub fn math_tan_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:tan => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:tan")?;
Ok(Value::Float(x.tan()))
}
pub fn math_tanh_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:tanh => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:tanh")?;
Ok(Value::Float(x.tanh()))
}
pub fn math_trunc_bridge(_i: &mut Interpreter, args: Vec<Value>) -> Result<Value, String> {
if args.len() != 1 {
return Err(format!("math:trunc => expected 1 argument, got {}", args.len()));
}
let x = coerce_single_to_f64(args[0].clone(), "math:trunc")?;
let t = x.trunc();
if t.is_finite() && t == t.trunc() && t >= (i32::MIN as f64) && t <= (i32::MAX as f64) {
Ok(Value::Int(t as i32))
} else {
Ok(Value::Float(t))
}
}