Some fixes to the internal-extractor macro substitution

This commit is contained in:
Chris Fallin
2021-09-09 18:12:46 -07:00
parent 3f96068f94
commit 5a8e35b253
2 changed files with 120 additions and 67 deletions

View File

@@ -99,6 +99,8 @@ pub enum Pattern {
Wildcard,
/// N sub-patterns that must all match.
And { subpats: Vec<Pattern> },
/// Internal use only: macro argument in a template.
MacroArg { index: usize },
}
impl Pattern {
@@ -109,6 +111,81 @@ impl Pattern {
_ => None,
}
}
pub fn make_macro_template(&self, macro_args: &[Ident]) -> Pattern {
log::trace!("repplace_macro_args: {:?} with {:?}", self, macro_args);
match self {
&Pattern::BindPattern {
ref var,
ref subpat,
} if matches!(&**subpat, &Pattern::Wildcard) => {
if let Some(i) = macro_args.iter().position(|arg| arg == var) {
Pattern::MacroArg { index: i }
} else {
self.clone()
}
}
&Pattern::BindPattern {
ref var,
ref subpat,
} => Pattern::BindPattern {
var: var.clone(),
subpat: Box::new(subpat.make_macro_template(macro_args)),
},
&Pattern::And { ref subpats } => {
let subpats = subpats
.iter()
.map(|subpat| subpat.make_macro_template(macro_args))
.collect::<Vec<_>>();
Pattern::And { subpats }
}
&Pattern::Term { ref sym, ref args } => {
let args = args
.iter()
.map(|arg| arg.make_macro_template(macro_args))
.collect::<Vec<_>>();
Pattern::Term {
sym: sym.clone(),
args,
}
}
&Pattern::Var { .. } | &Pattern::Wildcard | &Pattern::ConstInt { .. } => self.clone(),
&Pattern::MacroArg { .. } => unreachable!(),
}
}
pub fn subst_macro_args(&self, macro_args: &[Pattern]) -> Pattern {
match self {
&Pattern::BindPattern {
ref var,
ref subpat,
} => Pattern::BindPattern {
var: var.clone(),
subpat: Box::new(subpat.subst_macro_args(macro_args)),
},
&Pattern::And { ref subpats } => {
let subpats = subpats
.iter()
.map(|subpat| subpat.subst_macro_args(macro_args))
.collect::<Vec<_>>();
Pattern::And { subpats }
}
&Pattern::Term { ref sym, ref args } => {
let args = args
.iter()
.map(|arg| arg.subst_macro_args(macro_args))
.collect::<Vec<_>>();
Pattern::Term {
sym: sym.clone(),
args,
}
}
&Pattern::Var { .. } | &Pattern::Wildcard | &Pattern::ConstInt { .. } => self.clone(),
&Pattern::MacroArg { index } => macro_args[index].clone(),
}
}
}
/// A pattern in a term argument. Adds "evaluated expression" to kinds
@@ -125,6 +202,27 @@ pub enum TermArgPattern {
Expr(Expr),
}
impl TermArgPattern {
fn make_macro_template(&self, args: &[Ident]) -> TermArgPattern {
log::trace!("repplace_macro_args: {:?} with {:?}", self, args);
match self {
&TermArgPattern::Pattern(ref pat) => {
TermArgPattern::Pattern(pat.make_macro_template(args))
}
&TermArgPattern::Expr(_) => self.clone(),
}
}
fn subst_macro_args(&self, args: &[Pattern]) -> TermArgPattern {
match self {
&TermArgPattern::Pattern(ref pat) => {
TermArgPattern::Pattern(pat.subst_macro_args(args))
}
&TermArgPattern::Expr(_) => self.clone(),
}
}
}
/// An expression: the right-hand side of a rule.
///
/// Note that this *almost* looks like a core Lisp or lambda calculus,