forked from Orchid/orchid
Correctly halts
This commit is contained in:
@@ -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}")
|
||||
}
|
||||
|
||||
@@ -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() } }
|
||||
|
||||
@@ -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
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user