use crate::{
diagnostics::Diagnostics,
fun::{Adts, Constructors, Ctx, Pattern},
};
impl Ctx<'_> {
pub fn fix_match_defs(&mut self) -> Result<(), Diagnostics> {
self.info.start_pass();
for def in self.book.defs.values_mut() {
let mut errs = vec![];
let def_arity = def.arity();
for rule in &mut def.rules {
if rule.arity() != def_arity {
errs.push(format!(
"Incorrect pattern matching rule arity. Expected {} args, found {}.",
def_arity,
rule.arity()
));
}
for pat in &mut rule.pats {
pat.resolve_pat(&self.book.ctrs);
pat.check_good_ctr(&self.book.ctrs, &self.book.adts, &mut errs);
}
}
for err in errs {
self.info.add_rule_error(err, def.name.clone());
}
}
self.info.fatal(())
}
}
impl Pattern {
fn resolve_pat(&mut self, ctrs: &Constructors) {
if let Pattern::Var(Some(nam)) = self {
if ctrs.contains_key(nam) {
*self = Pattern::Ctr(std::mem::take(nam), vec![]);
}
}
for child in self.children_mut() {
child.resolve_pat(ctrs);
}
}
fn check_good_ctr(&self, ctrs: &Constructors, adts: &Adts, errs: &mut Vec<String>) {
if let Pattern::Ctr(nam, args) = self {
if let Some(adt) = ctrs.get(nam) {
let expected_arity = adts[adt].ctrs[nam].len();
let found_arity = args.len();
if expected_arity != found_arity {
errs.push(format!(
"Incorrect arity for constructor '{}' of type '{}' in pattern matching rule. Expected {} fields, found {}",
nam, adt, expected_arity, found_arity
));
}
} else {
errs.push(format!("Unbound constructor '{nam}' in pattern matching rule."));
}
}
for child in self.children() {
child.check_good_ctr(ctrs, adts, errs);
}
}
}