partway towards commands

I got very confused and started mucking about with "spawn" when in fact all I needed was the "inline" extension type in orcx that allows the interpreter to expose custom constants.
This commit is contained in:
2026-03-13 16:48:42 +01:00
parent cdcca694c5
commit 09cfcb1839
146 changed files with 3582 additions and 2822 deletions

View File

@@ -0,0 +1,98 @@
use std::borrow::Cow;
use std::time::Instant;
use chrono::TimeDelta;
use never::Never;
use orchid_api::ExprTicket;
use orchid_api_derive::{Coding, Hierarchy};
use orchid_api_traits::Request;
use orchid_base::{Numeric, OrcRes};
use orchid_extension::conv::{ToExpr, TryFromExpr};
use orchid_extension::expr::Expr;
use orchid_extension::gen_expr::{GExpr, call, new_atom};
use orchid_extension::system::sys_req;
use orchid_extension::tree::{GenMember, fun, prefix};
use orchid_extension::{Atomic, OwnedAtom, OwnedVariant, TAtom, ThinAtom, ThinVariant};
use ordered_float::NotNan;
use crate::std::std_system::StdReq;
use crate::{Float, Int, Num, StdSystem};
#[derive(Clone, Copy, Debug, Coding, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Hierarchy)]
#[extends(StdReq)]
pub struct CreateDT(pub OrcDT);
impl Request for CreateDT {
type Response = ExprTicket;
}
#[derive(Clone, Copy, Debug, Coding, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct OrcDT(pub TimeDelta);
impl Atomic for OrcDT {
type Variant = ThinVariant;
type Data = Self;
}
impl ThinAtom for OrcDT {}
impl ToExpr for OrcDT {
async fn to_gen(self) -> GExpr {
Expr::deserialize(sys_req::<StdSystem, _>(CreateDT(self)).await).await.to_gen().await
}
}
impl TryFromExpr for OrcDT {
async fn try_from_expr(expr: Expr) -> OrcRes<Self> {
Ok(TAtom::<OrcDT>::try_from_expr(expr).await?.value)
}
}
#[derive(Clone)]
pub struct InstantAtom(Instant);
impl Atomic for InstantAtom {
type Variant = OwnedVariant;
type Data = ();
}
impl OwnedAtom for InstantAtom {
type Refs = Never;
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
}
#[derive(Clone)]
struct Now(Expr);
impl Atomic for Now {
type Variant = OwnedVariant;
type Data = ();
}
impl OwnedAtom for Now {
type Refs = Never;
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
async fn command(self) -> OrcRes<Option<GExpr>> {
Ok(Some(call(self.0, new_atom(InstantAtom(Instant::now())))))
}
}
pub fn gen_time_lib() -> Vec<GenMember> {
prefix("std::time", [
fun(true, "weeks", async |amount: Int| new_atom(OrcDT(TimeDelta::weeks(amount.0)))),
fun(true, "num_weeks", async |amount: TAtom<OrcDT>| Int(amount.0.num_weeks())),
fun(true, "days", async |amount: Int| new_atom(OrcDT(TimeDelta::days(amount.0)))),
fun(true, "num_days", async |amount: TAtom<OrcDT>| Int(amount.0.num_days())),
fun(true, "hours", async |amount: Int| new_atom(OrcDT(TimeDelta::hours(amount.0)))),
fun(true, "num_hours", async |amount: TAtom<OrcDT>| Int(amount.0.num_hours())),
fun(true, "minutes", async |amount: Int| new_atom(OrcDT(TimeDelta::minutes(amount.0)))),
fun(true, "num_minutes", async |amount: TAtom<OrcDT>| Int(amount.0.num_minutes())),
fun(true, "secs", async |amount: Num| {
new_atom(OrcDT(match amount.0 {
Numeric::Int(i) => TimeDelta::seconds(i),
Numeric::Float(f) =>
TimeDelta::new(f.floor() as i64, (f.fract() * 1_000_000_000_f64).floor() as u32).unwrap(),
}))
}),
fun(true, "num_secs", async |amount: TAtom<OrcDT>| Int(amount.0.num_seconds())),
fun(true, "as_secs", async |amount: TAtom<OrcDT>| {
Float(NotNan::new(amount.0.as_seconds_f64()).unwrap())
}),
fun(true, "milis", async |amount: Int| new_atom(OrcDT(TimeDelta::milliseconds(amount.0)))),
fun(true, "num_millis", async |amount: TAtom<OrcDT>| Int(amount.0.num_milliseconds())),
fun(true, "nanos", async |amount: Int| new_atom(OrcDT(TimeDelta::nanoseconds(amount.0)))),
fun(true, "num_nanos", async |amount: TAtom<OrcDT>| Int(amount.0.num_nanoseconds().unwrap())),
fun(true, "now", async |cb: Expr| new_atom(Now(cb))),
])
}