Some fixes to the internal-extractor macro substitution
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user