Browse Source

ISLE: add a missing type check for whether terms used in expressions have a constructor

pull/3506/head
Nick Fitzgerald 3 years ago
parent
commit
00e7ca206f
  1. 19
      cranelift/isle/isle/src/ast.rs
  2. 23
      cranelift/isle/isle/src/sema.rs

19
cranelift/isle/isle/src/ast.rs

@ -338,6 +338,25 @@ impl Expr {
| &Expr::Let { pos, .. } => pos,
}
}
/// Call `f` for each of the terms in this expression.
pub fn terms(&self, f: &mut dyn FnMut(Pos, &Ident)) {
match self {
Expr::Term { sym, args, pos } => {
f(*pos, sym);
for arg in args {
arg.terms(f);
}
}
Expr::Let { defs, body, .. } => {
for def in defs {
def.val.terms(f);
}
body.terms(f);
}
Expr::Var { .. } | Expr::ConstInt { .. } | Expr::ConstPrim { .. } => {}
}
}
}
/// One variable locally bound in a `(let ...)` expression.

23
cranelift/isle/isle/src/sema.rs

@ -767,6 +767,7 @@ impl TermEnv {
tyenv.return_errors()?;
env.collect_rules(tyenv, defs);
env.check_for_undefined_decls(tyenv, defs);
env.check_for_expr_terms_without_constructors(tyenv, defs);
tyenv.return_errors()?;
Ok(env)
@ -1283,6 +1284,28 @@ impl TermEnv {
}
}
fn check_for_expr_terms_without_constructors(&self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
for def in &defs.defs {
if let ast::Def::Rule(rule) = def {
rule.expr.terms(&mut |pos, ident| {
let sym = tyenv.intern_mut(ident);
let term = self.term_map[&sym];
let term = &self.terms[term.index()];
if !term.has_constructor() {
tyenv.report_error(
pos,
format!(
"term `{}` cannot be used in an expression because \
it does not have a constructor",
ident.0
),
)
}
});
}
}
}
fn translate_pattern(
&self,
tyenv: &mut TypeEnv,

Loading…
Cancel
Save