From 5a8e35b253d41f11be4e6562642d954769f5b276 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Thu, 9 Sep 2021 18:12:46 -0700 Subject: [PATCH] Some fixes to the internal-extractor macro substitution --- cranelift/isle/src/ast.rs | 98 ++++++++++++++++++++++++++++++++++++++ cranelift/isle/src/sema.rs | 89 +++++++++------------------------- 2 files changed, 120 insertions(+), 67 deletions(-) diff --git a/cranelift/isle/src/ast.rs b/cranelift/isle/src/ast.rs index a0d6258485..8f1cd820c4 100644 --- a/cranelift/isle/src/ast.rs +++ b/cranelift/isle/src/ast.rs @@ -99,6 +99,8 @@ pub enum Pattern { Wildcard, /// N sub-patterns that must all match. And { subpats: Vec }, + /// 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::>(); + Pattern::And { subpats } + } + &Pattern::Term { ref sym, ref args } => { + let args = args + .iter() + .map(|arg| arg.make_macro_template(macro_args)) + .collect::>(); + 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::>(); + Pattern::And { subpats } + } + &Pattern::Term { ref sym, ref args } => { + let args = args + .iter() + .map(|arg| arg.subst_macro_args(macro_args)) + .collect::>(); + 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, diff --git a/cranelift/isle/src/sema.rs b/cranelift/isle/src/sema.rs index fe55369b70..df5854c2c4 100644 --- a/cranelift/isle/src/sema.rs +++ b/cranelift/isle/src/sema.rs @@ -110,10 +110,7 @@ pub enum TermKind { /// A term that defines an "extractor macro" in the LHS of a /// pattern. Its arguments take patterns and are simply /// substituted with the given patterns when used. - InternalExtractor { - args: Vec, - template: ast::Pattern, - }, + InternalExtractor { template: ast::Pattern }, /// A term defined solely by an external extractor function. ExternalExtractor { /// Extractor func. @@ -605,12 +602,11 @@ impl TermEnv { ) })?; let termdata = &mut self.terms[term.index()]; + let template = ext.template.make_macro_template(&ext.args[..]); + log::trace!("extractor def: {:?} becomes template {:?}", def, template); match &termdata.kind { &TermKind::Declared => { - termdata.kind = TermKind::InternalExtractor { - args: ext.args.clone(), - template: ext.template.clone(), - }; + termdata.kind = TermKind::InternalExtractor { template }; } _ => { return Err(tyenv.error( @@ -644,7 +640,6 @@ impl TermEnv { &rule.pattern, None, &mut bindings, - None, )?; let rhs = self.translate_expr(tyenv, rule.pos, &rule.expr, ty, &mut bindings)?; @@ -750,7 +745,6 @@ impl TermEnv { pat: &ast::Pattern, expected_ty: Option, bindings: &mut Bindings, - macro_args: Option<&HashMap>, ) -> SemaResult<(Pattern, TypeId)> { log::trace!("translate_pattern: {:?}", pat); log::trace!("translate_pattern: bindings = {:?}", bindings); @@ -772,14 +766,8 @@ impl TermEnv { let mut expected_ty = expected_ty; let mut children = vec![]; for subpat in subpats { - let (subpat, ty) = self.translate_pattern( - tyenv, - pos, - &*subpat, - expected_ty, - bindings, - macro_args, - )?; + let (subpat, ty) = + self.translate_pattern(tyenv, pos, &*subpat, expected_ty, bindings)?; expected_ty = expected_ty.or(Some(ty)); children.push(subpat); } @@ -793,29 +781,9 @@ impl TermEnv { ref var, ref subpat, } => { - // Handle macro-arg substitution. - if macro_args.is_some() && &**subpat == &ast::Pattern::Wildcard { - if let Some(macro_ast) = macro_args.as_ref().unwrap().get(var) { - return self.translate_pattern( - tyenv, - pos, - macro_ast, - expected_ty, - bindings, - macro_args, - ); - } - } - // Do the subpattern first so we can resolve the type for sure. - let (subpat, ty) = self.translate_pattern( - tyenv, - pos, - &*subpat, - expected_ty, - bindings, - macro_args, - )?; + let (subpat, ty) = + self.translate_pattern(tyenv, pos, &*subpat, expected_ty, bindings)?; let name = tyenv.intern_mut(var); if bindings.vars.iter().any(|bv| bv.name == name) { @@ -826,6 +794,7 @@ impl TermEnv { } let id = VarId(bindings.next_var); bindings.next_var += 1; + log::trace!("binding var {:?}", var.0); bindings.vars.push(BoundVar { name, id, ty }); Ok((Pattern::BindPattern(ty, id, Box::new(subpat)), ty)) @@ -916,33 +885,24 @@ impl TermEnv { } } } - &TermKind::InternalExtractor { - args: ref template_args, - ref template, - } => { + &TermKind::InternalExtractor { ref template } => { // Expand the extractor macro! We create a map // from macro args to AST pattern trees and // then evaluate the template with these // substitutions. - let mut arg_map = HashMap::new(); - for (template_arg, sub_ast) in template_args.iter().zip(args.iter()) { - let sub_ast = match sub_ast { + let mut macro_args: Vec = vec![]; + for template_arg in args { + let sub_ast = match template_arg { &ast::TermArgPattern::Pattern(ref pat) => pat.clone(), &ast::TermArgPattern::Expr(_) => { return Err(tyenv.error(pos, "Cannot expand an extractor macro with an expression in a macro argument".to_string())); } }; - arg_map.insert(template_arg.clone(), sub_ast.clone()); + macro_args.push(sub_ast.clone()); } - log::trace!("internal extractor map = {:?}", arg_map); - return self.translate_pattern( - tyenv, - pos, - template, - expected_ty, - bindings, - Some(&arg_map), - ); + log::trace!("internal extractor macro args = {:?}", args); + let pat = template.subst_macro_args(¯o_args[..]); + return self.translate_pattern(tyenv, pos, &pat, expected_ty, bindings); } &TermKind::ExternalConstructor { .. } | &TermKind::InternalConstructor => { // OK. @@ -957,19 +917,14 @@ impl TermEnv { let mut subpats = vec![]; for (i, arg) in args.iter().enumerate() { let arg_ty = self.terms[tid.index()].arg_tys[i]; - let (subpat, _) = self.translate_pattern_term_arg( - tyenv, - pos, - arg, - Some(arg_ty), - bindings, - macro_args, - )?; + let (subpat, _) = + self.translate_pattern_term_arg(tyenv, pos, arg, Some(arg_ty), bindings)?; subpats.push(subpat); } Ok((Pattern::Term(ty, *tid, subpats), ty)) } + &ast::Pattern::MacroArg { .. } => unreachable!(), } } @@ -980,12 +935,11 @@ impl TermEnv { pat: &ast::TermArgPattern, expected_ty: Option, bindings: &mut Bindings, - macro_args: Option<&HashMap>, ) -> SemaResult<(TermArgPattern, TypeId)> { match pat { &ast::TermArgPattern::Pattern(ref pat) => { let (subpat, ty) = - self.translate_pattern(tyenv, pos, pat, expected_ty, bindings, macro_args)?; + self.translate_pattern(tyenv, pos, pat, expected_ty, bindings)?; Ok((TermArgPattern::Pattern(subpat), ty)) } &ast::TermArgPattern::Expr(ref expr) => { @@ -1010,6 +964,7 @@ impl TermEnv { ty: TypeId, bindings: &mut Bindings, ) -> SemaResult { + log::trace!("translate_expr: {:?}", expr); match expr { &ast::Expr::Term { ref sym, ref args } => { // Look up the term.