cranelift-isle: Misc sema cleanups (#5242)

This mostly amounts to factoring out duplicated code and turning various
uses of `unwrap_or_continue!` into iterator chains.
This commit is contained in:
Jamey Sharp
2022-11-10 17:53:05 -08:00
committed by GitHub
parent 0367fbc2d4
commit 95ca72a37a

View File

@@ -303,6 +303,20 @@ impl Term {
self.ret_ty self.ret_ty
} }
fn check_args_count<T>(&self, args: &[T], tyenv: &mut TypeEnv, pos: Pos, sym: &ast::Ident) {
if self.arg_tys.len() != args.len() {
tyenv.report_error(
pos,
format!(
"Incorrect argument count for term '{}': got {}, expect {}",
sym.0,
args.len(),
self.arg_tys.len()
),
);
}
}
/// Is this term an enum variant? /// Is this term an enum variant?
pub fn is_enum_variant(&self) -> bool { pub fn is_enum_variant(&self) -> bool {
matches!(self.kind, TermKind::EnumVariant { .. }) matches!(self.kind, TermKind::EnumVariant { .. })
@@ -926,13 +940,13 @@ impl TypeEnv {
// Now lower AST nodes to type definitions, raising errors // Now lower AST nodes to type definitions, raising errors
// where typenames of fields are undefined or field names are // where typenames of fields are undefined or field names are
// duplicated. // duplicated.
let mut tid = 0;
for def in &defs.defs { for def in &defs.defs {
match def { match def {
&ast::Def::Type(ref td) => { &ast::Def::Type(ref td) => {
let ty = unwrap_or_continue!(tyenv.type_from_ast(TypeId(tid), td)); let tid = tyenv.types.len();
if let Some(ty) = tyenv.type_from_ast(TypeId(tid), td) {
tyenv.types.push(ty); tyenv.types.push(ty);
tid += 1; }
} }
_ => {} _ => {}
} }
@@ -1675,12 +1689,13 @@ impl TermEnv {
&mut bindings, &mut bindings,
/* is_root = */ true, /* is_root = */ true,
)); ));
let iflets = unwrap_or_continue!(self.translate_iflets( let iflets = rule
tyenv, .iflets
rule_term, .iter()
&rule.iflets[..], .filter_map(|iflet| {
&mut bindings, self.translate_iflet(tyenv, rule_term, iflet, &mut bindings)
)); })
.collect();
let rhs = unwrap_or_continue!(self.translate_expr( let rhs = unwrap_or_continue!(self.translate_expr(
tyenv, tyenv,
&rule.expr, &rule.expr,
@@ -1948,11 +1963,13 @@ impl TermEnv {
} }
}; };
let termdata = &self.terms[tid.index()];
// Get the return type and arg types. Verify the // Get the return type and arg types. Verify the
// expected type of this pattern, if any, against the // expected type of this pattern, if any, against the
// return type of the term. Insert an implicit // return type of the term. Insert an implicit
// converter if needed. // converter if needed.
let ret_ty = self.terms[tid.index()].ret_ty; let ret_ty = termdata.ret_ty;
let ty = match expected_ty { let ty = match expected_ty {
None => ret_ty, None => ret_ty,
Some(expected_ty) if expected_ty == ret_ty => ret_ty, Some(expected_ty) if expected_ty == ret_ty => ret_ty,
@@ -1985,20 +2002,7 @@ impl TermEnv {
} }
}; };
// Check that we have the correct argument count. termdata.check_args_count(args, tyenv, pos, sym);
if self.terms[tid.index()].arg_tys.len() != args.len() {
tyenv.report_error(
pos,
format!(
"Incorrect argument count for term '{}': got {}, expect {}",
sym.0,
args.len(),
self.terms[tid.index()].arg_tys.len()
),
);
}
let termdata = &self.terms[tid.index()];
match &termdata.kind { match &termdata.kind {
TermKind::Decl { TermKind::Decl {
@@ -2018,12 +2022,8 @@ impl TermEnv {
// from macro args to AST pattern trees and // from macro args to AST pattern trees and
// then evaluate the template with these // then evaluate the template with these
// substitutions. // substitutions.
let mut macro_args: Vec<ast::Pattern> = vec![];
for template_arg in args {
macro_args.push(template_arg.clone());
}
log!("internal extractor macro args = {:?}", args); log!("internal extractor macro args = {:?}", args);
let pat = template.subst_macro_args(&macro_args[..])?; let pat = template.subst_macro_args(&args)?;
return self.translate_pattern( return self.translate_pattern(
tyenv, tyenv,
rule_term, rule_term,
@@ -2049,20 +2049,21 @@ impl TermEnv {
} }
// Resolve subpatterns. // Resolve subpatterns.
let mut subpats = vec![]; let subpats = args
for (i, arg) in args.iter().enumerate() { .iter()
let term = unwrap_or_continue!(self.terms.get(tid.index())); .zip(termdata.arg_tys.iter())
let arg_ty = unwrap_or_continue!(term.arg_tys.get(i).copied()); .filter_map(|(arg, &arg_ty)| {
let (subpat, _) = unwrap_or_continue!(self.translate_pattern( self.translate_pattern(
tyenv, tyenv,
rule_term, rule_term,
arg, arg,
Some(arg_ty), Some(arg_ty),
bindings, bindings,
/* is_root = */ false, /* is_root = */ false,
)); )
subpats.push(subpat); })
} .map(|(subpat, _)| subpat)
.collect();
Some((Pattern::Term(ty, tid, subpats), ty)) Some((Pattern::Term(ty, tid, subpats), ty))
} }
@@ -2130,13 +2131,14 @@ impl TermEnv {
return None; return None;
} }
}; };
let termdata = &self.terms[tid.index()];
// Get the return type and arg types. Verify the // Get the return type and arg types. Verify the
// expected type of this pattern, if any, against the // expected type of this pattern, if any, against the
// return type of the term, and determine whether we // return type of the term, and determine whether we
// are doing an implicit conversion. Report an error // are doing an implicit conversion. Report an error
// if types don't match and no conversion is possible. // if types don't match and no conversion is possible.
let ret_ty = self.terms[tid.index()].ret_ty; let ret_ty = termdata.ret_ty;
let ty = if ty.is_some() && ret_ty != ty.unwrap() { let ty = if ty.is_some() && ret_ty != ty.unwrap() {
// Is there a converter for this type mismatch? // Is there a converter for this type mismatch?
if let Some(expanded_expr) = if let Some(expanded_expr) =
@@ -2158,11 +2160,8 @@ impl TermEnv {
}; };
// Check that the term's constructor is pure. // Check that the term's constructor is pure.
match &self.terms[tid.index()].kind { if pure {
TermKind::Decl { if let TermKind::Decl { pure: false, .. } = &termdata.kind {
pure: ctor_is_pure, ..
} => {
if pure && !ctor_is_pure {
tyenv.report_error( tyenv.report_error(
pos, pos,
format!( format!(
@@ -2172,36 +2171,17 @@ impl TermEnv {
); );
} }
} }
_ => {}
}
// Check that we have the correct argument count. termdata.check_args_count(args, tyenv, pos, sym);
if self.terms[tid.index()].arg_tys.len() != args.len() {
tyenv.report_error(
pos,
format!(
"Incorrect argument count for term '{}': got {}, expect {}",
sym.0,
args.len(),
self.terms[tid.index()].arg_tys.len()
),
);
}
// Resolve subexpressions. // Resolve subexpressions.
let mut subexprs = vec![]; let subexprs = args
for (i, arg) in args.iter().enumerate() { .iter()
let term = unwrap_or_continue!(self.terms.get(tid.index())); .zip(termdata.arg_tys.iter())
let arg_ty = unwrap_or_continue!(term.arg_tys.get(i).copied()); .filter_map(|(arg, &arg_ty)| {
let subexpr = unwrap_or_continue!(self.translate_expr( self.translate_expr(tyenv, arg, Some(arg_ty), bindings, pure)
tyenv, })
arg, .collect();
Some(arg_ty),
bindings,
pure
));
subexprs.push(subexpr);
}
Some(Expr::Term(ty, tid, subexprs)) Some(Expr::Term(ty, tid, subexprs))
} }
@@ -2338,22 +2318,6 @@ impl TermEnv {
} }
} }
fn translate_iflets(
&self,
tyenv: &mut TypeEnv,
rule_term: TermId,
iflets: &[ast::IfLet],
bindings: &mut Bindings,
) -> Option<Vec<IfLet>> {
let mut translated = vec![];
for iflet in iflets {
translated.push(unwrap_or_continue!(
self.translate_iflet(tyenv, rule_term, iflet, bindings)
));
}
Some(translated)
}
fn translate_iflet( fn translate_iflet(
&self, &self,
tyenv: &mut TypeEnv, tyenv: &mut TypeEnv,