exec working up to halt

clean shutdown doesn't for some reason
This commit is contained in:
2025-09-09 16:30:49 +02:00
parent e339350505
commit ce08021e79
36 changed files with 460 additions and 399 deletions

View File

@@ -1,6 +1,7 @@
use std::fmt;
use std::rc::{Rc, Weak};
use async_lock::OnceCell;
use derive_destructure::destructure;
use orchid_base::format::{FmtCtx, FmtUnit, Format, take_first_fmt};
use orchid_base::location::Pos;
@@ -9,7 +10,7 @@ use orchid_base::tree::AtomRepr;
use crate::api;
use crate::ctx::Ctx;
use crate::expr::Expr;
use crate::expr::{Expr, ExprParseCtx, PathSetBuilder};
use crate::extension::Extension;
use crate::system::System;
@@ -18,11 +19,12 @@ pub struct AtomData {
owner: System,
drop: Option<api::AtomId>,
data: Vec<u8>,
pub(crate) display: OnceCell<FmtUnit>,
}
impl AtomData {
#[must_use]
fn api(self) -> api::Atom {
let (owner, drop, data) = self.destructure();
let (owner, drop, data, _display) = self.destructure();
api::Atom { data, drop, owner: owner.id() }
}
#[must_use]
@@ -50,35 +52,22 @@ impl fmt::Debug for AtomData {
#[derive(Clone, Debug)]
pub struct AtomHand(Rc<AtomData>);
impl AtomHand {
#[must_use]
pub(crate) async fn new(api::Atom { data, drop, owner }: api::Atom, ctx: &Ctx) -> Self {
let create = || async {
let owner = ctx.system_inst(owner).await.expect("Dropped system created atom");
AtomHand(Rc::new(AtomData { data, owner, drop }))
};
if let Some(id) = drop {
let mut owned_g = ctx.owned_atoms.write().await;
if let Some(data) = owned_g.get(&id)
&& let Some(atom) = data.upgrade()
{
return atom;
}
let new = create().await;
owned_g.insert(id, new.downgrade());
new
} else {
create().await
}
pub(crate) fn new(data: Vec<u8>, owner: System, drop: Option<api::AtomId>) -> Self {
Self(Rc::new(AtomData { owner, drop, data, display: OnceCell::new() }))
}
#[must_use]
pub async fn call(self, arg: Expr) -> api::Expression {
pub async fn call(self, arg: Expr) -> Expr {
let owner_sys = self.0.owner.clone();
let reqnot = owner_sys.reqnot();
owner_sys.ext().exprs().give_expr(arg.clone());
match Rc::try_unwrap(self.0) {
let ret = match Rc::try_unwrap(self.0) {
Ok(data) => reqnot.request(api::FinalCall(data.api(), arg.id())).await,
Err(hand) => reqnot.request(api::CallRef(hand.api_ref(), arg.id())).await,
}
};
let mut parse_ctx = ExprParseCtx { ctx: owner_sys.ctx(), exprs: owner_sys.ext().exprs() };
let val = Expr::from_api(&ret, PathSetBuilder::new(), &mut parse_ctx).await;
owner_sys.ext().exprs().take_expr(arg.id());
val
}
#[must_use]
pub fn sys(&self) -> &System { &self.0.owner }
@@ -96,13 +85,19 @@ impl AtomHand {
}
impl Format for AtomHand {
async fn print<'a>(&'a self, _c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
FmtUnit::from_api(&self.0.owner.reqnot().request(api::AtomPrint(self.0.api_ref())).await)
(self.0.display.get_or_init(|| async {
FmtUnit::from_api(&self.0.owner.reqnot().request(api::AtomPrint(self.0.api_ref())).await)
}))
.await
.clone()
}
}
impl AtomRepr for AtomHand {
type Ctx = Ctx;
async fn from_api(atom: &orchid_api::Atom, _: Pos, ctx: &mut Self::Ctx) -> Self {
Self::new(atom.clone(), ctx).await
async fn from_api(atom: &api::Atom, _: Pos, ctx: &mut Self::Ctx) -> Self {
let api::Atom { data, drop, owner } = atom.clone();
let sys = ctx.system_inst(owner).await.expect("Dropped system created atom");
if let Some(id) = drop { sys.new_atom(data, id).await } else { AtomHand::new(data, sys, drop) }
}
async fn to_api(&self) -> orchid_api::Atom { self.api_ref() }
}