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

@@ -11,7 +11,6 @@ use futures::lock::Mutex;
use futures::{FutureExt, SinkExt, StreamExt, stream, stream_select};
use hashbrown::HashMap;
use itertools::Itertools;
use orchid_api::{ExtMsgSet, IntReq};
use orchid_api_traits::{Decode, UnderRoot, enc_vec};
use orchid_base::builtin::{ExtInit, ExtPort, Spawner};
use orchid_base::char_filter::{char_filter_match, char_filter_union, mk_char_filter};
@@ -29,9 +28,9 @@ use trait_set::trait_set;
use crate::api;
use crate::atom::{AtomCtx, AtomDynfo, AtomTypeId};
use crate::atom_owned::take_atom;
use crate::expr::{Expr, ExprHandle};
use crate::expr::{BorrowedExprStore, Expr, ExprHandle};
use crate::lexer::{LexContext, ekey_cascade, ekey_not_applicable};
use crate::parser::{PTok, PTokTree, ParsCtx, get_const, linev_into_api};
use crate::parser::{PTokTree, ParsCtx, get_const, linev_into_api};
use crate::system::{SysCtx, atom_by_idx};
use crate::system_ctor::{CtedObj, DynSystemCtor};
use crate::tree::{LazyMemberFactory, TreeIntoApiCtxImpl};
@@ -124,7 +123,7 @@ pub fn extension_init(
}));
let init_ctx = {
clone!(interner_weak, spawner, logger);
move |id: api::SysId, cted: CtedObj, reqnot: ReqNot<ExtMsgSet>| {
move |id: api::SysId, cted: CtedObj, reqnot: ReqNot<api::ExtMsgSet>| {
clone!(interner_weak, spawner, logger; async move {
let interner_rc =
interner_weak.upgrade().expect("System construction order while shutting down");
@@ -242,49 +241,62 @@ pub fn extension_init(
let text = Tok::from_api(text, &i).await;
let src = Sym::from_api(src, sys_ctx.i()).await;
let rep = Reporter::new();
let ctx = LexContext { id, pos, text: &text, src, ctx: sys_ctx.clone(), rep: &rep };
let expr_store = BorrowedExprStore::new();
let trigger_char = text.chars().nth(pos as usize).unwrap();
let ekey_na = ekey_not_applicable(&i).await;
let ekey_cascade = ekey_cascade(&i).await;
let lexers = sys_ctx.cted().inst().dyn_lexers();
for lx in lexers.iter().filter(|l| char_filter_match(l.char_filter(), trigger_char)) {
let ctx = LexContext {
id,
pos,
text: &text,
src: src.clone(),
ctx: sys_ctx.clone(),
rep: &rep,
exprs: &expr_store,
};
match lx.lex(&text[pos as usize..], &ctx).await {
Err(e) if e.any(|e| *e == ekey_na) => continue,
Err(e) => {
let eopt = e.keep_only(|e| *e != ekey_cascade).map(|e| Err(e.to_api()));
expr_store.dispose().await;
return hand.handle(&lex, &eopt).await;
},
Ok((s, expr)) => {
let expr = expr.into_api(&mut (), &mut (sys_ctx, &hand)).await;
let pos = (text.len() - s.len()) as u32;
expr_store.dispose().await;
return hand.handle(&lex, &Some(Ok(api::LexedExpr { pos, expr }))).await;
},
}
}
writeln!(logger, "Got notified about n/a character '{trigger_char}'");
expr_store.dispose().await;
hand.handle(&lex, &None).await
},
api::HostExtReq::ParseLine(pline) => {
let api::ParseLine { module, src, exported, comments, sys, line } = &pline;
let mut ctx = get_ctx(*sys).await;
let api::ParseLine { module, src, exported, comments, sys, line, idx } = &pline;
let ctx = get_ctx(*sys).await;
let parsers = ctx.cted().inst().dyn_parsers();
let src = Sym::from_api(*src, ctx.i()).await;
let comments =
join_all(comments.iter().map(|c| Comment::from_api(c, src.clone(), &i))).await;
let line: Vec<PTokTree> = ttv_from_api(line, &mut ctx, &mut (), &src, &i).await;
let expr_store = BorrowedExprStore::new();
let mut from_api_ctx = (ctx.clone(), &expr_store);
let line: Vec<PTokTree> =
ttv_from_api(line, &mut from_api_ctx, &mut (), &src, &i).await;
let snip = Snippet::new(line.first().expect("Empty line"), &line);
let (head, tail) = snip.pop_front().unwrap();
let name = if let PTok::Name(n) = &head.tok { n } else { panic!("No line head") };
let parser =
parsers.iter().find(|p| p.line_head() == **name).expect("No parser candidate");
let parser = parsers[*idx as usize];
let module = Sym::from_api(*module, ctx.i()).await;
let reporter = Reporter::new();
let pctx = ParsCtx::new(ctx.clone(), module, &reporter);
let parse_res = parser.parse(pctx, *exported, comments, tail).await;
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),
};
expr_store.dispose().await;
hand.handle(&pline, &o_line).await
},
api::HostExtReq::FetchParsedConst(ref fpc @ api::FetchParsedConst { id, sys }) => {
@@ -297,6 +309,7 @@ pub fn extension_init(
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;
@@ -327,16 +340,23 @@ pub fn extension_init(
hand.handle(fwded, &some.then_some(reply)).await
},
api::AtomReq::CallRef(call @ api::CallRef(_, arg)) => {
// SAFETY: function calls own their argument implicitly
let expr_handle = unsafe { ExprHandle::from_args(ctx.clone(), *arg) };
let ret = nfo.call_ref(actx, Expr::from_handle(Rc::new(expr_handle))).await;
hand.handle(call, &ret.api_return(ctx.clone(), &hand).await).await
// 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;
expr_store.dispose().await;
hand.handle(call, &api_expr).await
},
api::AtomReq::FinalCall(call @ api::FinalCall(_, arg)) => {
// SAFETY: function calls own their argument implicitly
let expr_handle = unsafe { ExprHandle::from_args(ctx.clone(), *arg) };
let ret = nfo.call(actx, Expr::from_handle(Rc::new(expr_handle))).await;
hand.handle(call, &ret.api_return(ctx.clone(), &hand).await).await
// 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;
expr_store.dispose().await;
hand.handle(call, &api_expr).await
},
api::AtomReq::Command(cmd @ api::Command(_)) => match nfo.command(actx).await {
Err(e) => hand.handle(cmd, &Err(e.to_api())).await,
@@ -358,8 +378,7 @@ pub fn extension_init(
let ctx = get_ctx(*sys).await;
// SAFETY: deserialization implicitly grants ownership to previously owned exprs
let refs = (refs.iter())
.map(|tk| unsafe { ExprHandle::from_args(ctx.clone(), *tk) })
.map(|handle| Expr::from_handle(Rc::new(handle)))
.map(|tk| Expr::from_handle(ExprHandle::deserialize(ctx.clone(), *tk)))
.collect_vec();
let id = AtomTypeId::decode(Pin::new(&mut read)).await;
let inst = ctx.cted().inst();
@@ -373,7 +392,7 @@ pub fn extension_init(
},
);
*interner_cell.borrow_mut() =
Some(Interner::new_replica(rn.clone().map(|ir: IntReq| ir.into_root())));
Some(Interner::new_replica(rn.clone().map(|ir: api::IntReq| ir.into_root())));
spawner(Box::pin(clone!(spawner; async move {
let mut streams = stream_select! { in_recv.map(Some), exit_recv.map(|_| None) };
while let Some(item) = streams.next().await {