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

@@ -1,17 +1,18 @@
use std::mem;
use std::pin::{Pin, pin};
use std::rc::Rc;
use futures::FutureExt;
use orchid_base::error::{OrcErr, OrcErrv};
use orchid_base::format::{FmtCtx, FmtUnit, Format, Variants};
use orchid_base::location::Pos;
use orchid_base::name::Sym;
use orchid_base::{match_mapping, tl_cache};
use futures::{FutureExt, Stream, StreamExt, stream};
use orchid_base::{
FmtCtx, FmtUnit, Format, OrcErr, OrcErrv, Pos, Sym, Variants, match_mapping, tl_cache,
};
use crate::api;
use crate::atom::{AtomFactory, ToAtom};
use crate::atom::{AtomFactory, AtomicFeatures};
use crate::conv::{ToExpr, ToExprFuture};
use crate::entrypoint::request;
use crate::expr::Expr;
use crate::system::sys_id;
#[derive(Clone, Debug)]
pub struct GExpr {
@@ -39,7 +40,7 @@ impl GExpr {
}
pub fn at(self, pos: Pos) -> Self { GExpr { pos, kind: self.kind } }
pub async fn create(self) -> Expr {
Expr::deserialize(request(api::Create(self.serialize().await)).await).await
Expr::deserialize(request(api::Create(sys_id(), self.serialize().await)).await).await
}
}
impl Format for GExpr {
@@ -55,6 +56,7 @@ pub enum GExprKind {
Arg(u64),
Seq(Box<GExpr>, Box<GExpr>),
Const(Sym),
#[allow(private_interfaces)]
NewAtom(AtomFactory),
Slot(Expr),
Bottom(OrcErrv),
@@ -105,27 +107,105 @@ impl Format for GExprKind {
fn inherit(kind: GExprKind) -> GExpr { GExpr { pos: Pos::Inherit, kind } }
pub fn sym_ref(path: Sym) -> GExpr { inherit(GExprKind::Const(path)) }
/// Creates an expression from a new atom that we own.
pub fn new_atom<A: ToAtom>(atom: A) -> GExpr { inherit(GExprKind::NewAtom(atom.to_atom_factory())) }
pub fn seq(deps: impl IntoIterator<Item = GExpr>, val: GExpr) -> GExpr {
fn recur(mut ops: impl Iterator<Item = GExpr>) -> Option<GExpr> {
let op = ops.next()?;
Some(match recur(ops) {
None => op,
Some(rec) => inherit(GExprKind::Seq(Box::new(op), Box::new(rec))),
})
impl ToExpr for Sym {
async fn to_expr(self) -> Expr
where Self: Sized {
self.to_gen().await.create().await
}
recur(deps.into_iter().chain([val])).expect("Empty list provided to seq!")
async fn to_gen(self) -> GExpr { inherit(GExprKind::Const(self)) }
}
/// Creates an expression from a new atom that we own.
pub fn new_atom<A: AtomicFeatures>(atom: A) -> GExpr { inherit(GExprKind::NewAtom(atom.factory())) }
pub fn seq(
deps: impl IntoGExprStream,
val: impl ToExpr,
) -> ToExprFuture<impl Future<Output = GExpr>> {
ToExprFuture(async {
async fn recur(mut ops: Pin<&mut impl Stream<Item = GExpr>>) -> Option<GExpr> {
let op = ops.next().await?.to_gen().await;
Some(match recur(ops).boxed_local().await {
None => op,
Some(rec) => inherit(GExprKind::Seq(Box::new(op), Box::new(rec))),
})
}
recur(pin!(deps.into_gexpr_stream().chain(stream::iter([val.to_gen().await]))))
.await
.expect("Empty list provided to seq!")
})
}
pub fn arg(n: u64) -> GExpr { inherit(GExprKind::Arg(n)) }
pub fn lambda(n: u64, [b]: [GExpr; 1]) -> GExpr { inherit(GExprKind::Lambda(n, Box::new(b))) }
pub fn lam<const N: u64>(b: impl ToExpr) -> ToExprFuture<impl Future<Output = GExpr>> {
dyn_lambda(N, b)
}
pub fn call(f: GExpr, argv: impl IntoIterator<Item = GExpr>) -> GExpr {
(argv.into_iter()).fold(f, |f, x| inherit(GExprKind::Call(Box::new(f), Box::new(x))))
pub fn dyn_lambda(n: u64, b: impl ToExpr) -> ToExprFuture<impl Future<Output = GExpr>> {
ToExprFuture(async move { inherit(GExprKind::Lambda(n, Box::new(b.to_gen().await))) })
}
pub trait IntoGExprStream {
fn into_gexpr_stream(self) -> impl Stream<Item = GExpr>;
}
impl<T: ToExpr> IntoGExprStream for T {
fn into_gexpr_stream(self) -> impl Stream<Item = GExpr> { (self,).into_gexpr_stream() }
}
impl IntoGExprStream for Vec<GExpr> {
fn into_gexpr_stream(self) -> impl Stream<Item = GExpr> { stream::iter(self) }
}
mod tuple_impls {
use futures::{Stream, StreamExt, stream};
use super::IntoGExprStream;
use crate::conv::ToExpr;
use crate::gen_expr::GExpr;
macro_rules! tuple_impl {
($($T:ident)*) => {
pastey::paste!{
impl<$($T: ToExpr),*> IntoGExprStream for ($($T,)*) {
fn into_gexpr_stream(self) -> impl Stream<Item = GExpr> {
let ($([< $T:snake >],)*) = self;
stream::once(async { stream::iter([$([< $T:snake >].to_gen().await,)*]) }).flatten()
}
}
}
};
}
tuple_impl!();
tuple_impl!(A);
tuple_impl!(A B);
tuple_impl!(A B C);
tuple_impl!(A B C D);
tuple_impl!(A B C D E);
tuple_impl!(A B C D E F);
}
pub fn call(
f: impl ToExpr,
argv: impl IntoGExprStream,
) -> ToExprFuture<impl Future<Output = GExpr>> {
ToExprFuture(async {
(argv.into_gexpr_stream())
.fold(f.to_gen().await, async |f, x| inherit(GExprKind::Call(Box::new(f), Box::new(x))))
.await
})
}
pub fn call_v(
f: impl ToExpr,
argv: impl IntoIterator<Item: ToExpr>,
) -> ToExprFuture<impl Future<Output = GExpr>> {
ToExprFuture(async {
stream::iter(argv)
.fold(f.to_gen().await, async |f, x| {
inherit(GExprKind::Call(Box::new(f), Box::new(x.to_gen().await)))
})
.await
})
}
pub fn bot(ev: impl IntoIterator<Item = OrcErr>) -> GExpr {