New macro system and stdlib additions

This commit is contained in:
2025-11-21 14:25:03 +01:00
parent b77653f841
commit 603efef28e
230 changed files with 3033 additions and 16640 deletions

View File

@@ -25,26 +25,26 @@ use crate::atom::{
AtomCard, AtomCtx, AtomDynfo, AtomFactory, Atomic, AtomicFeaturesImpl, AtomicVariant, MethodSet,
MethodSetBuilder, TAtom, err_not_callable, err_not_command, get_info,
};
use crate::context::{SysCtxEntry, ctx, i};
use crate::expr::Expr;
use crate::gen_expr::{GExpr, bot};
use crate::system::{SysCtx, SysCtxEntry};
use crate::system_ctor::CtedObj;
pub struct OwnedVariant;
impl AtomicVariant for OwnedVariant {}
impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVariant> for A {
fn _factory(self) -> AtomFactory {
AtomFactory::new(async move |ctx| {
let serial =
ctx.get_or_default::<ObjStore>().next_id.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
AtomFactory::new(async move || {
let serial = ctx()
.get_or_default::<ObjStore>()
.next_id
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
let atom_id = api::AtomId(NonZero::new(serial + 1).unwrap());
let (typ_id, _) = get_info::<A>(ctx.get::<CtedObj>().inst().card());
let (typ_id, _) = get_info::<A>(ctx().get::<CtedObj>().inst().card());
let mut data = enc_vec(&typ_id).await;
self.encode(Pin::<&mut Vec<u8>>::new(&mut data)).await;
let g = ctx.get_or_default::<ObjStore>().objects.read().await;
g.insert(atom_id, Box::new(self));
std::mem::drop(g);
api::Atom { drop: Some(atom_id), data: api::AtomData(data), owner: ctx.sys_id() }
ctx().get_or_default::<ObjStore>().objects.read().await.insert(atom_id, Box::new(self));
api::Atom { drop: Some(atom_id), data: api::AtomData(data), owner: ctx().sys_id() }
})
}
fn _info() -> Self::_Info { OwnedAtomDynfo { msbuild: A::reg_reqs(), ms: OnceCell::new() } }
@@ -58,8 +58,8 @@ pub(crate) struct AtomReadGuard<'a> {
guard: RwLockReadGuard<MemoMap<api::AtomId, Box<dyn DynOwnedAtom>>>,
}
impl<'a> AtomReadGuard<'a> {
async fn new(id: api::AtomId, ctx: &'a SysCtx) -> Self {
let guard = ctx.get_or_default::<ObjStore>().objects.read().await;
async fn new(id: api::AtomId) -> Self {
let guard = ctx().get_or_default::<ObjStore>().objects.read().await;
if guard.get(&id).is_none() {
panic!("Received invalid atom ID: {id:?}");
}
@@ -72,8 +72,8 @@ impl Deref for AtomReadGuard<'_> {
}
/// Remove an atom from the store
pub(crate) async fn take_atom(id: api::AtomId, ctx: &SysCtx) -> Box<dyn DynOwnedAtom> {
let mut g = ctx.get_or_default::<ObjStore>().objects.write().await;
pub(crate) async fn take_atom(id: api::AtomId) -> Box<dyn DynOwnedAtom> {
let mut g = ctx().get_or_default::<ObjStore>().objects.write().await;
g.remove(&id).unwrap_or_else(|| panic!("Received invalid atom ID: {}", id.0))
}
@@ -89,64 +89,53 @@ impl<T: OwnedAtom> AtomDynfo for OwnedAtomDynfo<T> {
Box::new(<T as AtomCard>::Data::decode(Pin::new(&mut &data[..])).await) as Box<dyn Any>
})
}
fn call(&self, AtomCtx(_, id, ctx): AtomCtx, arg: Expr) -> LocalBoxFuture<'_, GExpr> {
Box::pin(async move { take_atom(id.unwrap(), &ctx).await.dyn_call(arg).await })
fn call(&self, AtomCtx(_, id): AtomCtx, arg: Expr) -> LocalBoxFuture<'_, GExpr> {
Box::pin(async move { take_atom(id.unwrap()).await.dyn_call(arg).await })
}
fn call_ref<'a>(
&'a self,
AtomCtx(_, id, ctx): AtomCtx<'a>,
arg: Expr,
) -> LocalBoxFuture<'a, GExpr> {
Box::pin(async move { AtomReadGuard::new(id.unwrap(), &ctx).await.dyn_call_ref(arg).await })
fn call_ref<'a>(&'a self, AtomCtx(_, id): AtomCtx<'a>, arg: Expr) -> LocalBoxFuture<'a, GExpr> {
Box::pin(async move { AtomReadGuard::new(id.unwrap()).await.dyn_call_ref(arg).await })
}
fn print(&self, AtomCtx(_, id, ctx): AtomCtx<'_>) -> LocalBoxFuture<'_, FmtUnit> {
Box::pin(
async move { AtomReadGuard::new(id.unwrap(), &ctx).await.dyn_print(ctx.clone()).await },
)
fn print(&self, AtomCtx(_, id): AtomCtx<'_>) -> LocalBoxFuture<'_, FmtUnit> {
Box::pin(async move { AtomReadGuard::new(id.unwrap()).await.dyn_print().await })
}
fn handle_req<'a, 'b: 'a, 'c: 'a>(
&'a self,
AtomCtx(_, id, ctx): AtomCtx,
AtomCtx(_, id): AtomCtx,
key: Sym,
req: Pin<&'b mut dyn AsyncRead>,
rep: Pin<&'c mut dyn AsyncWrite>,
) -> LocalBoxFuture<'a, bool> {
Box::pin(async move {
let a = AtomReadGuard::new(id.unwrap(), &ctx).await;
let ms = self.ms.get_or_init(self.msbuild.pack(ctx.clone())).await;
ms.dispatch(a.as_any_ref().downcast_ref().unwrap(), ctx.clone(), key, req, rep).await
let a = AtomReadGuard::new(id.unwrap()).await;
let ms = self.ms.get_or_init(self.msbuild.pack()).await;
ms.dispatch(a.as_any_ref().downcast_ref().unwrap(), key, req, rep).await
})
}
fn command<'a>(
&'a self,
AtomCtx(_, id, ctx): AtomCtx<'a>,
AtomCtx(_, id): AtomCtx<'a>,
) -> LocalBoxFuture<'a, OrcRes<Option<GExpr>>> {
Box::pin(async move { take_atom(id.unwrap(), &ctx).await.dyn_command(ctx.clone()).await })
Box::pin(async move { take_atom(id.unwrap()).await.dyn_command().await })
}
fn drop(&self, AtomCtx(_, id, ctx): AtomCtx) -> LocalBoxFuture<'_, ()> {
Box::pin(async move { take_atom(id.unwrap(), &ctx).await.dyn_free(ctx.clone()).await })
fn drop(&self, AtomCtx(_, id): AtomCtx) -> LocalBoxFuture<'_, ()> {
Box::pin(async move { take_atom(id.unwrap()).await.dyn_free().await })
}
fn serialize<'a, 'b: 'a>(
&'a self,
AtomCtx(_, id, ctx): AtomCtx<'a>,
AtomCtx(_, id): AtomCtx<'a>,
mut write: Pin<&'b mut dyn AsyncWrite>,
) -> LocalBoxFuture<'a, Option<Vec<Expr>>> {
Box::pin(async move {
let id = id.unwrap();
id.encode(write.as_mut()).await;
AtomReadGuard::new(id, &ctx).await.dyn_serialize(ctx.clone(), write).await
AtomReadGuard::new(id).await.dyn_serialize(write).await
})
}
fn deserialize<'a>(
&'a self,
ctx: SysCtx,
data: &'a [u8],
refs: &'a [Expr],
) -> LocalBoxFuture<'a, api::Atom> {
fn deserialize<'a>(&'a self, data: &'a [u8], refs: &'a [Expr]) -> LocalBoxFuture<'a, api::Atom> {
Box::pin(async move {
let refs = T::Refs::from_iter(refs.iter().cloned());
let obj = T::deserialize(DeserCtxImpl(data, &ctx), refs).await;
obj._factory().build(ctx).await
let obj = T::deserialize(DeserCtxImpl(data), refs).await;
obj._factory().build().await
})
}
}
@@ -162,14 +151,12 @@ pub trait DeserializeCtx: Sized {
t
}
}
fn sys(&self) -> SysCtx;
}
struct DeserCtxImpl<'a>(&'a [u8], &'a SysCtx);
struct DeserCtxImpl<'a>(&'a [u8]);
impl DeserializeCtx for DeserCtxImpl<'_> {
async fn read<T: Decode>(&mut self) -> T { T::decode(Pin::new(&mut self.0)).await }
fn is_empty(&self) -> bool { self.0.is_empty() }
fn sys(&self) -> SysCtx { self.1.clone() }
}
pub trait RefSet {
@@ -220,22 +207,21 @@ pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Any + Clone + 'static {
fn val(&self) -> impl Future<Output = Cow<'_, Self::Data>>;
#[allow(unused_variables)]
fn call_ref(&self, arg: Expr) -> impl Future<Output = GExpr> {
async move { bot(err_not_callable(arg.ctx().i()).await) }
async move { bot(err_not_callable().await) }
}
fn call(self, arg: Expr) -> impl Future<Output = GExpr> {
async {
let ctx = arg.ctx();
let gcl = self.call_ref(arg).await;
self.free(ctx).await;
self.free().await;
gcl
}
}
#[allow(unused_variables)]
fn command(self, ctx: SysCtx) -> impl Future<Output = OrcRes<Option<GExpr>>> {
async move { Err(err_not_command(ctx.i()).await) }
fn command(self) -> impl Future<Output = OrcRes<Option<GExpr>>> {
async move { Err(err_not_command().await) }
}
#[allow(unused_variables)]
fn free(self, ctx: SysCtx) -> impl Future<Output = ()> { async {} }
fn free(self) -> impl Future<Output = ()> { async {} }
#[allow(unused_variables)]
fn print_atom<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> impl Future<Output = FmtUnit> {
async { format!("OwnedAtom({})", type_name::<Self>()).into() }
@@ -243,14 +229,13 @@ pub trait OwnedAtom: Atomic<Variant = OwnedVariant> + Any + Clone + 'static {
#[allow(unused_variables)]
fn serialize(
&self,
ctx: SysCtx,
write: Pin<&mut (impl AsyncWrite + ?Sized)>,
) -> impl Future<Output = Self::Refs> {
assert_serializable::<Self>();
async { panic!("Either implement serialize or set Refs to Never for {}", type_name::<Self>()) }
}
#[allow(unused_variables)]
fn deserialize(ctx: impl DeserializeCtx, refs: Self::Refs) -> impl Future<Output = Self> {
fn deserialize(dctx: impl DeserializeCtx, refs: Self::Refs) -> impl Future<Output = Self> {
assert_serializable::<Self>();
async {
panic!("Either implement deserialize or set Refs to Never for {}", type_name::<Self>())
@@ -269,12 +254,11 @@ pub trait DynOwnedAtom: DynClone + 'static {
fn encode<'a>(&'a self, buffer: Pin<&'a mut dyn AsyncWrite>) -> LocalBoxFuture<'a, ()>;
fn dyn_call_ref(&self, arg: Expr) -> LocalBoxFuture<'_, GExpr>;
fn dyn_call(self: Box<Self>, arg: Expr) -> LocalBoxFuture<'static, GExpr>;
fn dyn_command(self: Box<Self>, ctx: SysCtx) -> LocalBoxFuture<'static, OrcRes<Option<GExpr>>>;
fn dyn_free(self: Box<Self>, ctx: SysCtx) -> LocalBoxFuture<'static, ()>;
fn dyn_print(&self, ctx: SysCtx) -> LocalBoxFuture<'_, FmtUnit>;
fn dyn_command(self: Box<Self>) -> LocalBoxFuture<'static, OrcRes<Option<GExpr>>>;
fn dyn_free(self: Box<Self>) -> LocalBoxFuture<'static, ()>;
fn dyn_print(&self) -> LocalBoxFuture<'_, FmtUnit>;
fn dyn_serialize<'a>(
&'a self,
ctx: SysCtx,
sink: Pin<&'a mut dyn AsyncWrite>,
) -> LocalBoxFuture<'a, Option<Vec<Expr>>>;
}
@@ -290,23 +274,20 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
fn dyn_call(self: Box<Self>, arg: Expr) -> LocalBoxFuture<'static, GExpr> {
self.call(arg).boxed_local()
}
fn dyn_command(self: Box<Self>, ctx: SysCtx) -> LocalBoxFuture<'static, OrcRes<Option<GExpr>>> {
self.command(ctx).boxed_local()
fn dyn_command(self: Box<Self>) -> LocalBoxFuture<'static, OrcRes<Option<GExpr>>> {
self.command().boxed_local()
}
fn dyn_free(self: Box<Self>, ctx: SysCtx) -> LocalBoxFuture<'static, ()> {
self.free(ctx).boxed_local()
}
fn dyn_print(&self, ctx: SysCtx) -> LocalBoxFuture<'_, FmtUnit> {
async move { self.print_atom(&FmtCtxImpl { i: ctx.i() }).await }.boxed_local()
fn dyn_free(self: Box<Self>) -> LocalBoxFuture<'static, ()> { self.free().boxed_local() }
fn dyn_print(&self) -> LocalBoxFuture<'_, FmtUnit> {
async move { self.print_atom(&FmtCtxImpl { i: &i() }).await }.boxed_local()
}
fn dyn_serialize<'a>(
&'a self,
ctx: SysCtx,
sink: Pin<&'a mut dyn AsyncWrite>,
) -> LocalBoxFuture<'a, Option<Vec<Expr>>> {
match TypeId::of::<Never>() == TypeId::of::<<Self as OwnedAtom>::Refs>() {
true => ready(None).boxed_local(),
false => async { Some(self.serialize(ctx, sink).await.to_vec()) }.boxed_local(),
false => async { Some(self.serialize(sink).await.to_vec()) }.boxed_local(),
}
}
}
@@ -318,16 +299,16 @@ pub(crate) struct ObjStore {
}
impl SysCtxEntry for ObjStore {}
pub async fn own<A: OwnedAtom>(typ: TAtom<A>) -> A {
let ctx = typ.untyped.ctx();
let g = ctx.get_or_default::<ObjStore>().objects.read().await;
pub async fn own<A: OwnedAtom>(typ: &TAtom<A>) -> A {
let g = ctx().get_or_default::<ObjStore>().objects.read().await;
let atom_id = typ.untyped.atom.drop.expect("Owned atoms always have a drop ID");
let dyn_atom =
g.get(&atom_id).expect("Atom ID invalid; atom type probably not owned by this crate");
dyn_atom.as_any_ref().downcast_ref().cloned().expect("The ID should imply a type as well")
}
pub async fn debug_print_obj_store(ctx: &SysCtx, show_atoms: bool) {
pub async fn debug_print_obj_store(show_atoms: bool) {
let ctx = ctx();
let store = ctx.get_or_default::<ObjStore>();
let keys = store.objects.read().await.keys().cloned().collect_vec();
let mut message = "Atoms in store:".to_string();
@@ -342,7 +323,7 @@ pub async fn debug_print_obj_store(ctx: &SysCtx, show_atoms: bool) {
};
let atom = clone_box(&**atom);
std::mem::drop(g);
message += &format!("\n{k:?} -> {}", take_first(&atom.dyn_print(ctx.clone()).await, true));
message += &format!("\n{k:?} -> {}", take_first(&atom.dyn_print().await, true));
}
}
eprintln!("{message}")