Correctly halts

This commit is contained in:
2025-09-16 22:54:14 +02:00
parent ee45dbd28e
commit 7971a2b4eb
29 changed files with 381 additions and 195 deletions

View File

@@ -8,6 +8,7 @@ use std::sync::atomic::AtomicU64;
use async_lock::{RwLock, RwLockReadGuard};
use async_once_cell::OnceCell;
use dyn_clone::{DynClone, clone_box};
use futures::future::{LocalBoxFuture, ready};
use futures::{AsyncRead, AsyncWrite, FutureExt};
use itertools::Itertools;
@@ -15,7 +16,7 @@ use memo_map::MemoMap;
use never::Never;
use orchid_api_traits::{Decode, Encode, enc_vec};
use orchid_base::error::OrcRes;
use orchid_base::format::{FmtCtx, FmtCtxImpl, FmtUnit};
use orchid_base::format::{FmtCtx, FmtCtxImpl, FmtUnit, take_first};
use orchid_base::name::Sym;
use crate::api;
@@ -39,8 +40,10 @@ impl<A: OwnedAtom + Atomic<Variant = OwnedVariant>> AtomicFeaturesImpl<OwnedVari
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;
ctx.get_or_default::<ObjStore>().objects.read().await.insert(atom_id, Box::new(self));
api::Atom { drop: Some(atom_id), data, owner: ctx.sys_id() }
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() }
})
}
fn _info() -> Self::_Info { OwnedAtomDynfo { msbuild: A::reg_reqs(), ms: OnceCell::new() } }
@@ -55,8 +58,10 @@ pub(crate) struct AtomReadGuard<'a> {
impl<'a> AtomReadGuard<'a> {
async fn new(id: api::AtomId, ctx: &'a SysCtx) -> Self {
let guard = ctx.get_or_default::<ObjStore>().objects.read().await;
let valid = guard.iter().map(|i| i.0).collect_vec();
assert!(guard.get(&id).is_some(), "Received invalid atom ID: {id:?} not in {valid:?}");
if guard.get(&id).is_none() {
let valid = guard.iter().map(|i| i.0).collect_vec();
panic!("Received invalid atom ID: {id:?} not in {valid:?}");
}
Self { id, guard }
}
}
@@ -257,7 +262,7 @@ fn assert_serializable<T: OwnedAtom>() {
assert_ne!(TypeId::of::<T::Refs>(), TypeId::of::<Never>(), "{MSG}");
}
pub trait DynOwnedAtom: 'static {
pub trait DynOwnedAtom: DynClone + 'static {
fn atom_tid(&self) -> TypeId;
fn as_any_ref(&self) -> &dyn Any;
fn encode<'a>(&'a self, buffer: Pin<&'a mut dyn AsyncWrite>) -> LocalBoxFuture<'a, ()>;
@@ -306,16 +311,38 @@ impl<T: OwnedAtom> DynOwnedAtom for T {
}
#[derive(Default)]
struct ObjStore {
next_id: AtomicU64,
objects: RwLock<MemoMap<api::AtomId, Box<dyn DynOwnedAtom>>>,
pub(crate) struct ObjStore {
pub(crate) next_id: AtomicU64,
pub(crate) objects: RwLock<MemoMap<api::AtomId, Box<dyn DynOwnedAtom>>>,
}
impl SysCtxEntry for ObjStore {}
pub async fn own<A: OwnedAtom>(typ: TypAtom<A>) -> A {
let ctx = typ.untyped.ctx();
let g = ctx.get_or_default::<ObjStore>().objects.read().await;
let dyn_atom = (g.get(&typ.untyped.atom.drop.expect("Owned atoms always have a drop ID")))
.expect("Atom ID invalid; atom type probably not owned by this crate");
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) {
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();
if !show_atoms {
message += &keys.iter().map(|k| format!(" {:?}", k)).join("");
} else {
for k in keys {
let g = store.objects.read().await;
let Some(atom) = g.get(&k) else {
message += &format!("\n{k:?} has since been deleted");
continue;
};
let atom = clone_box(&**atom);
std::mem::drop(g);
message += &format!("\n{k:?} -> {}", take_first(&atom.dyn_print(ctx.clone()).await, true));
}
}
eprintln!("{message}")
}

View File

@@ -28,7 +28,7 @@ impl<A: ThinAtom + Atomic<Variant = ThinVariant>> AtomicFeaturesImpl<ThinVariant
let (id, _) = get_info::<A>(ctx.get::<CtedObj>().inst().card());
let mut buf = enc_vec(&id).await;
self.encode(Pin::new(&mut buf)).await;
api::Atom { drop: None, data: buf, owner: ctx.sys_id() }
api::Atom { drop: None, data: api::AtomData(buf), owner: ctx.sys_id() }
})
}
fn _info() -> Self::_Info { ThinAtomDynfo { msbuild: Self::reg_reqs(), ms: OnceCell::new() } }

