Significantly extended stdlib

This commit is contained in:
2026-01-27 20:53:45 +01:00
parent 66e5a71032
commit 534f08b45c
42 changed files with 635 additions and 211 deletions

View File

@@ -6,7 +6,7 @@ use std::future::Future;
use std::pin::Pin;
use std::rc::Rc;
use futures::future::LocalBoxFuture;
use futures::future::{LocalBoxFuture, join_all};
use futures::{AsyncWrite, FutureExt};
use itertools::Itertools;
use never::Never;
@@ -14,6 +14,7 @@ use orchid_api_traits::Encode;
use orchid_base::clone;
use orchid_base::error::OrcRes;
use orchid_base::format::{FmtCtx, FmtUnit};
use orchid_base::location::Pos;
use orchid_base::name::Sym;
use task_local::task_local;
use trait_set::trait_set;
@@ -24,7 +25,7 @@ use crate::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
use crate::conv::ToExpr;
use crate::coroutine_exec::{ExecHandle, exec};
use crate::expr::Expr;
use crate::gen_expr::GExpr;
use crate::gen_expr::{GExpr, new_atom};
use crate::system::sys_id;
trait_set! {
@@ -44,6 +45,16 @@ pub fn get_arg(idx: usize) -> Expr {
.expect("get_arg called outside ExprFunc")
}
pub fn get_argc() -> usize {
ARGV.try_with(|argv| argv.len()).expect("get_arg called outside ExprFunc")
}
pub async fn get_arg_posv(idxes: impl IntoIterator<Item = usize>) -> impl Iterator<Item = Pos> {
let args = (ARGV.try_with(|argv| idxes.into_iter().map(|i| &argv[i]).cloned().collect_vec()))
.expect("get_arg_posv called outside ExprFunc");
join_all(args.iter().map(|expr| expr.pos())).await.into_iter()
}
pub trait ExprFunc<I, O>: Clone + 'static {
fn argtyps() -> &'static [TypeId];
fn apply<'a>(&self, hand: ExecHandle<'a>, v: Vec<Expr>) -> impl Future<Output = OrcRes<GExpr>>;
@@ -123,7 +134,7 @@ impl OwnedAtom for Fun {
if new_args.len() == self.record.argtyps.len() {
(self.record.fun)(new_args).await.to_gen().await
} else {
Self { args: new_args, record: self.record.clone(), path: self.path.clone() }.to_gen().await
new_atom(Self { args: new_args, record: self.record.clone(), path: self.path.clone() })
}
}
async fn call(self, arg: Expr) -> GExpr { self.call_ref(arg).await }
@@ -169,7 +180,7 @@ impl OwnedAtom for Lambda {
if new_args.len() == self.record.argtyps.len() {
(self.record.fun)(new_args).await.to_gen().await
} else {
Self { args: new_args, record: self.record.clone() }.to_gen().await
new_atom(Self { args: new_args, record: self.record.clone() })
}
}
async fn call(self, arg: Expr) -> GExpr { self.call_ref(arg).await }
@@ -181,7 +192,7 @@ mod expr_func_derives {
use orchid_base::error::OrcRes;
use super::ExprFunc;
use super::{ARGV, ExprFunc};
use crate::conv::{ToExpr, TryFromExpr};
use crate::func_atom::{ExecHandle, Expr};
use crate::gen_expr::GExpr;
@@ -200,8 +211,9 @@ mod expr_func_derives {
}
async fn apply<'a>(&self, _: ExecHandle<'a>, v: Vec<Expr>) -> OrcRes<GExpr> {
assert_eq!(v.len(), Self::argtyps().len(), "Arity mismatch");
let argv = v.clone();
let [$([< $t:lower >],)*] = v.try_into().unwrap_or_else(|_| panic!("Checked above"));
Ok(self($($t::try_from_expr([< $t:lower >]).await?,)*).await.to_gen().await)
Ok(ARGV.scope(argv, self($($t::try_from_expr([< $t:lower >]).await?,)*)).await.to_gen().await)
}
}
}