use crate::executor::Environment;
use crate::value::Value;
pub fn register(env: &mut Environment) {
env.register_builtin("math.add", |args, _| {
let sum: f64 = args.iter().map(|v| v.to_number()).sum();
Ok(Value::Number(sum))
});
env.register_builtin("math.subtract", |args, _| {
if args.is_empty() {
return Ok(Value::Number(0.0));
}
let mut result = args[0].to_number();
for arg in &args[1..] {
result -= arg.to_number();
}
Ok(Value::Number(result))
});
env.register_builtin("math.multiply", |args, _| {
let product: f64 = args.iter().map(|v| v.to_number()).product();
Ok(Value::Number(product))
});
env.register_builtin("math.divide", |args, _| {
if args.len() < 2 {
return Ok(Value::Number(f64::NAN));
}
let a = args[0].to_number();
let b = args[1].to_number();
if b == 0.0 {
Ok(Value::Number(f64::INFINITY))
} else {
Ok(Value::Number(a / b))
}
});
env.register_builtin("math.modulo", |args, _| {
if args.len() < 2 {
return Ok(Value::Number(f64::NAN));
}
Ok(Value::Number(args[0].to_number() % args[1].to_number()))
});
env.register_builtin("math.abs", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().abs()),
))
});
env.register_builtin("math.round", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().round()),
))
});
env.register_builtin("math.floor", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().floor()),
))
});
env.register_builtin("math.ceil", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().ceil()),
))
});
env.register_builtin("math.min", |args, _| {
let mut min = f64::INFINITY;
for arg in args {
let n = arg.to_number();
if n < min {
min = n;
}
}
Ok(Value::Number(min))
});
env.register_builtin("math.max", |args, _| {
let mut max = f64::NEG_INFINITY;
for arg in args {
let n = arg.to_number();
if n > max {
max = n;
}
}
Ok(Value::Number(max))
});
env.register_builtin("math.pow", |args, _| {
if args.len() < 2 {
return Ok(Value::Number(f64::NAN));
}
Ok(Value::Number(
args[0].to_number().powf(args[1].to_number()),
))
});
env.register_builtin("math.sqrt", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().sqrt()),
))
});
env.register_builtin("math.sin", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().sin()),
))
});
env.register_builtin("math.cos", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().cos()),
))
});
env.register_builtin("math.tan", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().tan()),
))
});
env.register_builtin("math.pi", |_args, _| {
Ok(Value::Number(std::f64::consts::PI))
});
env.register_builtin("math.e", |_args, _| {
Ok(Value::Number(std::f64::consts::E))
});
env.register_builtin("math.power", |args, _| {
if args.len() < 2 {
return Ok(Value::Number(f64::NAN));
}
Ok(Value::Number(
args[0].to_number().powf(args[1].to_number()),
))
});
env.register_builtin("math.log", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().ln()),
))
});
env.register_builtin("math.log10", |args, _| {
Ok(Value::Number(
args.first().map_or(0.0, |v| v.to_number().log10()),
))
});
env.register_builtin("add", |args, _| {
let sum: f64 = args.iter().map(|v| v.to_number()).sum();
Ok(Value::Number(sum))
});
env.register_builtin("subtract", |args, _| {
if args.is_empty() {
return Ok(Value::Number(0.0));
}
let mut result = args[0].to_number();
for arg in &args[1..] {
result -= arg.to_number();
}
Ok(Value::Number(result))
});
env.register_builtin("multiply", |args, _| {
let product: f64 = args.iter().map(|v| v.to_number()).product();
Ok(Value::Number(product))
});
env.register_builtin("divide", |args, _| {
if args.len() < 2 {
return Ok(Value::Number(f64::NAN));
}
let a = args[0].to_number();
let b = args[1].to_number();
if b == 0.0 {
Ok(Value::Number(f64::INFINITY))
} else {
Ok(Value::Number(a / b))
}
});
}