Compiles again after command subsystem
Some checks failed
Rust / build (push) Failing after 3m52s

terrified to start testing
This commit is contained in:
2026-03-27 23:50:58 +01:00
parent 09cfcb1839
commit 0909524dee
75 changed files with 1165 additions and 609 deletions

View File

@@ -1,78 +1,21 @@
use std::any::{Any, TypeId, type_name};
use std::fmt::Debug;
use std::future::Future;
use std::num::NonZero;
use std::rc::Rc;
use futures::FutureExt;
use futures::future::LocalBoxFuture;
use orchid_api_traits::{Coding, Decode, Encode, Request};
use orchid_base::{BoxedIter, Receipt, ReqHandle, ReqReader, ReqReaderExt, Sym};
use orchid_base::{Receipt, ReqHandle, ReqReader, ReqReaderExt, Sym};
use task_local::task_local;
use crate::api;
use crate::atom::{AtomOps, AtomTypeId, Atomic, AtomicFeatures};
use crate::coroutine_exec::Replier;
use crate::entrypoint::request;
use crate::func_atom::{Fun, Lambda};
use crate::lexer::LexerObj;
use crate::parser::ParserObj;
use crate::system_ctor::{CtedObj, SystemCtor};
use crate::tree::GenMember;
use crate::{Cted, CtedObj, DynSystemCard, LexerObj, ParserObj, SystemCard, SystemCtor, api};
/// Description of a system. This is a distinct object because [SystemCtor]
/// isn't [Default]
pub trait SystemCard: Debug + Default + 'static {
type Ctor: SystemCtor;
type Req: Coding;
fn atoms() -> impl IntoIterator<Item = Option<Box<dyn AtomOps>>>;
}
/// Type-erased [SystemCard]
pub trait DynSystemCard: Any + 'static {
fn name(&self) -> &'static str;
/// Atoms explicitly defined by the system card. Do not rely on this for
/// querying atoms as it doesn't include the general atom types
fn atoms(&'_ self) -> BoxedIter<'_, Option<Box<dyn AtomOps>>>;
}
impl<T: DynSystemCard + ?Sized> DynSystemCardExt for T {}
pub(crate) trait DynSystemCardExt: DynSystemCard {
fn ops_by_tid(&self, tid: TypeId) -> Option<(AtomTypeId, Box<dyn AtomOps>)> {
(self.atoms().enumerate().map(|(i, o)| (NonZero::new(i as u32 + 1).unwrap(), o)))
.chain(general_atoms().enumerate().map(|(i, o)| (NonZero::new(!(i as u32)).unwrap(), o)))
.filter_map(|(i, o)| o.map(|a| (AtomTypeId(i), a)))
.find(|ent| ent.1.tid() == tid)
}
fn ops_by_atid(&self, tid: AtomTypeId) -> Option<Box<dyn AtomOps>> {
if (u32::from(tid.0) >> (u32::BITS - 1)) & 1 == 1 {
general_atoms().nth(!u32::from(tid.0) as usize).unwrap()
} else {
self.atoms().nth(u32::from(tid.0) as usize - 1).unwrap()
}
}
fn ops<A: Atomic>(&self) -> (AtomTypeId, Box<dyn AtomOps>) {
self
.ops_by_tid(TypeId::of::<A>())
.unwrap_or_else(|| panic!("{} is not an atom in {}", type_name::<A>(), self.name()))
}
}
/// Atoms supported by this package which may appear in all extensions.
/// The indices of these are bitwise negated, such that the MSB of an atom index
/// marks whether it belongs to this package (0) or the importer (1)
fn general_atoms() -> impl Iterator<Item = Option<Box<dyn AtomOps>>> {
[Some(Fun::ops()), Some(Lambda::ops()), Some(Replier::ops())].into_iter()
}
impl<T: SystemCard> DynSystemCard for T {
fn name(&self) -> &'static str { T::Ctor::NAME }
fn atoms(&'_ self) -> BoxedIter<'_, Option<Box<dyn AtomOps>>> {
Box::new(Self::atoms().into_iter())
}
}
pub type CardForSystem<T> = <<T as System>::Ctor as SystemCtor>::Card;
pub type ReqForSystem<T> = <CardForSystem<T> as SystemCard>::Req;
/// System as defined by author
pub trait System: SystemCard + 'static {
pub trait System: Debug + 'static {
type Ctor: SystemCtor<Instance = Self>;
fn prelude(&self) -> impl Future<Output = Vec<Sym>>;
fn env(&self) -> impl Future<Output = Vec<GenMember>>;
fn lexers(&self) -> Vec<LexerObj>;
@@ -80,11 +23,11 @@ pub trait System: SystemCard + 'static {
fn request<'a>(
&self,
hand: Box<dyn ReqHandle<'a> + 'a>,
req: Self::Req,
req: ReqForSystem<Self>,
) -> impl Future<Output = Receipt<'a>>;
}
pub trait DynSystem: DynSystemCard + 'static {
pub trait DynSystem: Debug + 'static {
fn dyn_prelude(&self) -> LocalBoxFuture<'_, Vec<Sym>>;
fn dyn_env(&self) -> LocalBoxFuture<'_, Vec<GenMember>>;
fn dyn_lexers(&self) -> Vec<LexerObj>;
@@ -93,7 +36,7 @@ pub trait DynSystem: DynSystemCard + 'static {
&'a self,
hand: Box<dyn ReqReader<'b> + 'b>,
) -> LocalBoxFuture<'a, Receipt<'b>>;
fn card(&self) -> &dyn DynSystemCard;
fn card(&self) -> Box<dyn DynSystemCard>;
}
impl<T: System> DynSystem for T {
@@ -106,11 +49,11 @@ impl<T: System> DynSystem for T {
mut hand: Box<dyn ReqReader<'b> + 'b>,
) -> LocalBoxFuture<'a, Receipt<'b>> {
Box::pin(async move {
let value = hand.read_req::<<Self as SystemCard>::Req>().await.unwrap();
let value = hand.read_req().await.unwrap();
self.request(hand.finish().await, value).await
})
}
fn card(&self) -> &dyn DynSystemCard { self }
fn card(&self) -> Box<dyn DynSystemCard> { Box::new(CardForSystem::<Self>::default()) }
}
#[derive(Clone)]
@@ -125,23 +68,7 @@ pub(crate) async fn with_sys<F: Future>(sys: SysCtx, fut: F) -> F::Output {
}
pub fn sys_id() -> api::SysId { SYS_CTX.with(|cx| cx.0) }
pub fn cted() -> CtedObj { SYS_CTX.with(|cx| cx.1.clone()) }
/// 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();
let own_inst = cted.inst();
let owner = if own_inst.card().type_id() == TypeId::of::<Sys>() {
sys_id()
} else {
(cted.deps().find(|s| s.get_card().type_id() == TypeId::of::<Sys>()))
.expect("System not in dependency array")
.id()
};
let reply = request(api::SysFwd(owner, msg)).await;
Req::Response::decode(std::pin::pin!(&reply[..])).await.unwrap()
pub fn dyn_cted() -> CtedObj { SYS_CTX.with(|cx| cx.1.clone()) }
pub fn cted<C: SystemCtor>() -> Cted<C> {
Rc::downcast::<Cted<C>>(dyn_cted().as_any()).unwrap().as_ref().clone()
}