bend/fun/check/
shared_names.rs

1use crate::fun::{Ctx, Name};
2use indexmap::IndexMap;
3use std::fmt::Display;
4
5#[derive(Debug, Clone)]
6pub struct RepeatedTopLevelNameErr {
7  kind_fst: NameKind,
8  kind_snd: NameKind,
9  name: Name,
10}
11
12impl Ctx<'_> {
13  /// Checks if there are any repeated top level names. Constructors
14  /// and functions can't share names and adts can't share names.
15  pub fn check_shared_names(&mut self) {
16    let mut names = NameInfo::default();
17
18    for adt_name in self.book.adts.keys() {
19      names.add_name(adt_name, NameKind::Adt);
20    }
21
22    for ctr_name in self.book.ctrs.keys() {
23      names.add_name(ctr_name, NameKind::Ctr);
24    }
25
26    for def_name in self.book.defs.keys() {
27      names.add_name(def_name, NameKind::Def);
28    }
29
30    for err in names.into_errs() {
31      self.info.add_book_error(err);
32    }
33  }
34}
35
36#[derive(Debug, Clone, Copy)]
37enum NameKind {
38  Adt,
39  Def,
40  Ctr,
41}
42
43#[derive(Debug, Default)]
44struct NameInfo<'a>(IndexMap<&'a Name, Vec<NameKind>>);
45
46impl<'a> NameInfo<'a> {
47  fn add_name(&mut self, name: &'a Name, kind: NameKind) {
48    self.0.entry(name).or_default().push(kind);
49  }
50
51  fn into_errs(self) -> Vec<RepeatedTopLevelNameErr> {
52    let mut errs = vec![];
53    for (name, kinds) in self.0 {
54      let mut num_adts = 0;
55      let mut fst_ctr_def = None;
56      for kind in kinds {
57        if let NameKind::Adt = kind {
58          num_adts += 1;
59          if num_adts >= 2 {
60            errs.push(RepeatedTopLevelNameErr {
61              kind_fst: NameKind::Adt,
62              kind_snd: NameKind::Adt,
63              name: name.clone(),
64            });
65          }
66        } else if let Some(fst) = fst_ctr_def {
67          errs.push(RepeatedTopLevelNameErr { kind_fst: fst, kind_snd: kind, name: name.clone() });
68        } else {
69          fst_ctr_def = Some(kind);
70        }
71      }
72    }
73    errs
74  }
75}
76
77impl Display for NameKind {
78  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79    match self {
80      NameKind::Adt => write!(f, "data type"),
81      NameKind::Def => write!(f, "function"),
82      NameKind::Ctr => write!(f, "constructor"),
83    }
84  }
85}
86
87impl std::fmt::Display for RepeatedTopLevelNameErr {
88  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89    let mut snd = self.kind_snd.to_string();
90    snd[0..1].make_ascii_uppercase();
91    write!(f, "{} '{}' has the same name as a previously defined {}", snd, self.name, self.kind_fst)
92  }
93}