bend/fun/transform/
fix_match_defs.rs

1use crate::{
2  diagnostics::Diagnostics,
3  fun::{Adts, Constructors, Ctx, Pattern, Rule, Term},
4};
5
6impl Ctx<'_> {
7  /// Makes every pattern matching definition have correct a left-hand side.
8  ///
9  /// Does not check exhaustiveness of rules and type mismatches. (Inter-ctr/type proprieties)
10  pub fn fix_match_defs(&mut self) -> Result<(), Diagnostics> {
11    for def in self.book.defs.values_mut() {
12      let mut errs = vec![];
13
14      let def_arity = def.arity();
15      for rule in &mut def.rules {
16        rule.fix_match_defs(def_arity, &self.book.ctrs, &self.book.adts, &mut errs);
17      }
18
19      for err in errs {
20        self.info.add_function_error(err, def.name.clone(), def.source.clone());
21      }
22    }
23
24    self.info.fatal(())
25  }
26}
27
28impl Rule {
29  fn fix_match_defs(&mut self, def_arity: usize, ctrs: &Constructors, adts: &Adts, errs: &mut Vec<String>) {
30    if self.arity() != def_arity {
31      errs.push(format!(
32        "Incorrect pattern matching rule arity. Expected {} args, found {}.",
33        def_arity,
34        self.arity()
35      ));
36    }
37
38    for pat in &mut self.pats {
39      pat.resolve_pat(ctrs);
40      pat.check_good_ctr(ctrs, adts, errs);
41    }
42
43    self.body.fix_match_defs(ctrs, adts, errs);
44  }
45}
46
47impl Term {
48  fn fix_match_defs(&mut self, ctrs: &Constructors, adts: &Adts, errs: &mut Vec<String>) {
49    match self {
50      Term::Def { def, nxt } => {
51        let def_arity = def.arity();
52        for rule in &mut def.rules {
53          rule.fix_match_defs(def_arity, ctrs, adts, errs);
54        }
55        nxt.fix_match_defs(ctrs, adts, errs);
56      }
57      _ => {
58        for children in self.children_mut() {
59          children.fix_match_defs(ctrs, adts, errs);
60        }
61      }
62    }
63  }
64}
65
66impl Pattern {
67  /// If a var pattern actually refers to an ADT constructor, convert it into a constructor pattern.
68  fn resolve_pat(&mut self, ctrs: &Constructors) {
69    if let Pattern::Var(Some(nam)) = self {
70      if ctrs.contains_key(nam) {
71        *self = Pattern::Ctr(std::mem::take(nam), vec![]);
72      }
73    }
74    for child in self.children_mut() {
75      child.resolve_pat(ctrs);
76    }
77  }
78
79  /// Check that ADT constructor pats are correct, meaning defined in a `data` and with correct arity.
80  fn check_good_ctr(&self, ctrs: &Constructors, adts: &Adts, errs: &mut Vec<String>) {
81    if let Pattern::Ctr(nam, args) = self {
82      if let Some(adt) = ctrs.get(nam) {
83        let expected_arity = adts[adt].ctrs[nam].fields.len();
84        let found_arity = args.len();
85        if expected_arity != found_arity {
86          errs.push(format!(
87            "Incorrect arity for constructor '{}' of type '{}' in pattern matching rule. Expected {} fields, found {}",
88            nam, adt, expected_arity, found_arity
89          ));
90        }
91      } else {
92        errs.push(format!("Unbound constructor '{nam}' in pattern matching rule."));
93      }
94    }
95    for child in self.children() {
96      child.check_good_ctr(ctrs, adts, errs);
97    }
98  }
99}