Macro system done in theory
too afraid to begin debugging, resting for a moment
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::OrcRes;
|
||||
use orchid_base::interner::Interner;
|
||||
use orchid_base::interner::{Interner, Tok};
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::name::Sym;
|
||||
|
||||
@@ -16,46 +15,47 @@ use super::vec_match::vec_match;
|
||||
use crate::macros::mactree::{Ph, PhKind};
|
||||
use crate::macros::{MacTok, MacTree};
|
||||
|
||||
pub fn first_is_vec(pattern: &[MacTree]) -> bool { vec_attrs(pattern.first().unwrap()).is_some() }
|
||||
pub fn last_is_vec(pattern: &[MacTree]) -> bool { vec_attrs(pattern.last().unwrap()).is_some() }
|
||||
|
||||
pub struct NamedMatcher(AnyMatcher);
|
||||
pub struct NamedMatcher {
|
||||
inner: AnyMatcher,
|
||||
head: Sym,
|
||||
after_tok: Tok<String>,
|
||||
}
|
||||
impl NamedMatcher {
|
||||
pub async fn new(pattern: &[MacTree], i: &Interner) -> OrcRes<Self> {
|
||||
assert!(
|
||||
matches!(pattern.first().map(|tree| &*tree.tok), Some(MacTok::Name(_))),
|
||||
"Named matchers must begin with a name"
|
||||
);
|
||||
|
||||
Ok(Self(match last_is_vec(pattern) {
|
||||
true => mk_any(pattern, i).await,
|
||||
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 tok = MacTok::Ph(Ph { name: i.i("::after").await, kind });
|
||||
let suffix = [MacTree { pos: Pos::None, tok: Rc::new(tok) }];
|
||||
mk_any(&pattern.iter().chain(&suffix).cloned().collect_vec(), i).await
|
||||
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 async fn apply<'a>(
|
||||
pub fn apply<'a>(
|
||||
&self,
|
||||
seq: &'a [MacTree],
|
||||
i: &Interner,
|
||||
save_loc: impl Fn(Sym) -> bool,
|
||||
) -> Option<(MatchState<'a>, &'a [MacTree])> {
|
||||
let mut state = any_match(&self.0, seq, &save_loc)?;
|
||||
match state.remove(i.i("::after").await) {
|
||||
Some(StateEntry::Scalar(_)) => panic!("::after can never be a scalar entry!"),
|
||||
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.0.fmt(f) }
|
||||
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})") }
|
||||
|
||||
Reference in New Issue
Block a user