lex_hello worked for a second just now

this is just a backup however
This commit is contained in:
2025-02-02 10:20:03 +01:00
parent 2b79e96dc9
commit 1556d54226
45 changed files with 646 additions and 371 deletions

View File

@@ -86,7 +86,7 @@ impl AtomHand {
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
Self::new(atom.clone(), ctx).await
}
async fn to_api(&self) -> orchid_api::Atom { self.api_ref() }
async fn print(&self) -> String { self.to_string().await }

View File

@@ -1,12 +1,12 @@
use std::cell::RefCell;
use std::num::NonZeroU16;
use std::num::{NonZero, NonZeroU16};
use std::rc::Rc;
use std::{fmt, ops};
use async_std::sync::RwLock;
use futures::task::LocalSpawn;
use hashbrown::HashMap;
use orchid_api::SysId;
use orchid_base::builtin::Spawner;
use orchid_base::interner::Interner;
use crate::api;
@@ -15,7 +15,7 @@ use crate::system::{System, WeakSystem};
pub struct CtxData {
pub i: Rc<Interner>,
pub spawn: Rc<dyn LocalSpawn>,
pub spawn: Spawner,
pub systems: RwLock<HashMap<api::SysId, WeakSystem>>,
pub system_id: RefCell<NonZeroU16>,
pub owned_atoms: RwLock<HashMap<api::AtomId, WeakAtomHand>>,
@@ -24,9 +24,18 @@ pub struct CtxData {
pub struct Ctx(Rc<CtxData>);
impl ops::Deref for Ctx {
type Target = CtxData;
fn deref(&self) -> &Self::Target { &*self.0 }
fn deref(&self) -> &Self::Target { &self.0 }
}
impl Ctx {
pub fn new(spawn: Spawner) -> Self {
Self(Rc::new(CtxData {
spawn,
i: Rc::default(),
systems: RwLock::default(),
system_id: RefCell::new(NonZero::new(1).unwrap()),
owned_atoms: RwLock::default(),
}))
}
pub(crate) async fn system_inst(&self, id: api::SysId) -> Option<System> {
self.systems.read().await.get(&id).and_then(WeakSystem::upgrade)
}

View File

@@ -1,7 +1,6 @@
use std::collections::VecDeque;
use std::num::NonZeroU64;
use std::rc::{Rc, Weak};
use std::sync::atomic::AtomicBool;
use async_std::sync::RwLock;
use futures::FutureExt;
@@ -19,7 +18,6 @@ pub type ExprParseCtx = Extension;
#[derive(Debug)]
pub struct ExprData {
is_canonical: AtomicBool,
pos: Pos,
kind: RwLock<ExprKind>,
}
@@ -51,7 +49,7 @@ impl Expr {
}
let pos = Pos::from_api(&api.location, &ctx.ctx().i).await;
let kind = RwLock::new(ExprKind::from_api(&api.kind, pos.clone(), ctx).boxed_local().await);
Self(Rc::new(ExprData { is_canonical: AtomicBool::new(false), pos, kind }))
Self(Rc::new(ExprData { pos, kind }))
}
pub async fn to_api(&self) -> api::InspectedKind {
use api::InspectedKind as K;

View File

@@ -9,7 +9,6 @@ use async_std::sync::Mutex;
use derive_destructure::destructure;
use futures::FutureExt;
use futures::future::{join, join_all};
use futures::task::LocalSpawnExt;
use hashbrown::HashMap;
use itertools::Itertools;
use orchid_api::HostMsgSet;
@@ -18,7 +17,6 @@ use orchid_base::builtin::ExtInit;
use orchid_base::clone;
use orchid_base::interner::Tok;
use orchid_base::logging::Logger;
use orchid_base::macros::mtreev_from_api;
use orchid_base::reqnot::{ReqNot, Requester as _};
use orchid_base::tree::AtomRepr;
@@ -26,7 +24,6 @@ use crate::api;
use crate::atom::AtomHand;
use crate::ctx::Ctx;
use crate::expr_store::ExprStore;
use crate::macros::{macro_recur, macro_treev_to_api};
use crate::system::SystemCtor;
pub struct ReqPair<R: Request>(R, Sender<R::Response>);
@@ -45,9 +42,13 @@ pub struct ExtensionData {
next_pars: RefCell<NonZeroU64>,
exprs: ExprStore,
lex_recur: Mutex<HashMap<api::ParsId, channel::Sender<ReqPair<api::SubLex>>>>,
mac_recur: Mutex<HashMap<api::ParsId, channel::Sender<ReqPair<api::RunMacros>>>>,
}
impl Drop for ExtensionData {
fn drop(&mut self) { self.reqnot.notify(api::HostExtNotif::Exit); }
fn drop(&mut self) {
let reqnot = self.reqnot.clone();
(self.ctx.spawn)(Box::pin(async move { reqnot.notify(api::HostExtNotif::Exit).await }))
}
}
#[derive(Clone)]
@@ -60,17 +61,19 @@ impl Extension {
systems: (init.systems.iter().cloned())
.map(|decl| SystemCtor { decl, ext: WeakExtension(weak.clone()) })
.collect(),
logger,
logger: logger.clone(),
init,
next_pars: RefCell::new(NonZeroU64::new(1).unwrap()),
lex_recur: Mutex::default(),
mac_recur: Mutex::default(),
reqnot: ReqNot::new(
logger,
clone!(weak; move |sfn, _| clone!(weak; async move {
let data = weak.upgrade().unwrap();
data.logger.log_buf("Downsending", sfn);
data.init.send(sfn).await
}.boxed_local())),
clone!(weak; move |notif, _| clone!(weak; async move {
clone!(weak; move |notif, _| {
clone!(weak; Box::pin(async move {
let this = Extension(weak.upgrade().unwrap());
match notif {
api::ExtHostNotif::ExprNotif(api::ExprNotif::Acquire(acq)) => {
@@ -90,12 +93,12 @@ impl Extension {
},
api::ExtHostNotif::Log(api::Log(str)) => this.logger().log(str),
}
}.boxed_local())),
}))}),
{
clone!(weak, ctx);
move |hand, req| {
clone!(weak, ctx);
async move {
Box::pin(async move {
let this = Self(weak.upgrade().unwrap());
let i = this.ctx().i.clone();
match req {
@@ -124,10 +127,12 @@ impl Extension {
hand.handle(fw, &sys.request(body.clone()).await).await
},
api::ExtHostReq::SubLex(sl) => {
let (rep_in, rep_out) = channel::bounded(0);
let lex_g = this.0.lex_recur.lock().await;
let req_in = lex_g.get(&sl.id).expect("Sublex for nonexistent lexid");
req_in.send(ReqPair(sl.clone(), rep_in)).await.unwrap();
let (rep_in, rep_out) = channel::bounded(1);
{
let lex_g = this.0.lex_recur.lock().await;
let req_in = lex_g.get(&sl.id).expect("Sublex for nonexistent lexid");
req_in.send(ReqPair(sl.clone(), rep_in)).await.unwrap();
}
hand.handle(&sl, &rep_out.recv().await.unwrap()).await
},
api::ExtHostReq::ExprReq(api::ExprReq::Inspect(ins @ api::Inspect { target })) => {
@@ -140,19 +145,17 @@ impl Extension {
})
.await
},
api::ExtHostReq::RunMacros(ref rm @ api::RunMacros { ref run_id, ref query }) => {
let mtreev =
mtreev_from_api(query, &i, &mut |_| panic!("Atom in macro recur")).await;
match macro_recur(*run_id, mtreev).await {
Some(x) => hand.handle(rm, &Some(macro_treev_to_api(*run_id, x).await)).await,
None => hand.handle(rm, &None).await,
}
api::ExtHostReq::RunMacros(rm) => {
let (rep_in, rep_out) = channel::bounded(1);
let lex_g = this.0.mac_recur.lock().await;
let req_in = lex_g.get(&rm.run_id).expect("Sublex for nonexistent lexid");
req_in.send(ReqPair(rm.clone(), rep_in)).await.unwrap();
hand.handle(&rm, &rep_out.recv().await.unwrap()).await
},
api::ExtHostReq::ExtAtomPrint(ref eap @ api::ExtAtomPrint(ref atom)) =>
hand.handle(eap, &AtomHand::new(atom.clone(), &ctx).await.print().await).await,
}
}
.boxed_local()
})
}
},
),
@@ -185,7 +188,7 @@ impl Extension {
// get unique lex ID
let id = api::ParsId(self.next_pars());
// create and register channel
let (req_in, req_out) = channel::bounded(0);
let (req_in, req_out) = channel::bounded(1);
self.0.lex_recur.lock().await.insert(id, req_in); // lex_recur released
let (ret, ()) = join(
async {
@@ -207,19 +210,15 @@ impl Extension {
}
pub async fn recv_one(&self) {
let reqnot = self.0.reqnot.clone();
self
.0
.init
.recv(Box::new(move |msg| async move { reqnot.receive(msg).await }.boxed_local()))
(self.0.init.recv(Box::new(move |msg| async move { reqnot.receive(msg).await }.boxed_local())))
.await;
}
pub fn system_drop(&self, id: api::SysId) {
let rc = self.clone();
(self.ctx().spawn.spawn_local(async move {
(self.ctx().spawn)(Box::pin(async move {
rc.reqnot().notify(api::SystemDrop(id)).await;
rc.ctx().systems.write().await.remove(&id);
}))
.expect("Failed to drop system!");
}
pub fn downgrade(&self) -> WeakExtension { WeakExtension(Rc::downgrade(&self.0)) }
}

View File

@@ -34,7 +34,7 @@ impl<'a> LexCtx<'a> {
tail: &self.source[pos as usize..],
systems: self.systems,
sub_trees: &mut *self.sub_trees,
ctx: &self.ctx,
ctx: self.ctx,
}
}
pub fn get_pos(&self) -> u32 { self.end_pos() - self.tail.len() as u32 }
@@ -76,7 +76,7 @@ impl<'a> LexCtx<'a> {
}
}
pub async fn lex_once<'a>(ctx: &mut LexCtx<'a>) -> OrcRes<ParsTokTree> {
pub async fn lex_once(ctx: &mut LexCtx<'_>) -> OrcRes<ParsTokTree> {
let start = ctx.get_pos();
assert!(
!ctx.tail.is_empty() && !ctx.tail.starts_with(unrep_space),
@@ -140,7 +140,7 @@ pub async fn lex_once<'a>(ctx: &mut LexCtx<'a>) -> OrcRes<ParsTokTree> {
let numstr = ctx.get_start_matches(|x| x != ')').trim();
match parse_num(numstr) {
Ok(num) => ParsTok::Macro(Some(num.to_f64())),
Err(e) => return Err(num_to_err(e, pos, &*ctx.ctx.i).await.into()),
Err(e) => return Err(num_to_err(e, pos, &ctx.ctx.i).await.into()),
}
} else {
ParsTok::Macro(None)
@@ -154,8 +154,9 @@ pub async fn lex_once<'a>(ctx: &mut LexCtx<'a>) -> OrcRes<ParsTokTree> {
let errors_lck = &Mutex::new(&mut errors);
let lx = sys
.lex(source, pos, |pos| async move {
match lex_once(&mut ctx_lck.lock().await.push(pos)).boxed_local().await {
Ok(t) => Some(api::SubLexed { pos, ticket: ctx_lck.lock().await.add_subtree(t) }),
let mut ctx_g = ctx_lck.lock().await;
match lex_once(&mut ctx_g.push(pos)).boxed_local().await {
Ok(t) => Some(api::SubLexed { pos, ticket: ctx_g.add_subtree(t) }),
Err(e) => {
errors_lck.lock().await.push(e);
None
@@ -166,9 +167,12 @@ pub async fn lex_once<'a>(ctx: &mut LexCtx<'a>) -> OrcRes<ParsTokTree> {
match lx {
Err(e) =>
return Err(
errors.into_iter().fold(OrcErrv::from_api(&e, &*ctx.ctx.i).await, |a, b| a + b),
errors.into_iter().fold(OrcErrv::from_api(&e, &ctx.ctx.i).await, |a, b| a + b),
),
Ok(Some(lexed)) => return Ok(tt_to_owned(&lexed.expr, &mut ctx.push(lexed.pos)).await),
Ok(Some(lexed)) => {
ctx.set_pos(lexed.pos);
return Ok(tt_to_owned(&lexed.expr, ctx).await);
},
Ok(None) => match errors.into_iter().reduce(|a, b| a + b) {
Some(errors) => return Err(errors),
None => continue,
@@ -196,13 +200,13 @@ async fn tt_to_owned(api: &api::TokenTree, ctx: &mut LexCtx<'_>) -> ParsTokTree
Atom(atom =>
AtomHand::from_api(atom, Pos::Range(api.range.clone()), &mut ctx.ctx.clone()).await
),
Bottom(err => OrcErrv::from_api(err, &*ctx.ctx.i).await),
Bottom(err => OrcErrv::from_api(err, &ctx.ctx.i).await),
LambdaHead(arg => ttv_to_owned(arg, ctx).boxed_local().await),
Name(name => Tok::from_api(*name, &*ctx.ctx.i).await),
Name(name => Tok::from_api(*name, &ctx.ctx.i).await),
S(p.clone(), b => ttv_to_owned(b, ctx).boxed_local().await),
BR, NS,
Comment(c.clone()),
Ph(ph => Ph::from_api(ph, &*ctx.ctx.i).await),
Ph(ph => Ph::from_api(ph, &ctx.ctx.i).await),
Macro(*prio),
} {
api::Token::Slot(id) => return ctx.rm_subtree(*id),
@@ -216,7 +220,7 @@ async fn ttv_to_owned<'a>(
) -> Vec<ParsTokTree> {
let mut out = Vec::new();
for tt in api {
out.push(tt_to_owned(&tt, ctx).await)
out.push(tt_to_owned(tt, ctx).await)
}
out
}

View File

@@ -1,17 +1,16 @@
use std::rc::Rc;
use async_std::sync::RwLock;
use futures::FutureExt;
use hashbrown::{HashMap, HashSet};
use itertools::Itertools;
use orchid_base::interner::Interner;
use orchid_base::clone;
use orchid_base::macros::{MTok, MTree, mtreev_from_api, mtreev_to_api};
use orchid_base::name::Sym;
use trait_set::trait_set;
use crate::api;
use crate::atom::AtomHand;
use crate::rule::matcher::{NamedMatcher, PriodMatcher};
use crate::ctx::Ctx;
use crate::rule::state::MatchState;
use crate::tree::Code;
@@ -22,36 +21,27 @@ trait_set! {
trait MacroCB = Fn(Vec<MacTree>) -> Option<Vec<MacTree>>;
}
thread_local! {
static RECURSION: RwLock<HashMap<api::ParsId, Box<dyn MacroCB>>> = RwLock::default();
static MACRO_SLOTS: RwLock<HashMap<api::ParsId, HashMap<api::MacroTreeId, Rc<MacTok>>>> =
RwLock::default();
}
type Slots = HashMap<api::MacroTreeId, Rc<MacTok>>;
pub async fn macro_recur(run_id: api::ParsId, input: Vec<MacTree>) -> Option<Vec<MacTree>> {
(RECURSION.read().unwrap()[&run_id])(input)
}
pub async fn macro_treev_to_api(run_id: api::ParsId, mtree: Vec<MacTree>) -> Vec<api::MacroTree> {
let mut g = MACRO_SLOTS.write().unwrap();
let run_cache = g.get_mut(&run_id).expect("Parser run not found");
pub async fn macro_treev_to_api(mtree: Vec<MacTree>, slots: &mut Slots) -> Vec<api::MacroTree> {
mtreev_to_api(&mtree, &mut |a: &AtomHand| {
let id = api::MacroTreeId((run_cache.len() as u64 + 1).try_into().unwrap());
run_cache.insert(id, Rc::new(MacTok::Atom(a.clone())));
api::MacroToken::Slot(id)
})
}
pub async fn macro_treev_from_api(api: Vec<api::MacroTree>, i: &Interner) -> Vec<MacTree> {
mtreev_from_api(&api, i, &mut |atom| {
async { MacTok::Atom(AtomHand::from_api(atom.clone())) }.boxed_local()
let id = api::MacroTreeId((slots.len() as u64 + 1).try_into().unwrap());
slots.insert(id, Rc::new(MacTok::Atom(a.clone())));
async move { api::MacroToken::Slot(id) }.boxed_local()
})
.await
}
pub fn deslot_macro(run_id: api::ParsId, tree: &[MacTree]) -> Option<Vec<MacTree>> {
let mut slots = (MACRO_SLOTS.write().unwrap()).remove(&run_id).expect("Run not found");
return work(&mut slots, tree);
pub async fn macro_treev_from_api(api: Vec<api::MacroTree>, ctx: Ctx) -> Vec<MacTree> {
mtreev_from_api(&api, &ctx.clone().i, &mut move |atom| {
clone!(ctx);
Box::pin(async move { MacTok::Atom(AtomHand::new(atom.clone(), &ctx).await) })
})
.await
}
pub fn deslot_macro(tree: &[MacTree], slots: &mut Slots) -> Option<Vec<MacTree>> {
return work(slots, tree);
fn work(
slots: &mut HashMap<api::MacroTreeId, Rc<MacTok>>,
tree: &[MacTree],
@@ -90,74 +80,6 @@ pub struct Macro<Matcher> {
cases: Vec<(Matcher, Code)>,
}
pub struct MacroRepo {
named: HashMap<Sym, Vec<Macro<NamedMatcher>>>,
prio: Vec<Macro<PriodMatcher>>,
}
impl MacroRepo {
/// TODO: the recursion inside this function needs to be moved into Orchid.
/// See the markdown note
pub fn process_exprv(&self, target: &[MacTree], i: &Interner) -> Option<Vec<MacTree>> {
let mut workcp = target.to_vec();
let mut lexicon;
'try_named: loop {
lexicon = HashSet::new();
target.iter().for_each(|tgt| fill_lexicon(tgt, &mut lexicon));
for (idx, tree) in workcp.iter().enumerate() {
let MacTok::Name(name) = &*tree.tok else { continue };
let matches = (self.named.get(name).into_iter().flatten())
.filter(|m| m.deps.is_subset(&lexicon))
.filter_map(|mac| {
(mac.cases.iter())
.find_map(|cas| cas.0.apply(&workcp[idx..], i, |_| false).map(|s| (cas, s)))
})
.collect_vec();
assert!(
matches.len() < 2,
"Multiple conflicting matches on {:?}: {:?}",
&workcp[idx..],
matches
);
let Some((case, (state, tail))) = matches.into_iter().next() else { continue };
let inj = (run_body(&case.1, state).into_iter())
.map(|MacTree { pos, tok }| MacTree { pos, tok: Rc::new(MacTok::Done(tok)) });
workcp.splice(idx..(workcp.len() - tail.len()), inj);
continue 'try_named;
}
break;
}
if let Some(((_, body), state)) = (self.prio.iter())
.filter(|mac| mac.deps.is_subset(&lexicon))
.flat_map(|mac| &mac.cases)
.find_map(|case| case.0.apply(&workcp, |_| false).map(|state| (case, state)))
{
return Some(run_body(body, state));
}
let results = (workcp.into_iter())
.map(|mt| match &*mt.tok {
MTok::S(p, body) => self.process_exprv(body, i).map(|body| MTok::S(*p, body).at(mt.pos)),
MTok::Lambda(arg, body) =>
match (self.process_exprv(arg, i), self.process_exprv(body, i)) {
(Some(arg), Some(body)) => Some(MTok::Lambda(arg, body).at(mt.pos)),
(Some(arg), None) => Some(MTok::Lambda(arg, body.to_vec()).at(mt.pos)),
(None, Some(body)) => Some(MTok::Lambda(arg.to_vec(), body).at(mt.pos)),
(None, None) => None,
},
_ => None,
})
.collect_vec();
results.iter().any(Option::is_some).then(|| {
(results.into_iter().zip(target))
.map(|(opt, fb)| opt.unwrap_or_else(|| fb.clone()))
.collect_vec()
})
}
}
fn fill_lexicon(tgt: &MacTree, lexicon: &mut HashSet<Sym>) {
match &*tgt.tok {
MTok::Name(n) => {

View File

@@ -4,7 +4,7 @@ use futures::FutureExt;
use futures::future::join_all;
use itertools::Itertools;
use never::Never;
use orchid_base::error::{OrcErrv, OrcRes, Reporter, mk_err, mk_errv};
use orchid_base::error::{OrcErrv, OrcRes, Reporter, ReporterImpl, mk_err, mk_errv};
use orchid_base::interner::Tok;
use orchid_base::location::Pos;
use orchid_base::macros::{MTok, MTree};
@@ -25,9 +25,19 @@ use crate::tree::{
type ParsSnippet<'a> = Snippet<'a, 'static, AtomHand, Never>;
pub trait ParseCtx: Send + Sync {
pub struct ParseCtxImpl<'a> {
pub systems: &'a [System],
pub reporter: &'a ReporterImpl,
}
impl ParseCtx for ParseCtxImpl<'_> {
fn reporter(&self) -> &(impl Reporter + ?Sized) { self.reporter }
fn systems(&self) -> impl Iterator<Item = &System> { self.systems.iter() }
}
pub trait ParseCtx {
fn systems(&self) -> impl Iterator<Item = &System>;
fn reporter(&self) -> &impl Reporter;
fn reporter(&self) -> &(impl Reporter + ?Sized);
}
pub async fn parse_items(
@@ -239,8 +249,8 @@ pub async fn parse_mtree(mut snip: ParsSnippet<'_>) -> OrcRes<Vec<MacTree>> {
Token::LambdaHead(arg) => (
ttree.range.start..snip.pos().end,
MTok::Lambda(
parse_mtree(Snippet::new(ttree, arg, snip.interner())).await?,
parse_mtree(tail).await?,
parse_mtree(Snippet::new(ttree, arg, snip.interner())).boxed_local().await?,
parse_mtree(tail).boxed_local().await?,
),
Snippet::new(ttree, &[], snip.interner()),
),
@@ -272,7 +282,7 @@ pub async fn parse_macro(
let mut errors = Vec::new();
let mut rules = Vec::new();
for (i, item) in
line_items(Snippet::new(&prev, block, tail.interner())).await.into_iter().enumerate()
line_items(Snippet::new(prev, block, tail.interner())).await.into_iter().enumerate()
{
let Parsed { tail, output } = try_pop_no_fluff(item.tail).await?;
if !output.is_kw(tail.i("rule").await) {

View File

@@ -20,7 +20,7 @@ pub fn scal_match<'a>(
(ScalMatcher::Placeh { key }, _) =>
Some(MatchState::from_ph(key.clone(), StateEntry::Scalar(expr))),
(ScalMatcher::S(c1, b_mat), MacTok::S(c2, body)) if c1 == c2 =>
any_match(&b_mat, &body[..], save_loc),
any_match(b_mat, &body[..], save_loc),
(ScalMatcher::Lambda(arg_mat, b_mat), MacTok::Lambda(arg, body)) =>
Some(any_match(arg_mat, arg, save_loc)?.combine(any_match(b_mat, body, save_loc)?)),
_ => None,

View File

@@ -1,7 +1,6 @@
use std::cell::RefCell;
use std::path::PathBuf;
use std::pin::Pin;
use std::rc::Rc;
use std::thread;
use async_process::{self, Child, ChildStdin, ChildStdout};
@@ -9,7 +8,6 @@ use async_std::io::{self, BufReadExt, BufReader};
use async_std::sync::Mutex;
use futures::FutureExt;
use futures::future::LocalBoxFuture;
use futures::task::LocalSpawnExt;
use orchid_api_traits::{Decode, Encode};
use orchid_base::builtin::{ExtInit, ExtPort};
use orchid_base::logging::Logger;
@@ -31,7 +29,7 @@ pub async fn ext_command(
.stderr(async_process::Stdio::piped())
.spawn()?;
let mut stdin = child.stdin.take().unwrap();
api::HostHeader { log_strategy: logger.strat() }.encode(Pin::new(&mut stdin));
api::HostHeader { log_strategy: logger.strat() }.encode(Pin::new(&mut stdin)).await;
let mut stdout = child.stdout.take().unwrap();
let header = api::ExtensionHeader::decode(Pin::new(&mut stdout)).await;
let child_stderr = child.stderr.take().unwrap();
@@ -50,7 +48,7 @@ pub async fn ext_command(
Ok(ExtInit {
header,
port: Box::new(Subprocess {
child: Rc::new(RefCell::new(child)),
child: RefCell::new(Some(child)),
stdin: Mutex::new(Box::pin(stdin)),
stdout: Mutex::new(Box::pin(stdout)),
ctx,
@@ -59,19 +57,18 @@ pub async fn ext_command(
}
pub struct Subprocess {
child: Rc<RefCell<Child>>,
child: RefCell<Option<Child>>,
stdin: Mutex<Pin<Box<ChildStdin>>>,
stdout: Mutex<Pin<Box<ChildStdout>>>,
ctx: Ctx,
}
impl Drop for Subprocess {
fn drop(&mut self) {
let child = self.child.clone();
(self.ctx.spawn.spawn_local(async move {
let status = child.borrow_mut().status().await.expect("Extension exited with error");
let mut child = self.child.borrow_mut().take().unwrap();
(self.ctx.spawn)(Box::pin(async move {
let status = child.status().await.expect("Extension exited with error");
assert!(status.success(), "Extension exited with error {status}");
}))
.expect("Could not spawn process terminating future")
}
}
impl ExtPort for Subprocess {

View File

@@ -7,7 +7,6 @@ use async_stream::stream;
use derive_destructure::destructure;
use futures::StreamExt;
use futures::future::join_all;
use futures::task::LocalSpawnExt;
use hashbrown::HashMap;
use itertools::Itertools;
use orchid_base::async_once_cell::OnceCell;
@@ -57,7 +56,7 @@ impl System {
pub fn id(&self) -> api::SysId { self.0.id }
pub fn ext(&self) -> &Extension { &self.0.ext }
pub fn ctx(&self) -> &Ctx { &self.0.ctx }
pub(crate) fn reqnot(&self) -> &ReqNot<api::HostMsgSet> { &self.0.ext.reqnot() }
pub(crate) fn reqnot(&self) -> &ReqNot<api::HostMsgSet> { self.0.ext.reqnot() }
pub async fn get_tree(&self, id: api::TreeId) -> api::MemberKind {
self.reqnot().request(api::GetMember(self.0.id, id)).await
}
@@ -94,10 +93,9 @@ impl System {
}
pub(crate) fn drop_atom(&self, drop: api::AtomId) {
let this = self.0.clone();
(self.0.ctx.spawn.spawn_local(async move {
(self.0.ctx.spawn)(Box::pin(async move {
this.ctx.owned_atoms.write().await.remove(&drop);
}))
.expect("Failed to drop atom");
}
pub async fn print(&self) -> String {
let ctor = (self.0.ext.system_ctors().find(|c| c.id() == self.0.decl_id))