for a moment, everything works
This commit is contained in:
@@ -16,4 +16,5 @@ orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
|
||||
orchid-base = { version = "0.1.0", path = "../orchid-base" }
|
||||
orchid-extension = { version = "0.1.0", path = "../orchid-extension" }
|
||||
ordered-float = "4.6.0"
|
||||
rust_decimal = "1.36.0"
|
||||
tokio = { version = "1.43.0", features = ["full"] }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use orchid_api_derive::Coding;
|
||||
use orchid_base::error::OrcRes;
|
||||
use orchid_base::format::FmtUnit;
|
||||
use orchid_base::number::Numeric;
|
||||
use orchid_extension::atom::{
|
||||
AtomFactory, Atomic, AtomicFeatures, MethodSetBuilder, ToAtom, TypAtom,
|
||||
};
|
||||
@@ -9,6 +10,7 @@ use orchid_extension::conv::TryFromExpr;
|
||||
use orchid_extension::expr::Expr;
|
||||
use orchid_extension::system::SysCtx;
|
||||
use ordered_float::NotNan;
|
||||
use rust_decimal::prelude::Zero;
|
||||
|
||||
#[derive(Clone, Debug, Coding)]
|
||||
pub struct Int(pub i64);
|
||||
@@ -38,27 +40,56 @@ impl ThinAtom for Float {
|
||||
}
|
||||
impl TryFromExpr for Float {
|
||||
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
||||
TypAtom::<Float>::try_from_expr(expr).await.map(|t| t.value)
|
||||
Ok(Self(Num::try_from_expr(expr).await?.0.to_f64()))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Numeric {
|
||||
Int(i64),
|
||||
Float(NotNan<f64>),
|
||||
}
|
||||
impl TryFromExpr for Numeric {
|
||||
pub struct Num(pub Numeric);
|
||||
impl TryFromExpr for Num {
|
||||
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
|
||||
match Int::try_from_expr(expr.clone()).await {
|
||||
Ok(t) => Ok(Numeric::Int(t.0)),
|
||||
Err(e) => Float::try_from_expr(expr).await.map(|t| Numeric::Float(t.0)).map_err(|e2| e + e2),
|
||||
let e = match Int::try_from_expr(expr.clone()).await {
|
||||
Ok(t) => return Ok(Num(Numeric::Int(t.0))),
|
||||
Err(e) => e,
|
||||
};
|
||||
match TypAtom::<Float>::try_from_expr(expr).await {
|
||||
Ok(t) => Ok(Num(Numeric::Float(t.0))),
|
||||
Err(e2) => Err(e + e2),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ToAtom for Numeric {
|
||||
impl ToAtom for Num {
|
||||
fn to_atom_factory(self) -> AtomFactory {
|
||||
match self {
|
||||
Self::Float(f) => Float(f).factory(),
|
||||
Self::Int(i) => Int(i).factory(),
|
||||
match self.0 {
|
||||
Numeric::Float(f) => Float(f).factory(),
|
||||
Numeric::Int(i) => Int(i).factory(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A homogenous fixed length number array that forces all of its elements into
|
||||
/// the weakest element type. This describes the argument casting behaviour of
|
||||
/// most numeric operations.
|
||||
pub enum HomoArray<const N: usize> {
|
||||
Int([i64; N]),
|
||||
Float([NotNan<f64>; N]),
|
||||
}
|
||||
impl<const N: usize> HomoArray<N> {
|
||||
pub fn new(n: [Numeric; N]) -> Self {
|
||||
let mut ints = [0i64; N];
|
||||
for i in 0..N {
|
||||
if let Numeric::Int(val) = n[i] {
|
||||
ints[i] = val
|
||||
} else {
|
||||
let mut floats = [NotNan::zero(); N];
|
||||
for (i, int) in ints.iter().take(i).enumerate() {
|
||||
floats[i] = NotNan::new(*int as f64).expect("i64 cannot convert to f64 NaN");
|
||||
}
|
||||
for j in i..N {
|
||||
floats[j] = n[j].to_f64();
|
||||
}
|
||||
return Self::Float(floats);
|
||||
}
|
||||
}
|
||||
Self::Int(ints)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use orchid_base::error::OrcRes;
|
||||
use orchid_base::number::{Numeric, num_to_err, parse_num};
|
||||
use orchid_extension::atom::AtomicFeatures;
|
||||
use orchid_base::number::{num_to_err, parse_num};
|
||||
use orchid_extension::atom::ToAtom;
|
||||
use orchid_extension::lexer::{LexContext, Lexer};
|
||||
use orchid_extension::tree::{GenTok, GenTokTree};
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use super::num_atom::{Float, Int};
|
||||
use super::num_atom::Num;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NumLexer;
|
||||
@@ -17,9 +16,7 @@ impl Lexer for NumLexer {
|
||||
let ends_at = all.find(|c: char| !c.is_ascii_hexdigit() && !"xX._pP".contains(c));
|
||||
let (chars, tail) = all.split_at(ends_at.unwrap_or(all.len()));
|
||||
let fac = match parse_num(chars) {
|
||||
Ok(Numeric::Float(f)) => Float(f).factory(),
|
||||
Ok(Numeric::Uint(uint)) => Int(uint.try_into().unwrap()).factory(),
|
||||
Ok(Numeric::Decimal(dec)) => Float(NotNan::new(dec.try_into().unwrap()).unwrap()).factory(),
|
||||
Ok(numeric) => Num(numeric).to_atom_factory(),
|
||||
Err(e) => return Err(num_to_err(e, ctx.pos(all), ctx.i).await.into()),
|
||||
};
|
||||
Ok((tail, GenTok::X(fac).at(ctx.pos(all)..ctx.pos(tail))))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use never::Never;
|
||||
use orchid_base::number::Numeric;
|
||||
use orchid_base::reqnot::Receipt;
|
||||
use orchid_extension::atom::{AtomDynfo, AtomicFeatures};
|
||||
use orchid_extension::entrypoint::ExtReq;
|
||||
@@ -8,9 +9,10 @@ use orchid_extension::fs::DeclFs;
|
||||
use orchid_extension::system::{System, SystemCard};
|
||||
use orchid_extension::system_ctor::SystemCtor;
|
||||
use orchid_extension::tree::{MemKind, comments, fun, module, root_mod};
|
||||
use ordered_float::NotNan;
|
||||
|
||||
use crate::OrcString;
|
||||
use crate::number::num_atom::{Float, Int};
|
||||
use crate::number::num_atom::{Float, HomoArray, Int, Num};
|
||||
use crate::number::num_lexer::NumLexer;
|
||||
use crate::string::str_atom::{IntStrAtom, StrAtom};
|
||||
use crate::string::str_lexer::StringLexer;
|
||||
@@ -37,11 +39,39 @@ impl System for StdSystem {
|
||||
fn parsers() -> Vec<orchid_extension::parser::ParserObj> { vec![] }
|
||||
fn vfs() -> DeclFs { DeclFs::Mod(&[]) }
|
||||
fn env() -> Vec<(String, MemKind)> {
|
||||
vec![root_mod("std", [], [module(true, "string", [], [comments(
|
||||
["Concatenate two strings"],
|
||||
fun(true, "concat", |left: OrcString<'static>, right: OrcString<'static>| async move {
|
||||
StrAtom::new(Rc::new(left.get_string().await.to_string() + &right.get_string().await))
|
||||
}),
|
||||
)])])]
|
||||
vec![root_mod("std", [], [
|
||||
module(true, "string", [], [comments(
|
||||
["Concatenate two strings"],
|
||||
fun(true, "concat", |left: OrcString<'static>, right: OrcString<'static>| async move {
|
||||
StrAtom::new(Rc::new(left.get_string().await.to_string() + &right.get_string().await))
|
||||
}),
|
||||
)]),
|
||||
module(true, "number", [], [
|
||||
fun(true, "add", |a: Num, b: Num| async move {
|
||||
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(true, "neg", |a: Num| async move {
|
||||
Num(match a.0 {
|
||||
Numeric::Int(i) => Numeric::Int(-i),
|
||||
Numeric::Float(f) => Numeric::Float(-f),
|
||||
})
|
||||
}),
|
||||
fun(true, "mul", |a: Num, b: Num| async move {
|
||||
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(true, "idiv", |a: Int, b: Int| async move { Int(a.0 / b.0) }),
|
||||
fun(true, "imod", |a: Int, b: Int| async move { Int(a.0 % b.0) }),
|
||||
fun(true, "fdiv", |a: Float, b: Float| async move { Float(a.0 / b.0) }),
|
||||
fun(true, "fmod", |a: Float, b: Float| async move {
|
||||
Float(a.0 - NotNan::new((a.0 / b.0).trunc()).unwrap() * b.0)
|
||||
}),
|
||||
]),
|
||||
])]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ impl OwnedAtom for IntStrAtom {
|
||||
}
|
||||
async fn deserialize(mut ctx: impl DeserializeCtx, _: ()) -> Self {
|
||||
let s = ctx.decode::<String>().await;
|
||||
Self(ctx.sys().i.i(&s).await)
|
||||
Self(ctx.sys().i().i(&s).await)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ pub enum OrcStringKind<'a> {
|
||||
impl OrcString<'_> {
|
||||
pub async fn get_string(&self) -> Rc<String> {
|
||||
match &self.kind {
|
||||
OrcStringKind::Int(tok) => self.ctx.i.ex(**tok).await.rc(),
|
||||
OrcStringKind::Int(tok) => self.ctx.i().ex(**tok).await.rc(),
|
||||
OrcStringKind::Val(atom) => atom.request(StringGetVal).await,
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ impl TryFromExpr for OrcString<'static> {
|
||||
let ctx = expr.ctx();
|
||||
match TypAtom::<IntStrAtom>::try_from_expr(expr).await {
|
||||
Ok(t) => Ok(OrcString { ctx: t.data.ctx(), kind: OrcStringKind::Int(t) }),
|
||||
Err(e) => Err(mk_errv(ctx.i.i("A string was expected").await, "", e.pos_iter())),
|
||||
Err(e) => Err(mk_errv(ctx.i().i("A string was expected").await, "", e.pos_iter())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user