bend/fun/check/
shared_names.rs1use 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 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}