diff --git a/cranelift/isle/isle/isle_examples/pass/conversions_extern.isle b/cranelift/isle/isle/isle_examples/pass/conversions_extern.isle new file mode 100644 index 0000000000..1cddf65749 --- /dev/null +++ b/cranelift/isle/isle/isle_examples/pass/conversions_extern.isle @@ -0,0 +1,22 @@ +(type T (primitive T)) +(type U (primitive U)) +(type V (primitive V)) + +(convert T U t_to_u) + +(type Result (enum (T (u U) (v V)))) + +;; Use the implicit converter before the underlying constructor is +;; declared (below). Also use one of the conversions before it is +;; declared (below). +(decl entry (T) Result) +(rule (entry t) + (Result.T t t)) + +(convert T V t_to_v) + +(decl t_to_u (T) U) +(extern constructor t_to_u t_to_u) + +(decl t_to_v (T) V) +(rule (t_to_v _) 0) diff --git a/cranelift/isle/isle/src/sema.rs b/cranelift/isle/isle/src/sema.rs index 10dac801c6..65f7cf753e 100644 --- a/cranelift/isle/isle/src/sema.rs +++ b/cranelift/isle/isle/src/sema.rs @@ -793,6 +793,8 @@ impl TermEnv { tyenv.return_errors()?; env.collect_converters(tyenv, defs); tyenv.return_errors()?; + env.collect_externs(tyenv, defs); + tyenv.return_errors()?; env.collect_rules(tyenv, defs); env.check_for_undefined_decls(tyenv, defs); env.check_for_expr_terms_without_constructors(tyenv, defs); @@ -1164,64 +1166,9 @@ impl TermEnv { } } - fn collect_rules(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) { + fn collect_externs(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) { for def in &defs.defs { match def { - &ast::Def::Rule(ref rule) => { - let pos = rule.pos; - let mut bindings = Bindings { - next_var: 0, - vars: vec![], - }; - - let rule_term = match rule.pattern.root_term() { - Some(name) => { - let sym = tyenv.intern_mut(name); - match self.term_map.get(&sym) { - Some(term) => *term, - None => { - tyenv.report_error( - pos, - "Cannot define a rule for an unknown term".to_string(), - ); - continue; - } - } - } - None => { - tyenv.report_error( - pos, - "Rule does not have a term at the root of its left-hand side" - .to_string(), - ); - continue; - } - }; - - let (lhs, ty) = unwrap_or_continue!(self.translate_pattern( - tyenv, - rule_term, - &rule.pattern, - None, - &mut bindings, - /* is_root = */ true, - )); - let rhs = unwrap_or_continue!(self.translate_expr( - tyenv, - &rule.expr, - ty, - &mut bindings - )); - - let rid = RuleId(self.rules.len()); - self.rules.push(Rule { - id: rid, - lhs, - rhs, - prio: rule.prio, - pos, - }); - } &ast::Def::Extern(ast::Extern::Constructor { ref term, ref func, @@ -1356,6 +1303,69 @@ impl TermEnv { } } + fn collect_rules(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) { + for def in &defs.defs { + match def { + &ast::Def::Rule(ref rule) => { + let pos = rule.pos; + let mut bindings = Bindings { + next_var: 0, + vars: vec![], + }; + + let rule_term = match rule.pattern.root_term() { + Some(name) => { + let sym = tyenv.intern_mut(name); + match self.term_map.get(&sym) { + Some(term) => *term, + None => { + tyenv.report_error( + pos, + "Cannot define a rule for an unknown term".to_string(), + ); + continue; + } + } + } + None => { + tyenv.report_error( + pos, + "Rule does not have a term at the root of its left-hand side" + .to_string(), + ); + continue; + } + }; + + let (lhs, ty) = unwrap_or_continue!(self.translate_pattern( + tyenv, + rule_term, + &rule.pattern, + None, + &mut bindings, + /* is_root = */ true, + )); + let rhs = unwrap_or_continue!(self.translate_expr( + tyenv, + &rule.expr, + ty, + &mut bindings + )); + + let rid = RuleId(self.rules.len()); + self.rules.push(Rule { + id: rid, + lhs, + rhs, + prio: rule.prio, + pos, + }); + } + _ => {} + } + } + } + fn check_for_undefined_decls(&self, tyenv: &mut TypeEnv, defs: &ast::Defs) { for def in &defs.defs { if let ast::Def::Decl(decl) = def {