lex_hello worked for a second just now
this is just a backup however
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user