Refactor math functions to a separate module
Move the `register_math` function and its associated logic into a new `math` module. This improves organization and separation of concerns within the RTL AST.
This commit is contained in:
@@ -471,78 +471,4 @@ fn register_logic(env: &Environment) {
|
|||||||
_ => Value::Void,
|
_ => Value::Void,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
register_math(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_math(env: &Environment) {
|
|
||||||
let math_unary_ty = StaticType::Function(Box::new(Signature {
|
|
||||||
params: StaticType::Tuple(vec![StaticType::Any]),
|
|
||||||
ret: StaticType::Any,
|
|
||||||
}));
|
|
||||||
|
|
||||||
env.register_native("abs", math_unary_ty, Purity::Pure, |args| {
|
|
||||||
if args.len() != 1 {
|
|
||||||
return Value::Void;
|
|
||||||
}
|
|
||||||
match args[0] {
|
|
||||||
Value::Int(i) => Value::Int(i.abs()),
|
|
||||||
Value::Float(f) => Value::Float(f.abs()),
|
|
||||||
_ => Value::Void,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let math_variadic_ty = StaticType::Function(Box::new(Signature {
|
|
||||||
params: StaticType::Any,
|
|
||||||
ret: StaticType::Any,
|
|
||||||
}));
|
|
||||||
|
|
||||||
env.register_native("min", math_variadic_ty.clone(), Purity::Pure, |args| {
|
|
||||||
if args.is_empty() {
|
|
||||||
return Value::Void;
|
|
||||||
}
|
|
||||||
let mut best = args[0].clone();
|
|
||||||
for arg in &args[1..] {
|
|
||||||
if *arg < best {
|
|
||||||
best = arg.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
best
|
|
||||||
});
|
|
||||||
|
|
||||||
env.register_native("max", math_variadic_ty, Purity::Pure, |args| {
|
|
||||||
if args.is_empty() {
|
|
||||||
return Value::Void;
|
|
||||||
}
|
|
||||||
let mut best = args[0].clone();
|
|
||||||
for arg in &args[1..] {
|
|
||||||
if *arg > best {
|
|
||||||
best = arg.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
best
|
|
||||||
});
|
|
||||||
|
|
||||||
let random_ty = StaticType::Function(Box::new(Signature {
|
|
||||||
params: StaticType::Tuple(vec![]),
|
|
||||||
ret: StaticType::Float,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let prng = env.prng.clone();
|
|
||||||
env.register_native("random", random_ty, Purity::SideEffectFree, move |_| {
|
|
||||||
Value::Float(prng.borrow_mut().f64())
|
|
||||||
});
|
|
||||||
|
|
||||||
let seed_ty = StaticType::Function(Box::new(Signature {
|
|
||||||
params: StaticType::Tuple(vec![StaticType::Int]),
|
|
||||||
ret: StaticType::Void,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let prng_seed = env.prng.clone();
|
|
||||||
env.register_native("seed!", seed_ty, Purity::Impure, move |args| {
|
|
||||||
if let Value::Int(s) = args[0] {
|
|
||||||
prng_seed.borrow_mut().seed(s as u64);
|
|
||||||
}
|
|
||||||
Value::Void
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,162 @@
|
|||||||
|
use crate::ast::compiler::optimizer::Purity;
|
||||||
|
use crate::ast::environment::Environment;
|
||||||
|
use crate::ast::types::{Signature, StaticType, Value};
|
||||||
|
use std::f64::consts;
|
||||||
|
|
||||||
|
pub fn register(env: &Environment) {
|
||||||
|
// Constants
|
||||||
|
env.register_constant("PI", StaticType::Float, Value::Float(consts::PI));
|
||||||
|
env.register_constant("E", StaticType::Float, Value::Float(consts::E));
|
||||||
|
|
||||||
|
// Helper to get f64 from Value (Int or Float)
|
||||||
|
fn to_f64(v: &Value) -> Option<f64> {
|
||||||
|
match v {
|
||||||
|
Value::Float(f) => Some(*f),
|
||||||
|
Value::Int(i) => Some(*i as f64),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unary functions (float -> float)
|
||||||
|
let register_unary = |name: &'static str, f: fn(f64) -> f64| {
|
||||||
|
let ty = StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![StaticType::Float]),
|
||||||
|
ret: StaticType::Float,
|
||||||
|
}));
|
||||||
|
env.register_native(name, ty, Purity::Pure, move |args| {
|
||||||
|
if let Some(x) = to_f64(&args[0]) {
|
||||||
|
Value::Float(f(x))
|
||||||
|
} else {
|
||||||
|
Value::Void
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unary functions (float -> int)
|
||||||
|
let register_to_int = |name: &'static str, f: fn(f64) -> f64| {
|
||||||
|
let ty = StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![StaticType::Float]),
|
||||||
|
ret: StaticType::Int,
|
||||||
|
}));
|
||||||
|
env.register_native(name, ty, Purity::Pure, move |args| {
|
||||||
|
if let Some(x) = to_f64(&args[0]) {
|
||||||
|
Value::Int(f(x) as i64)
|
||||||
|
} else {
|
||||||
|
Value::Void
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
register_unary("sqrt", f64::sqrt);
|
||||||
|
register_unary("sin", f64::sin);
|
||||||
|
register_unary("cos", f64::cos);
|
||||||
|
register_unary("tan", f64::tan);
|
||||||
|
register_unary("asin", f64::asin);
|
||||||
|
register_unary("acos", f64::acos);
|
||||||
|
register_unary("atan", f64::atan);
|
||||||
|
register_unary("exp", f64::exp);
|
||||||
|
register_unary("ln", f64::ln);
|
||||||
|
register_unary("log10", f64::log10);
|
||||||
|
register_unary("fract", f64::fract);
|
||||||
|
|
||||||
|
// Rounding functions returning Int
|
||||||
|
register_to_int("round", f64::round);
|
||||||
|
register_to_int("floor", f64::floor);
|
||||||
|
register_to_int("ceil", f64::ceil);
|
||||||
|
register_to_int("trunc", f64::trunc);
|
||||||
|
|
||||||
|
// Binary functions (float, float -> float)
|
||||||
|
let register_binary = |name: &'static str, f: fn(f64, f64) -> f64| {
|
||||||
|
let ty = StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![StaticType::Float, StaticType::Float]),
|
||||||
|
ret: StaticType::Float,
|
||||||
|
}));
|
||||||
|
env.register_native(name, ty, Purity::Pure, move |args| {
|
||||||
|
if let (Some(a), Some(b)) = (to_f64(&args[0]), to_f64(&args[1])) {
|
||||||
|
Value::Float(f(a, b))
|
||||||
|
} else {
|
||||||
|
Value::Void
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
register_binary("atan2", f64::atan2);
|
||||||
|
register_binary("pow", f64::powf);
|
||||||
|
register_binary("log", f64::log);
|
||||||
|
|
||||||
|
// Specialized abs to handle Int -> Int, Float -> Float
|
||||||
|
let abs_ty = StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![StaticType::Any]),
|
||||||
|
ret: StaticType::Any,
|
||||||
|
}));
|
||||||
|
env.register_native("abs", abs_ty, Purity::Pure, |args| {
|
||||||
|
if args.len() != 1 {
|
||||||
|
return Value::Void;
|
||||||
|
}
|
||||||
|
match args[0] {
|
||||||
|
Value::Int(i) => Value::Int(i.abs()),
|
||||||
|
Value::Float(f) => Value::Float(f.abs()),
|
||||||
|
_ => Value::Void,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Variadic min / max
|
||||||
|
let variadic_ty = StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Any,
|
||||||
|
ret: StaticType::Any,
|
||||||
|
}));
|
||||||
|
|
||||||
|
env.register_native("min", variadic_ty.clone(), Purity::Pure, |args| {
|
||||||
|
if args.is_empty() {
|
||||||
|
return Value::Void;
|
||||||
|
}
|
||||||
|
let mut best = args[0].clone();
|
||||||
|
for arg in &args[1..] {
|
||||||
|
if let Some(ord) = arg.partial_cmp(&best)
|
||||||
|
&& ord == std::cmp::Ordering::Less
|
||||||
|
{
|
||||||
|
best = arg.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best
|
||||||
|
});
|
||||||
|
|
||||||
|
env.register_native("max", variadic_ty, Purity::Pure, |args| {
|
||||||
|
if args.is_empty() {
|
||||||
|
return Value::Void;
|
||||||
|
}
|
||||||
|
let mut best = args[0].clone();
|
||||||
|
for arg in &args[1..] {
|
||||||
|
if let Some(ord) = arg.partial_cmp(&best)
|
||||||
|
&& ord == std::cmp::Ordering::Greater
|
||||||
|
{
|
||||||
|
best = arg.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best
|
||||||
|
});
|
||||||
|
|
||||||
|
// Random
|
||||||
|
let random_ty = StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![]),
|
||||||
|
ret: StaticType::Float,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let prng = env.prng.clone();
|
||||||
|
env.register_native("random", random_ty, Purity::SideEffectFree, move |_| {
|
||||||
|
Value::Float(prng.borrow_mut().f64())
|
||||||
|
});
|
||||||
|
|
||||||
|
let seed_ty = StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![StaticType::Int]),
|
||||||
|
ret: StaticType::Void,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let prng_seed = env.prng.clone();
|
||||||
|
env.register_native("seed!", seed_ty, Purity::Impure, move |args| {
|
||||||
|
if let Value::Int(s) = args[0] {
|
||||||
|
prng_seed.borrow_mut().seed(s as u64);
|
||||||
|
}
|
||||||
|
Value::Void
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
pub mod core;
|
pub mod core;
|
||||||
pub mod datetime;
|
pub mod datetime;
|
||||||
pub mod intrinsics;
|
pub mod intrinsics;
|
||||||
|
pub mod math;
|
||||||
pub mod type_registry;
|
pub mod type_registry;
|
||||||
|
|
||||||
use crate::ast::environment::Environment;
|
use crate::ast::environment::Environment;
|
||||||
@@ -8,4 +9,5 @@ use crate::ast::environment::Environment;
|
|||||||
pub fn register(env: &Environment) {
|
pub fn register(env: &Environment) {
|
||||||
core::register(env);
|
core::register(env);
|
||||||
datetime::register(env);
|
datetime::register(env);
|
||||||
|
math::register(env);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user