View File

@@ -5,6 +5,7 @@ use std::num::NonZero;
use std::pin::Pin;
use std::rc::Rc;
use async_lock::RwLock;
use futures::channel::mpsc::{Receiver, Sender, channel};
use futures::future::{LocalBoxFuture, join_all};
use futures::lock::Mutex;
@@ -54,7 +55,7 @@ pub enum MemberRecord {
}
pub struct SystemRecord {
lazy_members: HashMap<api::TreeId, MemberRecord>,
lazy_members: Mutex<HashMap<api::TreeId, MemberRecord>>,
ctx: SysCtx,
}
@@ -72,7 +73,7 @@ pub async fn with_atom_record<'a, F: Future<Output = SysCtx>, T>(
atom: &'a api::Atom,
cb: impl WithAtomRecordCallback<'a, T>,
) -> T {
let mut data = &atom.data[..];
let mut data = &atom.data.0[..];
let ctx = get_sys_ctx(atom.owner).await;
let inst = ctx.get::<CtedObj>().inst();
let id = AtomTypeId::decode(Pin::new(&mut data)).await;
@@ -82,7 +83,7 @@ pub async fn with_atom_record<'a, F: Future<Output = SysCtx>, T>(
pub struct ExtensionOwner {
_interner_cell: Rc<RefCell<Option<Interner>>>,
_systems_lock: Rc<Mutex<HashMap<api::SysId, SystemRecord>>>,
_systems_lock: Rc<RwLock<HashMap<api::SysId, SystemRecord>>>,
out_recv: Mutex<Receiver<Vec<u8>>>,
out_send: Sender<Vec<u8>>,
}
@@ -106,7 +107,7 @@ pub fn extension_init(
.map(|(id, sys)| (u16::try_from(id).expect("more than u16max system ctors"), sys))
.map(|(id, sys)| sys.decl(api::SysDeclId(NonZero::new(id + 1).unwrap())))
.collect_vec();
let systems_lock = Rc::new(Mutex::new(HashMap::<api::SysId, SystemRecord>::new()));
let systems_lock = Rc::new(RwLock::new(HashMap::<api::SysId, SystemRecord>::new()));
let ext_header = api::ExtensionHeader { name: data.name.to_string(), systems: decls.clone() };
let (out_send, in_recv) = channel::<Vec<u8>>(1);
let (in_send, out_recv) = channel::<Vec<u8>>(1);
@@ -119,7 +120,7 @@ pub fn extension_init(
let get_ctx = clone!(systems_weak; move |id: api::SysId| clone!(systems_weak; async move {
let systems =
systems_weak.upgrade().expect("System table dropped before request processing done");
systems.lock().await.get(&id).expect("System not found").ctx.clone()
systems.read().await.get(&id).expect("System not found").ctx.clone()
}));
let init_ctx = {
clone!(interner_weak, spawner, logger);
@@ -139,19 +140,14 @@ pub fn extension_init(
Box::pin(async move { in_send.send(a.to_vec()).await.unwrap() })
},
{
clone!(systems_weak, exit_send, get_ctx);
clone!(exit_send);
move |n, _| {
clone!(systems_weak, exit_send mut, get_ctx);
clone!(exit_send mut);
async move {
match n {
api::HostExtNotif::Exit => exit_send.send(()).await.unwrap(),
api::HostExtNotif::SystemDrop(api::SystemDrop(sys_id)) =>
if let Some(rc) = systems_weak.upgrade() {
mem::drop(rc.lock().await.remove(&sys_id))
},
api::HostExtNotif::AtomDrop(api::AtomDrop(sys_id, atom)) => {
let ctx = get_ctx(sys_id).await;
take_atom(atom, &ctx).await.dyn_free(ctx.clone()).await
api::HostExtNotif::Exit => {
eprintln!("Exit received");
exit_send.send(()).await.unwrap()
},
}
}
@@ -165,8 +161,22 @@ pub fn extension_init(
async move {
let interner_cell = interner_weak.upgrade().expect("Interner dropped before request");
let i = interner_cell.borrow().clone().expect("Request arrived before interner set");
writeln!(msg_logger, "{} extension received request {req:?}", data.name);
if !matches!(req, api::HostExtReq::AtomReq(api::AtomReq::AtomPrint(_))) {
writeln!(msg_logger, "{} extension received request {req:?}", data.name);
}
match req {
api::HostExtReq::SystemDrop(sys_drop) => {
if let Some(rc) = systems_weak.upgrade() {
mem::drop(rc.write().await.remove(&sys_drop.0))
}
hand.handle(&sys_drop, &()).await
},
api::HostExtReq::AtomDrop(atom_drop @ api::AtomDrop(sys_id, atom)) => {
let ctx = get_ctx(sys_id).await;
take_atom(atom, &ctx).await.dyn_free(ctx.clone()).await;
hand.handle(&atom_drop, &()).await
},
api::HostExtReq::Ping(ping @ api::Ping) => hand.handle(&ping, &()).await,
api::HostExtReq::Sweep(sweep @ api::Sweep) =>
hand.handle(&sweep, &i.sweep_replica().await).await,
@@ -178,18 +188,17 @@ pub fn extension_init(
cted.inst().dyn_lexers().iter().fold(api::CharFilter(vec![]), |cf, lx| {
char_filter_union(&cf, &mk_char_filter(lx.char_filter().iter().cloned()))
});
let lazy_mems = Mutex::new(HashMap::new());
let lazy_members = Mutex::new(HashMap::new());
let ctx = init_ctx(new_sys.id, cted.clone(), hand.reqnot()).await;
let const_root = stream::iter(cted.inst().dyn_env())
.then(|mem| {
let (req, lazy_mems) = (&hand, &lazy_mems);
let lazy_mems = &lazy_members;
clone!(i, ctx; async move {
let mut tia_ctx = TreeIntoApiCtxImpl {
lazy_members: &mut *lazy_mems.lock().await,
sys: ctx,
basepath: &[],
path: Substack::Bottom,
req
};
(i.i(&mem.name).await.to_api(), mem.kind.into_api(&mut tia_ctx).await)
})
@@ -198,9 +207,9 @@ pub fn extension_init(
.await;
let prelude =
cted.inst().dyn_prelude(&i).await.iter().map(|sym| sym.to_api()).collect();
let record = SystemRecord { ctx, lazy_members: lazy_mems.into_inner() };
let record = SystemRecord { ctx, lazy_members };
let systems = systems_weak.upgrade().expect("System constructed during shutdown");
systems.lock().await.insert(new_sys.id, record);
systems.write().await.insert(new_sys.id, record);
let line_types = join_all(
(cted.inst().dyn_parsers().iter())
.map(|p| async { i.i(p.line_head()).await.to_api() }),
@@ -212,9 +221,9 @@ pub fn extension_init(
api::HostExtReq::GetMember(get_tree @ api::GetMember(sys_id, tree_id)) => {
let sys_ctx = get_ctx(sys_id).await;
let systems = systems_weak.upgrade().expect("Member queried during shutdown");
let mut systems_g = systems.lock().await;
let SystemRecord { lazy_members, .. } =
systems_g.get_mut(&sys_id).expect("System not found");
let systems_g = systems.read().await;
let mut lazy_members =
systems_g.get(&sys_id).expect("System not found").lazy_members.lock().await;
let (path, cb) = match lazy_members.insert(tree_id, MemberRecord::Res) {
None => panic!("Tree for ID not found"),
Some(MemberRecord::Res) => panic!("This tree has already been transmitted"),
@@ -225,8 +234,7 @@ pub fn extension_init(
sys: sys_ctx,
path: Substack::Bottom,
basepath: &path,
lazy_members,
req: &hand,
lazy_members: &mut lazy_members,
};
hand.handle(&get_tree, &tree.into_api(&mut tia_ctx).await).await
},
@@ -237,7 +245,7 @@ pub fn extension_init(
sys.dyn_request(hand, payload).await
},
api::HostExtReq::LexExpr(lex @ api::LexExpr { sys, src, text, pos, id }) => {
let sys_ctx = get_ctx(sys).await;
let mut sys_ctx = get_ctx(sys).await;
let text = Tok::from_api(text, &i).await;
let src = Sym::from_api(src, sys_ctx.i()).await;
let rep = Reporter::new();
@@ -264,7 +272,7 @@ pub fn extension_init(
return hand.handle(&lex, &eopt).await;
},
Ok((s, expr)) => {
let expr = expr.into_api(&mut (), &mut (sys_ctx, &hand)).await;
let expr = expr.into_api(&mut (), &mut sys_ctx).await;
let pos = (text.len() - s.len()) as u32;
expr_store.dispose().await;
return hand.handle(&lex, &Some(Ok(api::LexedExpr { pos, expr }))).await;
@@ -294,22 +302,22 @@ pub fn extension_init(
let parse_res = parser.parse(pctx, *exported, comments, snip).await;
let o_line = match reporter.merge(parse_res) {
Err(e) => Err(e.to_api()),
Ok(t) => Ok(linev_into_api(t, ctx.clone(), &hand).await),
Ok(t) => Ok(linev_into_api(t, ctx.clone()).await),
};
mem::drop(line);
expr_store.dispose().await;
hand.handle(&pline, &o_line).await
},
api::HostExtReq::FetchParsedConst(ref fpc @ api::FetchParsedConst { id, sys }) => {
api::HostExtReq::FetchParsedConst(ref fpc @ api::FetchParsedConst(sys, id)) => {
let ctx = get_ctx(sys).await;
let cnst = get_const(id, ctx.clone()).await;
hand.handle(fpc, &cnst.api_return(ctx, &hand).await).await
hand.handle(fpc, &cnst.api_return(ctx).await).await
},
api::HostExtReq::AtomReq(atom_req) => {
let atom = atom_req.get_atom();
let atom_req = atom_req.clone();
with_atom_record(&get_ctx, atom, async move |nfo, ctx, id, buf| {
let actx = AtomCtx(buf, atom.drop, ctx.clone());
match &atom_req {
api::AtomReq::SerializeAtom(ser) => {
let mut buf = enc_vec(&id).await;
@@ -340,21 +348,20 @@ pub fn extension_init(
hand.handle(fwded, &some.then_some(reply)).await
},
api::AtomReq::CallRef(call @ api::CallRef(_, arg)) => {
// SAFETY: function calls borrow their argument implicitly
let expr_store = BorrowedExprStore::new();
let expr_handle = ExprHandle::borrowed(ctx.clone(), *arg, &expr_store);
let ret = nfo.call_ref(actx, Expr::from_handle(expr_handle.clone())).await;
expr_handle.drop_one().await;
let api_expr = ret.api_return(ctx.clone(), &hand).await;
let api_expr = ret.api_return(ctx.clone()).await;
mem::drop(expr_handle);
expr_store.dispose().await;
hand.handle(call, &api_expr).await
},
api::AtomReq::FinalCall(call @ api::FinalCall(_, arg)) => {
// SAFETY: function calls borrow their argument implicitly
let expr_store = BorrowedExprStore::new();
let expr_handle = ExprHandle::borrowed(ctx.clone(), *arg, &expr_store);
let ret = nfo.call(actx, Expr::from_handle(expr_handle.clone())).await;
let api_expr = ret.api_return(ctx.clone(), &hand).await;
let api_expr = ret.api_return(ctx.clone()).await;
mem::drop(expr_handle);
expr_store.dispose().await;
hand.handle(call, &api_expr).await
},
@@ -363,7 +370,7 @@ pub fn extension_init(
Ok(opt) => match opt {
None => hand.handle(cmd, &Ok(api::NextStep::Halt)).await,
Some(cont) => {
let cont = cont.api_return(ctx.clone(), &hand).await;
let cont = cont.api_return(ctx.clone()).await;
hand.handle(cmd, &Ok(api::NextStep::Continue(cont))).await
},
},

View File

@@ -51,14 +51,24 @@ impl ExprHandle {
/// Drop one instance of the handle silently; if it's the last one, do
/// nothing, otherwise send an Acquire
pub async fn drop_one(self: Rc<Self>) {
if let Err(rc) = Rc::try_unwrap(self) {
rc.ctx.reqnot().notify(api::Acquire(rc.ctx.sys_id(), rc.tk)).await
match Rc::try_unwrap(self) {
Err(rc) => {
eprintln!("Extending lifetime for {:?}", rc.tk);
rc.ctx.reqnot().notify(api::Acquire(rc.ctx.sys_id(), rc.tk)).await
},
Ok(hand) => {
// avoid calling destructor
hand.destructure();
},
}
}
/// Drop the handle and get the ticket without a release notification.
/// Use this with messages that imply ownership transfer. This function is
/// safe because abusing it is a memory leak.
pub fn serialize(self) -> api::ExprTicket { self.destructure().0 }
pub fn serialize(self) -> api::ExprTicket {
eprintln!("Skipping destructor for {:?}", self.tk);
self.destructure().0
}
}
impl Eq for ExprHandle {}
impl PartialEq for ExprHandle {

View File

@@ -1,3 +1,4 @@
use std::mem;
use std::rc::Rc;
use futures::FutureExt;
@@ -5,7 +6,6 @@ use orchid_base::error::{OrcErr, OrcErrv};
use orchid_base::format::{FmtCtx, FmtUnit, Format, Variants};
use orchid_base::location::Pos;
use orchid_base::name::Sym;
use orchid_base::reqnot::ReqHandlish;
use orchid_base::{match_mapping, tl_cache};
use crate::api;
@@ -19,17 +19,21 @@ pub struct GExpr {
pub pos: Pos,
}
impl GExpr {
pub async fn api_return(self, ctx: SysCtx, hand: &impl ReqHandlish) -> api::Expression {
pub async fn api_return(self, ctx: SysCtx) -> api::Expression {
if let GExprKind::Slot(ex) = self.kind {
hand.defer_drop(ex.handle());
let hand = ex.handle();
mem::drop(ex);
api::Expression {
location: api::Location::SlotTarget,
kind: api::ExpressionKind::Slot(ex.handle().tk),
kind: match Rc::try_unwrap(hand) {
Ok(h) => api::ExpressionKind::Slot { tk: h.serialize(), by_value: true },
Err(rc) => api::ExpressionKind::Slot { tk: rc.tk, by_value: false },
},
}
} else {
api::Expression {
location: api::Location::Inherit,
kind: self.kind.api_return(ctx, hand).boxed_local().await,
kind: self.kind.api_return(ctx).boxed_local().await,
}
}
}
@@ -53,17 +57,17 @@ pub enum GExprKind {
Bottom(OrcErrv),
}
impl GExprKind {
pub async fn api_return(self, ctx: SysCtx, hand: &impl ReqHandlish) -> api::ExpressionKind {
pub async fn api_return(self, ctx: SysCtx) -> api::ExpressionKind {
match_mapping!(self, Self => api::ExpressionKind {
Call(
f => Box::new(f.api_return(ctx.clone(), hand).await),
x => Box::new(x.api_return(ctx, hand).await)
f => Box::new(f.api_return(ctx.clone()).await),
x => Box::new(x.api_return(ctx).await)
),
Seq(
a => Box::new(a.api_return(ctx.clone(), hand).await),
b => Box::new(b.api_return(ctx, hand).await)
a => Box::new(a.api_return(ctx.clone()).await),
b => Box::new(b.api_return(ctx).await)
),
Lambda(arg, body => Box::new(body.api_return(ctx, hand).await)),
Lambda(arg, body => Box::new(body.api_return(ctx).await)),
Arg(arg),
Const(name.to_api()),
Bottom(err.to_api()),

View File

@@ -12,7 +12,7 @@ use orchid_base::location::SrcRange;
use orchid_base::match_mapping;
use orchid_base::name::Sym;
use orchid_base::parse::{Comment, ParseCtx, Snippet};
use orchid_base::reqnot::{ReqHandlish, Requester};
use orchid_base::reqnot::Requester;
use orchid_base::tree::{TokTree, Token, ttv_into_api};
use crate::api;
@@ -100,8 +100,8 @@ impl ParseCtx for ParsCtx<'_> {
type BoxConstCallback = Box<dyn FnOnce(ConstCtx) -> LocalBoxFuture<'static, GExpr>>;
#[derive(Default)]
struct ParsedConstCtxEntry {
consts: IdStore<BoxConstCallback>,
pub(crate) struct ParsedConstCtxEntry {
pub(crate) consts: IdStore<BoxConstCallback>,
}
impl SysCtxEntry for ParsedConstCtxEntry {}
@@ -136,7 +136,7 @@ impl ParsedLine {
let comments = comments.into_iter().cloned().collect();
ParsedLine { comments, sr: sr.clone(), kind: line_kind }
}
pub async fn into_api(self, ctx: SysCtx, hand: &dyn ReqHandlish) -> api::ParsedLine {
pub async fn into_api(self, mut ctx: SysCtx) -> api::ParsedLine {
api::ParsedLine {
comments: self.comments.into_iter().map(|c| c.to_api()).collect(),
source_range: self.sr.to_api(),
@@ -149,24 +149,20 @@ impl ParsedLine {
ctx.get_or_default::<ParsedConstCtxEntry>().consts.add(cb).id(),
)),
ParsedMemKind::Mod { lines, use_prelude } => api::ParsedMemberKind::Module {
lines: linev_into_api(lines, ctx, hand).boxed_local().await,
lines: linev_into_api(lines, ctx).boxed_local().await,
use_prelude,
},
},
}),
ParsedLineKind::Rec(tv) =>
api::ParsedLineKind::Recursive(ttv_into_api(tv, &mut (), &mut (ctx, hand)).await),
api::ParsedLineKind::Recursive(ttv_into_api(tv, &mut (), &mut ctx).await),
},
}
}
}
pub(crate) async fn linev_into_api(
v: Vec<ParsedLine>,
ctx: SysCtx,
hand: &dyn ReqHandlish,
) -> Vec<api::ParsedLine> {
join_all(v.into_iter().map(|l| l.into_api(ctx.clone(), hand))).await
pub(crate) async fn linev_into_api(v: Vec<ParsedLine>, ctx: SysCtx) -> Vec<api::ParsedLine> {
join_all(v.into_iter().map(|l| l.into_api(ctx.clone()))).await
}
pub enum ParsedLineKind {
@@ -218,7 +214,7 @@ impl ConstCtx {
}
pub(crate) async fn get_const(id: api::ParsedConstId, ctx: SysCtx) -> GExpr {
let ent = ctx.get::<ParsedConstCtxEntry>();
let ent = ctx.get_or_default::<ParsedConstCtxEntry>();
let rec = ent.consts.get(id.0).expect("Bad ID or double read of parsed const");
let ctx = ConstCtx { constid: id, ctx: ctx.clone() };
rec.remove()(ctx).await

View File

@@ -71,7 +71,7 @@ pub async fn resolv_atom(
sys: &(impl DynSystemCard + ?Sized),
atom: &api::Atom,
) -> Box<dyn AtomDynfo> {
let tid = AtomTypeId::decode(Pin::new(&mut &atom.data[..])).await;
let tid = AtomTypeId::decode(Pin::new(&mut &atom.data.0[..])).await;
atom_by_idx(sys, tid).expect("Value of nonexistent type found")
}
@@ -117,7 +117,7 @@ impl<T: System> DynSystem for T {
pub async fn downcast_atom<A>(foreign: ForeignAtom) -> Result<TypAtom<A>, ForeignAtom>
where A: AtomicFeatures {
let mut data = &foreign.atom.data[..];
let mut data = &foreign.atom.data.0[..];
let ctx = foreign.ctx().clone();
let value = AtomTypeId::decode(Pin::new(&mut data)).await;
let own_inst = ctx.get::<CtedObj>().inst();

View File

@@ -9,7 +9,6 @@ use itertools::Itertools;
use orchid_base::interner::{Interner, Tok};
use orchid_base::location::SrcRange;
use orchid_base::name::Sym;
use orchid_base::reqnot::ReqHandlish;
use orchid_base::tree::{TokTree, Token, TokenVariant};
use substack::Substack;
use trait_set::trait_set;
@@ -27,7 +26,7 @@ pub type GenTok = Token<Expr, GExpr>;
impl TokenVariant<api::Expression> for GExpr {
type FromApiCtx<'a> = ();
type ToApiCtx<'a> = (SysCtx, &'a dyn ReqHandlish);
type ToApiCtx<'a> = SysCtx;
async fn from_api(
_: &api::Expression,
_: &mut Self::FromApiCtx<'_>,
@@ -36,8 +35,8 @@ impl TokenVariant<api::Expression> for GExpr {
) -> Self {
panic!("Received new expression from host")
}
async fn into_api(self, (ctx, hand): &mut Self::ToApiCtx<'_>) -> api::Expression {
self.api_return(ctx.clone(), hand).await
async fn into_api(self, ctx: &mut Self::ToApiCtx<'_>) -> api::Expression {
self.api_return(ctx.clone()).await
}
}
@@ -188,7 +187,7 @@ impl MemKind {
pub async fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::MemberKind {
match self {
Self::Lazy(lazy) => api::MemberKind::Lazy(ctx.with_lazy(lazy)),
Self::Const(c) => api::MemberKind::Const(c.api_return(ctx.sys(), ctx.req()).await),
Self::Const(c) => api::MemberKind::Const(c.api_return(ctx.sys()).await),
Self::Mod { members } => api::MemberKind::Module(api::Module {
members: stream(async |mut cx| {
for m in members {
@@ -207,22 +206,19 @@ pub trait TreeIntoApiCtx {
fn sys(&self) -> SysCtx;
fn with_lazy(&mut self, fac: LazyMemberFactory) -> api::TreeId;
fn push_path(&mut self, seg: Tok<String>) -> impl TreeIntoApiCtx;
fn req(&self) -> &impl ReqHandlish;
}
pub struct TreeIntoApiCtxImpl<'a, 'b, RH: ReqHandlish> {
pub struct TreeIntoApiCtxImpl<'a, 'b> {
pub sys: SysCtx,
pub basepath: &'a [Tok<String>],
pub path: Substack<'a, Tok<String>>,
pub lazy_members: &'b mut HashMap<api::TreeId, MemberRecord>,
pub req: &'a RH,
}
impl<RH: ReqHandlish> TreeIntoApiCtx for TreeIntoApiCtxImpl<'_, '_, RH> {
impl TreeIntoApiCtx for TreeIntoApiCtxImpl<'_, '_> {
fn sys(&self) -> SysCtx { self.sys.clone() }
fn push_path(&mut self, seg: Tok<String>) -> impl TreeIntoApiCtx {
TreeIntoApiCtxImpl {
req: self.req,
lazy_members: self.lazy_members,
sys: self.sys.clone(),
basepath: self.basepath,
@@ -235,5 +231,4 @@ impl<RH: ReqHandlish> TreeIntoApiCtx for TreeIntoApiCtxImpl<'_, '_, RH> {
self.lazy_members.insert(id, MemberRecord::Gen(path, fac));
id
}
fn req(&self) -> &impl ReqHandlish { self.req }
}