Significantly extended stdlib
Some checks failed
Rust / build (push) Has been cancelled

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

@@ -9,9 +9,9 @@ use orchid_base::interner::is;
use orchid_base::location::Pos;
use trait_set::trait_set;
use crate::atom::{AtomicFeatures, ForeignAtom, TAtom, ToAtom};
use crate::atom::{AtomicFeatures, ForeignAtom, TAtom};
use crate::expr::{Expr, ExprKind};
use crate::gen_expr::{GExpr, atom, bot};
use crate::gen_expr::{GExpr, bot};
pub trait TryFromExpr: Sized {
fn try_from_expr(expr: Expr) -> impl Future<Output = OrcRes<Self>>;
@@ -111,10 +111,6 @@ impl<T: ToExpr> ToExpr for OrcRes<T> {
}
}
impl<A: ToAtom> ToExpr for A {
async fn to_gen(self) -> GExpr { atom(self) }
}
impl ToExpr for Never {
async fn to_gen(self) -> GExpr { match self {} }
}

View File

@@ -13,7 +13,7 @@ use crate::atom::Atomic;
use crate::atom_owned::{OwnedAtom, OwnedVariant};
use crate::conv::{ToExpr, TryFromExpr};
use crate::expr::Expr;
use crate::gen_expr::{GExpr, arg, call, lambda, seq};
use crate::gen_expr::{GExpr, arg, call, lambda, new_atom, seq};
enum Command {
Execute(GExpr, Sender<Expr>),
@@ -34,11 +34,11 @@ impl BuilderCoroutine {
None => panic!("Before the stream ends, we should have gotten a Halt"),
Some(Command::Halt(expr)) => expr,
Some(Command::Execute(expr, reply)) => call(
lambda(0, [seq([arg(0)], call(Replier { reply, builder: self }.to_gen().await, [arg(0)]))]),
lambda(0, [seq([arg(0)], call(new_atom(Replier { reply, builder: self }), [arg(0)]))]),
[expr],
),
Some(Command::Register(expr, reply)) =>
call(Replier { reply, builder: self }.to_gen().await, [expr]),
call(new_atom(Replier { reply, builder: self }), [expr]),
}
}
}

View File

@@ -261,7 +261,8 @@ impl ExtensionBuilder {
let text = es(text).await;
let src = Sym::from_api(src).await;
let expr_store = BorrowedExprStore::new();
let trigger_char = text.chars().nth(pos as usize).unwrap();
let tail = &text[pos as usize..];
let trigger_char = tail.chars().next().unwrap();
let ekey_na = ekey_not_applicable().await;
let ekey_cascade = ekey_cascade().await;
let lexers = cted().inst().dyn_lexers();
@@ -269,7 +270,7 @@ impl ExtensionBuilder {
lexers.iter().filter(|l| char_filter_match(l.char_filter(), trigger_char))
{
let ctx = LexContext::new(&expr_store, &text, id, pos, src.clone());
match try_with_reporter(lx.lex(&text[pos as usize..], &ctx)).await {
match try_with_reporter(lx.lex(tail, &ctx)).await {
Err(e) if e.any(|e| *e == ekey_na) => continue,
Err(e) => {
let eopt = e.keep_only(|e| *e != ekey_cascade).map(|e| Err(e.to_api()));

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)
}
}
}

View File

@@ -106,7 +106,8 @@ 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)) }
pub fn atom<A: ToAtom>(atom: A) -> GExpr { inherit(GExprKind::NewAtom(atom.to_atom_factory())) }
/// 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> {

View File

@@ -155,7 +155,10 @@ where A: AtomicFeatures {
Ok(TAtom { value: *value, untyped: foreign })
}
pub async fn dep_req<Sys: SystemCard, Req: Request + Into<Sys::Req>>(req: Req) -> Req::Response {
/// Make a global request to a system that supports this request type. The
/// target system must either be the system in which this function is called, or
/// one of its direct dependencies.
pub async fn sys_req<Sys: SystemCard, Req: Request + Into<Sys::Req>>(req: Req) -> Req::Response {
let mut msg = Vec::new();
req.into().encode_vec(&mut msg);
let cted = cted();

View File

@@ -20,7 +20,7 @@ use crate::api;
use crate::conv::ToExpr;
use crate::expr::{BorrowedExprStore, Expr, ExprHandle};
use crate::func_atom::{ExprFunc, Fun};
use crate::gen_expr::{GExpr, sym_ref};
use crate::gen_expr::{GExpr, new_atom, sym_ref};
pub type GenTokTree = TokTree<Expr, GExpr>;
pub type GenTok = Token<Expr, GExpr>;
@@ -75,7 +75,7 @@ pub fn root_mod(name: &str, mems: impl IntoIterator<Item = Vec<GenMember>>) -> (
}
pub fn fun<I, O>(public: bool, name: &str, xf: impl ExprFunc<I, O>) -> Vec<GenMember> {
let fac =
LazyMemberFactory::new(async move |sym| MemKind::Const(Fun::new(sym, xf).await.to_gen().await));
LazyMemberFactory::new(async move |sym| MemKind::Const(new_atom(Fun::new(sym, xf).await)));
vec![GenMember { name: name.to_string(), kind: MemKind::Lazy(fac), public, comments: vec![] }]
}
pub fn prefix(path: &str, items: impl IntoIterator<Item = Vec<GenMember>>) -> Vec<GenMember> {