base and extension fully compiles, host in good shape

This commit is contained in:
2025-01-25 00:10:49 +01:00
parent 7be8716b19
commit 2b79e96dc9
49 changed files with 1719 additions and 1168 deletions

View File

@@ -1,14 +1,16 @@
use std::sync::{Arc, RwLock};
use std::rc::Rc;
use async_std::sync::RwLock;
use futures::FutureExt;
use hashbrown::{HashMap, HashSet};
use itertools::Itertools;
use lazy_static::lazy_static;
use orchid_base::interner::Interner;
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::extension::AtomHand;
use crate::atom::AtomHand;
use crate::rule::matcher::{NamedMatcher, PriodMatcher};
use crate::rule::state::MatchState;
use crate::tree::Code;
@@ -17,38 +19,41 @@ pub type MacTok = MTok<'static, AtomHand>;
pub type MacTree = MTree<'static, AtomHand>;
trait_set! {
trait MacroCB = Fn(Vec<MacTree>) -> Option<Vec<MacTree>> + Send + Sync;
trait MacroCB = Fn(Vec<MacTree>) -> Option<Vec<MacTree>>;
}
lazy_static! {
static ref RECURSION: RwLock<HashMap<api::ParsId, Box<dyn MacroCB>>> = RwLock::default();
static ref MACRO_SLOTS: RwLock<HashMap<api::ParsId, HashMap<api::MacroTreeId, Arc<MacTok>>>> =
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();
}
pub fn macro_recur(run_id: api::ParsId, input: Vec<MacTree>) -> Option<Vec<MacTree>> {
pub async fn macro_recur(run_id: api::ParsId, input: Vec<MacTree>) -> Option<Vec<MacTree>> {
(RECURSION.read().unwrap()[&run_id])(input)
}
pub fn macro_treev_to_api(run_id: api::ParsId, mtree: Vec<MacTree>) -> Vec<api::MacroTree> {
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");
mtreev_to_api(&mtree, &mut |a: &AtomHand| {
let id = api::MacroTreeId((run_cache.len() as u64 + 1).try_into().unwrap());
run_cache.insert(id, Arc::new(MacTok::Atom(a.clone())));
run_cache.insert(id, Rc::new(MacTok::Atom(a.clone())));
api::MacroToken::Slot(id)
})
}
pub fn macro_treev_from_api(api: Vec<api::MacroTree>) -> Vec<MacTree> {
mtreev_from_api(&api, &mut |atom| MacTok::Atom(AtomHand::from_api(atom.clone())))
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()
})
.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);
fn work(
slots: &mut HashMap<api::MacroTreeId, Arc<MacTok>>,
slots: &mut HashMap<api::MacroTreeId, Rc<MacTok>>,
tree: &[MacTree],
) -> Option<Vec<MacTree>> {
let items = (tree.iter())
@@ -59,8 +64,8 @@ pub fn deslot_macro(run_id: api::ParsId, tree: &[MacTree]) -> Option<Vec<MacTree
MacTok::Ref(_) => panic!("Ref is an extension-local optimization"),
MacTok::Done(_) => panic!("Created and removed by matcher"),
MacTok::Slot(slot) => slots.get(&slot.id()).expect("Slot not found").clone(),
MacTok::S(paren, b) => Arc::new(MacTok::S(*paren, work(slots, b)?)),
MacTok::Lambda(a, b) => Arc::new(match (work(slots, a), work(slots, b)) {
MacTok::S(paren, b) => Rc::new(MacTok::S(*paren, work(slots, b)?)),
MacTok::Lambda(a, b) => Rc::new(match (work(slots, a), work(slots, b)) {
(None, None) => return None,
(Some(a), None) => MacTok::Lambda(a, b.clone()),
(None, Some(b)) => MacTok::Lambda(a.clone(), b),
@@ -92,7 +97,7 @@ pub struct MacroRepo {
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]) -> Option<Vec<MacTree>> {
pub fn process_exprv(&self, target: &[MacTree], i: &Interner) -> Option<Vec<MacTree>> {
let mut workcp = target.to_vec();
let mut lexicon;
@@ -100,24 +105,25 @@ impl MacroRepo {
lexicon = HashSet::new();
target.iter().for_each(|tgt| fill_lexicon(tgt, &mut lexicon));
for (i, tree) in workcp.iter().enumerate() {
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[i..], |_| false).map(|s| (cas, s)))
(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[i..],
&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: Arc::new(MacTok::Done(tok)) });
workcp.splice(i..(workcp.len() - tail.len()), inj);
.map(|MacTree { pos, tok }| MacTree { pos, tok: Rc::new(MacTok::Done(tok)) });
workcp.splice(idx..(workcp.len() - tail.len()), inj);
continue 'try_named;
}
break;
@@ -133,13 +139,14 @@ impl MacroRepo {
let results = (workcp.into_iter())
.map(|mt| match &*mt.tok {
MTok::S(p, body) => self.process_exprv(body).map(|body| MTok::S(*p, body).at(mt.pos)),
MTok::Lambda(arg, body) => match (self.process_exprv(arg), self.process_exprv(body)) {
(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,
},
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();
@@ -169,6 +176,6 @@ fn run_body(body: &Code, mut state: MatchState<'_>) -> Vec<MacTree> {
let inject: Vec<MacTree> = todo!("Call the interpreter with bindings");
inject
.into_iter()
.map(|MTree { pos, tok }| MTree { pos, tok: Arc::new(MTok::Done(tok)) })
.map(|MTree { pos, tok }| MTree { pos, tok: Rc::new(MTok::Done(tok)) })
.collect_vec()
}