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:
@@ -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();
|
||||||
tyenv.types.push(ty);
|
if let Some(ty) = tyenv.type_from_ast(TypeId(tid), td) {
|
||||||
tid += 1;
|
tyenv.types.push(ty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -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(¯o_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,50 +2160,28 @@ 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, ..
|
tyenv.report_error(
|
||||||
} => {
|
pos,
|
||||||
if pure && !ctor_is_pure {
|
format!(
|
||||||
tyenv.report_error(
|
"Used non-pure constructor '{}' in pure expression context",
|
||||||
pos,
|
sym.0
|
||||||
format!(
|
),
|
||||||
"Used non-pure constructor '{}' in pure expression context",
|
);
|
||||||
sym.0
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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,
|
||||||
|
|||||||
Reference in New Issue
Block a user