task_local context over context objects

- interner impls logically separate from API in orchid-base (default host interner still in base for testing)
- error reporting, logging, and a variety of other features passed down via context in extension, not yet in host to maintain library-ish profile, should consider options
- no global spawn mechanic, the host has a spawn function but extensions only get a stash for enqueuing async work in sync callbacks which is then explicitly, manually, and with strict order popped and awaited
- still deadlocks nondeterministically for some ungodly reason
This commit is contained in:
2026-01-01 14:54:29 +00:00
parent 06debb3636
commit 32d6237dc5
92 changed files with 2507 additions and 2223 deletions

View File

@@ -2,17 +2,16 @@ use futures::FutureExt;
use futures::future::join_all;
use itertools::Itertools;
use orchid_base::error::{OrcRes, mk_errv};
use orchid_base::interner::Tok;
use orchid_base::interner::{IStr, is};
use orchid_base::join_ok;
use orchid_base::side::Side;
use orchid_extension::context::i;
use super::shared::{AnyMatcher, ScalMatcher, VecMatcher};
use super::vec_attrs::vec_attrs;
use crate::macros::mactree::{Ph, PhKind};
use crate::macros::{MacTok, MacTree};
pub type MaxVecSplit<'a> = (&'a [MacTree], (Tok<String>, u8, bool), &'a [MacTree]);
pub type MaxVecSplit<'a> = (&'a [MacTree], (IStr, u8, bool), &'a [MacTree]);
/// Derive the details of the central vectorial and the two sides from a
/// slice of Expr's
@@ -126,7 +125,7 @@ async fn mk_scalar(pattern: &MacTree) -> OrcRes<ScalMatcher> {
MacTok::S(c, body) => ScalMatcher::S(*c, Box::new(mk_any(&body.items).boxed_local().await?)),
MacTok::Lambda(..) =>
return Err(mk_errv(
i().i("Lambda in matcher").await,
is("Lambda in matcher").await,
"Lambdas can't be matched for, only generated in templates",
[pattern.pos()],
)),
@@ -137,10 +136,11 @@ async fn mk_scalar(pattern: &MacTree) -> OrcRes<ScalMatcher> {
#[cfg(test)]
mod test {
use orchid_base::interner::local_interner::local_interner;
use orchid_base::interner::{is, with_interner};
use orchid_base::location::SrcRange;
use orchid_base::sym;
use orchid_base::tokens::Paren;
use orchid_extension::context::{i, mock_ctx, with_ctx};
use test_executors::spin_on;
use super::mk_any;
@@ -149,27 +149,27 @@ mod test {
#[test]
fn test_scan() {
spin_on(with_ctx(mock_ctx(), async {
let ex = |tok: MacTok| async { tok.at(SrcRange::mock(&i()).await.pos()) };
spin_on(with_interner(local_interner(), async {
let ex = |tok: MacTok| async { tok.at(SrcRange::mock().await.pos()) };
let pattern = vec![
ex(MacTok::Ph(Ph {
kind: PhKind::Vector { priority: 0, at_least_one: false },
name: i().i("::prefix").await,
name: is("::prefix").await,
}))
.await,
ex(MacTok::Name(sym!(prelude::do; i()))).await,
ex(MacTok::Name(sym!(prelude::do))).await,
ex(MacTok::S(
Paren::Round,
MacTreeSeq::new([
ex(MacTok::Ph(Ph {
kind: PhKind::Vector { priority: 0, at_least_one: false },
name: i().i("expr").await,
name: is("expr").await,
}))
.await,
ex(MacTok::Name(sym!(prelude::; ; i()))).await,
ex(MacTok::Name(sym!(prelude::;))).await,
ex(MacTok::Ph(Ph {
kind: PhKind::Vector { priority: 1, at_least_one: false },
name: i().i("rest").await,
name: is("rest").await,
}))
.await,
]),
@@ -177,7 +177,7 @@ mod test {
.await,
ex(MacTok::Ph(Ph {
kind: PhKind::Vector { priority: 0, at_least_one: false },
name: i().i("::suffix").await,
name: is("::suffix").await,
}))
.await,
];

View File

@@ -2,8 +2,8 @@ use std::fmt;
use std::rc::Rc;
use orchid_base::error::OrcRes;
use orchid_base::interner::is;
use orchid_base::name::Sym;
use orchid_extension::context::i;
use super::any_match::any_match;
use super::build::mk_any;
@@ -24,12 +24,12 @@ impl Matcher {
let first = pattern.first().expect("Empty pattern is not allowed");
if vec_attrs(first).is_none() {
let pos = first.pos();
pattern.insert(0, MacTok::Ph(Ph { name: i().i("::before").await, kind }).at(pos));
pattern.insert(0, MacTok::Ph(Ph { name: is("::before").await, kind }).at(pos));
}
let last = pattern.last().expect("first returned Some above");
if vec_attrs(last).is_none() {
let pos = last.pos();
pattern.insert(0, MacTok::Ph(Ph { name: i().i("::after").await, kind }).at(pos));
pattern.insert(0, MacTok::Ph(Ph { name: is("::after").await, kind }).at(pos));
}
Ok(Matcher { inner: mk_any(&pattern).await? })
}
@@ -42,7 +42,7 @@ impl Matcher {
) -> Option<(&'a [MacTree], MatchState<'a>, &'a [MacTree])> {
let mut result = any_match(&self.inner, seq, &save_loc)?;
async fn remove_frame<'a>(result: &mut MatchState<'a>, key: &str) -> &'a [MacTree] {
match result.remove(i().i(key).await) {
match result.remove(is(key).await) {
Some(StateEntry::Scalar(_)) => panic!("{key} is defined in the constructor as a Vec"),
Some(StateEntry::Vec(v)) => v,
None => &[],

View File

@@ -3,7 +3,7 @@
use std::fmt;
use itertools::Itertools;
use orchid_base::interner::Tok;
use orchid_base::interner::IStr;
use orchid_base::name::Sym;
use orchid_base::side::Side;
use orchid_base::tokens::{PARENS, Paren};
@@ -11,12 +11,12 @@ use orchid_base::tokens::{PARENS, Paren};
pub enum ScalMatcher {
Name(Sym),
S(Paren, Box<AnyMatcher>),
Placeh { key: Tok<String> },
Placeh { key: IStr },
}
pub enum VecMatcher {
Placeh {
key: Tok<String>,
key: IStr,
nonzero: bool,
},
Scan {
@@ -41,7 +41,7 @@ pub enum VecMatcher {
/// the length of matches on either side.
///
/// Vectorial keys that appear on either side, in priority order
key_order: Vec<Tok<String>>,
key_order: Vec<IStr>,
},
}

View File

@@ -2,7 +2,7 @@
use std::any::Any;
use hashbrown::HashMap;
use orchid_base::interner::Tok;
use orchid_base::interner::IStr;
use orchid_base::join::join_maps;
use orchid_base::location::Pos;
use orchid_base::match_mapping;
@@ -30,11 +30,11 @@ pub enum StateEntry<'a> {
}
#[derive(Clone, Debug)]
pub struct MatchState<'a> {
placeholders: HashMap<Tok<String>, StateEntry<'a>>,
placeholders: HashMap<IStr, StateEntry<'a>>,
name_posv: HashMap<Sym, Vec<Pos>>,
}
impl<'a> MatchState<'a> {
pub fn from_ph(key: Tok<String>, entry: StateEntry<'a>) -> Self {
pub fn from_ph(key: IStr, entry: StateEntry<'a>) -> Self {
Self { placeholders: HashMap::from([(key, entry)]), name_posv: HashMap::new() }
}
pub fn combine(self, s: Self) -> Self {
@@ -45,7 +45,7 @@ impl<'a> MatchState<'a> {
}),
}
}
pub fn ph_len(&self, key: &Tok<String>) -> Option<usize> {
pub fn ph_len(&self, key: &IStr) -> Option<usize> {
match self.placeholders.get(key)? {
StateEntry::Vec(slc) => Some(slc.len()),
_ => None,
@@ -57,10 +57,8 @@ impl<'a> MatchState<'a> {
pub fn names(&self) -> impl Iterator<Item = (Sym, &[Pos])> {
self.name_posv.iter().map(|(sym, vec)| (sym.clone(), &vec[..]))
}
pub fn get(&self, key: &Tok<String>) -> Option<&StateEntry<'a>> { self.placeholders.get(key) }
pub fn remove(&mut self, name: Tok<String>) -> Option<StateEntry<'a>> {
self.placeholders.remove(&name)
}
pub fn get(&self, key: &IStr) -> Option<&StateEntry<'a>> { self.placeholders.get(key) }
pub fn remove(&mut self, name: IStr) -> Option<StateEntry<'a>> { self.placeholders.remove(&name) }
pub fn mk_owned(self) -> OwnedState {
OwnedState {
placeholders: (self.placeholders.into_iter())
@@ -88,10 +86,10 @@ pub enum OwnedEntry {
Scalar(MacTree),
}
pub struct OwnedState {
placeholders: HashMap<Tok<String>, OwnedEntry>,
placeholders: HashMap<IStr, OwnedEntry>,
name_posv: HashMap<Sym, Vec<Pos>>,
}
impl OwnedState {
pub fn get(&self, key: &Tok<String>) -> Option<&OwnedEntry> { self.placeholders.get(key) }
pub fn get(&self, key: &IStr) -> Option<&OwnedEntry> { self.placeholders.get(key) }
pub fn positions(&self, name: &Sym) -> &[Pos] { self.name_posv.get(name).map_or(&[], |v| &v[..]) }
}

View File

@@ -1,4 +1,4 @@
use orchid_base::interner::Tok;
use orchid_base::interner::IStr;
use crate::macros::mactree::{Ph, PhKind};
use crate::macros::{MacTok, MacTree};
@@ -6,7 +6,7 @@ use crate::macros::{MacTok, MacTree};
/// Returns the name, priority and at_least_one of the expression if it is
/// a vectorial placeholder
#[must_use]
pub fn vec_attrs(expr: &MacTree) -> Option<(Tok<String>, u8, bool)> {
pub fn vec_attrs(expr: &MacTree) -> Option<(IStr, u8, bool)> {
match (*expr.tok).clone() {
MacTok::Ph(Ph { kind: PhKind::Vector { priority, at_least_one }, name }) =>
Some((name, priority, at_least_one)),