microcad_lang/resolve/
symbol_table.rs1use derive_more::{Deref, DerefMut};
5
6use crate::{resolve::*, syntax::*};
7
8#[derive(Default, Deref, DerefMut)]
10pub struct SymbolTable(SymbolMap);
11
12impl SymbolTable {
13 pub fn add_symbol(&mut self, symbol: Symbol) -> ResolveResult<()> {
15 self.insert_symbol(symbol.id(), symbol.clone())
16 }
17
18 pub fn insert_symbol(&mut self, id: Identifier, symbol: Symbol) -> ResolveResult<()> {
20 log::trace!("insert symbol: {id}");
21 if let Some(symbol) = self.insert(id, symbol.clone()) {
22 Err(ResolveError::SymbolAlreadyDefined(symbol.full_name()))
23 } else {
24 Ok(())
25 }
26 }
27
28 pub(super) fn symbols(&self) -> Symbols {
29 self.values().cloned().collect()
30 }
31
32 pub fn unchecked(&self) -> Symbols {
34 let mut unchecked = Symbols::default();
35 self.values()
36 .for_each(|symbol| symbol.unchecked(&mut unchecked));
37 unchecked
38 }
39
40 pub fn unused(&self) -> Symbols {
44 let mut unchecked = Symbols::default();
45 self.values()
46 .for_each(|symbol| symbol.unused(&mut unchecked));
47 unchecked
48 }
49
50 pub(super) fn search_target_mode_ids(&self) -> ResolveResult<IdentifierSet> {
52 let mut ids = IdentifierSet::default();
53 self.values()
54 .try_for_each(|symbol| symbol.search_target_mode_ids(&mut ids))?;
55 Ok(ids)
56 }
57}
58
59impl WriteToFile for SymbolTable {}
60
61impl Lookup for SymbolTable {
62 fn lookup(&self, name: &QualifiedName) -> ResolveResult<Symbol> {
64 log::trace!(
65 "{lookup} for global symbol '{name:?}'",
66 lookup = crate::mark!(LOOKUP)
67 );
68 self.deny_super(name)?;
69
70 let symbol = match self.search(name, true) {
71 Ok(symbol) => symbol,
72 Err(err) => {
73 log::trace!(
74 "{not_found} global symbol: {name:?}",
75 not_found = crate::mark!(NOT_FOUND_INTERIM),
76 );
77 return Err(err)?;
78 }
79 };
80 symbol.set_check();
81 log::trace!(
82 "{found} global symbol: {symbol:?}",
83 found = crate::mark!(FOUND_INTERIM),
84 );
85 Ok(symbol)
86 }
87
88 fn ambiguity_error(ambiguous: QualifiedName, others: QualifiedNames) -> ResolveError {
89 ResolveError::AmbiguousSymbol(ambiguous, others)
90 }
91}
92
93impl std::fmt::Display for SymbolTable {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 writeln!(
96 f,
97 "{}",
98 self.iter()
99 .map(|(_, symbol)| symbol)
100 .filter(|symbol| !symbol.is_deleted())
101 .map(|symbol| symbol.full_name().to_string())
102 .collect::<Vec<_>>()
103 .join(", ")
104 )
105 }
106}
107
108impl std::fmt::Debug for SymbolTable {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 writeln!(f, "{:?}", self.0)
111 }
112}