microcad_lang/resolve/
symbol_map.rs1use crate::{diag::*, resolve::*, syntax::*, value::*};
5use derive_more::{Deref, DerefMut};
6use std::collections::btree_map::BTreeMap;
7
8#[derive(Debug, Default, Clone, Deref, DerefMut)]
10pub struct SymbolMap(BTreeMap<Identifier, Symbol>);
11
12impl From<Tuple> for SymbolMap {
13 fn from(tuple: Tuple) -> Self {
14 let mut symbol_map = SymbolMap::default();
15 for (id, value) in tuple.named.iter() {
16 symbol_map.add_node(Symbol::new_call_argument(id.clone(), value.clone()))
17 }
18 symbol_map
19 }
20}
21
22impl FromIterator<(Identifier, Value)> for SymbolMap {
23 fn from_iter<T: IntoIterator<Item = (Identifier, Value)>>(iter: T) -> Self {
24 let mut symbol_map = SymbolMap::default();
25 for (id, value) in iter {
26 symbol_map.add_node(Symbol::new_call_argument(id.clone(), value.clone()))
27 }
28 symbol_map
29 }
30}
31
32impl WriteToFile for SymbolMap {}
33
34impl SymbolMap {
35 pub fn new() -> Self {
37 Self(Default::default())
38 }
39
40 pub fn add_node(&mut self, symbol: Symbol) {
42 let id = symbol.id();
43 self.0.insert(id, symbol);
44 }
45
46 pub fn insert_node(&mut self, id: Identifier, symbol: Symbol) {
48 self.0.insert(id, symbol);
49 }
50
51 pub fn search(&self, name: &QualifiedName) -> ResolveResult<Symbol> {
53 if name.is_empty() {
54 if let Some(symbol) = self.get(&Identifier::none()) {
55 symbol.borrow_mut().used = true;
56 return Ok(symbol.clone());
57 }
58 } else {
59 let (id, leftover) = name.split_first();
60 if let Some(symbol) = self.get(&id) {
61 symbol.borrow_mut().used = true;
62 if leftover.is_empty() {
63 log::trace!("Fetched {name:?} from globals (symbol map)");
64 return Ok(symbol.clone());
65 } else if let Some(symbol) = symbol.search(&leftover) {
66 return Ok(symbol);
67 }
68 }
69 }
70
71 Err(ResolveError::SymbolNotFound(name.clone()))
72 }
73
74 pub fn detach_from_parent(mut self) -> Self {
76 for child in self.iter_mut() {
77 child.1.borrow_mut().parent = None;
78 }
79 self
80 }
81
82 pub fn print(&self, f: &mut std::fmt::Formatter<'_>, depth: usize) -> std::fmt::Result {
84 for (id, symbol) in self.0.iter() {
85 symbol.print_symbol(f, Some(id), depth, true)?;
86 }
87
88 Ok(())
89 }
90
91 pub fn move_children(&mut self, from: &Symbol) {
99 from.borrow().children.iter().for_each(|(id, child)| {
101 child.borrow_mut().parent = None;
102 self.insert(id.clone(), child.clone());
103 });
104 }
105
106 pub fn path_to(&self, what: &QualifiedName) -> ResolveResult<Symbols> {
110 (1..(what.len() + 1))
111 .map(|n| what[0..n].iter().cloned().collect())
112 .map(|what| self.search(&what))
113 .collect()
114 }
115}
116
117impl std::fmt::Display for SymbolMap {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 for (id, symbol) in self.0.iter() {
120 symbol.print_symbol(f, Some(id), 0, true)?;
121 }
122
123 Ok(())
124 }
125}
126
127#[test]
128fn symbol_map_path_to() {
129 let mut symbols = SymbolMap::new();
130 let a = Symbol::new(SymbolDefinition::Tester("a".into()), None);
131 let b = Symbol::new(SymbolDefinition::Tester("b".into()), Some(a.clone()));
132 let c = Symbol::new(SymbolDefinition::Tester("c".into()), Some(b.clone()));
133 Symbol::add_child(&b, c);
134 Symbol::add_child(&a, b);
135 symbols.add_node(a);
136
137 let name: QualifiedName = "a::b::c".into();
138
139 log::trace!("symbols:\n{}", symbols);
140 let symbols = symbols.path_to(&name).expect("test error");
141 log::trace!("parents of {name}: {}", symbols.full_names());
142 assert_eq!(
143 symbols.full_names().to_string(),
144 "a, a::b, a::b::c".to_string(),
145 );
146}