61 lines
1.8 KiB
Rust
61 lines
1.8 KiB
Rust
use orchid_base::error::mk_errv;
|
|
use orchid_base::interner::is;
|
|
use orchid_base::number::Numeric;
|
|
use orchid_extension::func_atom::get_arg;
|
|
use orchid_extension::tree::{GenMember, fun, prefix};
|
|
use ordered_float::NotNan;
|
|
use rust_decimal::prelude::ToPrimitive;
|
|
|
|
use super::num_atom::{Float, HomoArray, Int, Num};
|
|
|
|
pub fn gen_num_lib() -> Vec<GenMember> {
|
|
prefix("std::number", [
|
|
fun(false, "add", async |a: Num, b: Num| {
|
|
Num(match HomoArray::new([a.0, b.0]) {
|
|
HomoArray::Int([a, b]) => Numeric::Int(a + b),
|
|
HomoArray::Float([a, b]) => Numeric::Float(a + b),
|
|
})
|
|
}),
|
|
fun(false, "sub", async |a: Num, b: Num| {
|
|
Num(match HomoArray::new([a.0, b.0]) {
|
|
HomoArray::Int([a, b]) => Numeric::Int(a - b),
|
|
HomoArray::Float([a, b]) => Numeric::Float(a - b),
|
|
})
|
|
}),
|
|
fun(false, "neg", async |a: Num| {
|
|
Num(match a.0 {
|
|
Numeric::Int(i) => Numeric::Int(-i),
|
|
Numeric::Float(f) => Numeric::Float(-f),
|
|
})
|
|
}),
|
|
fun(false, "mul", async |a: Num, b: Num| {
|
|
Num(match HomoArray::new([a.0, b.0]) {
|
|
HomoArray::Int([a, b]) => Numeric::Int(a * b),
|
|
HomoArray::Float([a, b]) => Numeric::Float(a * b),
|
|
})
|
|
}),
|
|
fun(false, "idiv", async |a: Int, b: Int| Int(a.0 / b.0)),
|
|
fun(false, "imod", async |a: Int, b: Int| Int(a.0 % b.0)),
|
|
fun(false, "fdiv", async |a: Float, b: Float| Float(a.0 / b.0)),
|
|
fun(false, "fmod", async |a: Float, b: Float| {
|
|
Float(a.0 - NotNan::new((a.0 / b.0).trunc()).unwrap() * b.0)
|
|
}),
|
|
fun(false, "to_i", async |a: Num| {
|
|
Ok(Int(match a.0 {
|
|
Numeric::Int(i) => i,
|
|
Numeric::Float(f) => match f.to_i64() {
|
|
Some(i) => i,
|
|
None => {
|
|
return Err(mk_errv(
|
|
is("Float out of range").await,
|
|
format!("{f} is not representable as an integer"),
|
|
[get_arg(0).pos().await],
|
|
));
|
|
},
|
|
},
|
|
}))
|
|
}),
|
|
fun(false, "to_f", async |a: Num| Float(a.0.to_f64())),
|
|
])
|
|
}
|