New macro system and stdlib additions

This commit is contained in:
2025-11-21 14:25:03 +01:00
parent b77653f841
commit 603efef28e
230 changed files with 3033 additions and 16640 deletions

View File

@@ -1,87 +1,61 @@
use std::fmt;
use std::rc::Rc;
use itertools::Itertools;
use orchid_base::error::OrcRes;
use orchid_base::interner::{Interner, Tok};
use orchid_base::location::Pos;
use orchid_base::name::Sym;
use orchid_extension::context::i;
use super::any_match::any_match;
use super::build::{mk_any, mk_vec};
use super::shared::{AnyMatcher, VecMatcher};
use super::build::mk_any;
use super::shared::AnyMatcher;
use super::state::{MatchState, StateEntry};
use super::vec_attrs::vec_attrs;
use super::vec_match::vec_match;
use crate::macros::mactree::{Ph, PhKind};
use crate::macros::mactree::{MacTreeSeq, Ph, PhKind};
use crate::macros::{MacTok, MacTree};
pub struct NamedMatcher {
pub struct Matcher {
inner: AnyMatcher,
head: Sym,
after_tok: Tok<String>,
}
impl NamedMatcher {
pub async fn new(pattern: &[MacTree], i: &Interner) -> OrcRes<Self> {
let head = match pattern.first().map(|tree| tree.tok()) {
Some(MacTok::Name(name)) => name.clone(),
_ => panic!("Named matchers must begin with a name"),
};
let after_tok = i.i("::after").await;
let inner = match pattern.last().and_then(vec_attrs).is_some() {
true => mk_any(pattern, i).await?,
false => {
let kind = PhKind::Vector { priority: 0, at_least_one: false };
let suffix = [MacTok::Ph(Ph { name: after_tok.clone(), kind }).at(Pos::None)];
mk_any(&pattern.iter().cloned().chain(suffix).collect_vec(), i).await?
},
};
Ok(Self { after_tok, inner, head })
}
pub fn head(&self) -> Sym { self.head.clone() }
/// Also returns the tail, if any, which should be matched further
/// Note that due to how priod works below, the main usable information from
/// the tail is its length
pub fn apply<'a>(
&self,
seq: &'a [MacTree],
save_loc: impl Fn(Sym) -> bool,
) -> Option<(MatchState<'a>, &'a [MacTree])> {
let mut state = any_match(&self.inner, seq, &save_loc)?;
match state.remove(self.after_tok.clone()) {
Some(StateEntry::Scalar(_)) => panic!("{} can never be a scalar entry!", self.after_tok),
Some(StateEntry::Vec(v)) => Some((state, v)),
None => Some((state, &[][..])),
}
}
}
impl fmt::Display for NamedMatcher {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) }
}
impl fmt::Debug for NamedMatcher {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "NamedMatcher({self})") }
}
pub struct PriodMatcher(VecMatcher);
impl PriodMatcher {
pub async fn new(pattern: &[MacTree], i: &Interner) -> OrcRes<Self> {
assert!(
pattern.first().and_then(vec_attrs).is_some() && pattern.last().and_then(vec_attrs).is_some(),
"Prioritized matchers must start and end with a vectorial",
);
Ok(Self(mk_vec(pattern, i).await?))
impl Matcher {
pub async fn new(pattern: MacTreeSeq) -> OrcRes<Self> {
let mut pattern = Rc::unwrap_or_clone(pattern.items);
let kind = PhKind::Vector { at_least_one: false, priority: 0 };
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));
}
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));
}
Ok(Matcher { inner: mk_any(&pattern).await? })
}
/// tokens before the offset always match the prefix
pub fn apply<'a>(
/// Also returns the head and tail, which should be matched by overarching
/// matchers attempted later.
pub async fn apply<'a>(
&self,
seq: &'a [MacTree],
save_loc: impl Fn(Sym) -> bool,
) -> Option<MatchState<'a>> {
vec_match(&self.0, seq, &save_loc)
save_loc: &dyn Fn(Sym) -> bool,
) -> 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) {
Some(StateEntry::Scalar(_)) => panic!("{key} is defined in the constructor as a Vec"),
Some(StateEntry::Vec(v)) => v,
None => &[],
}
}
let before = remove_frame(&mut result, "::before").await;
let after = remove_frame(&mut result, "::after").await;
Some((before, result, after))
}
}
impl fmt::Display for PriodMatcher {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) }
impl fmt::Display for Matcher {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) }
}
impl fmt::Debug for PriodMatcher {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "PriodMatcher({self})") }
impl fmt::Debug for Matcher {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "NamedMatcher({self})") }
}