bend/fun/transform/
fix_match_defs.rs1use crate::{
2 diagnostics::Diagnostics,
3 fun::{Adts, Constructors, Ctx, Pattern, Rule, Term},
4};
5
6impl Ctx<'_> {
7 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 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 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}