1use crate::{builtin::*, rc::*, resolve::*, src_ref::*, syntax::*, value::*};
5use custom_debug::Debug;
6use derive_more::{Deref, DerefMut};
7
8#[derive(Debug, Clone)]
10pub struct SymbolInner {
11 pub def: SymbolDefinition,
13 #[debug(skip)]
15 pub parent: Option<Symbol>,
16 pub children: SymbolMap,
18 pub used: bool,
20}
21
22impl Default for SymbolInner {
23 fn default() -> Self {
24 Self {
25 def: SymbolDefinition::SourceFile(SourceFile::default().into()),
26 parent: Default::default(),
27 children: Default::default(),
28 used: false,
29 }
30 }
31}
32
33#[derive(Debug, Clone, Deref, DerefMut)]
41pub struct Symbol {
42 visibility: Visibility,
43 #[deref]
44 #[deref_mut]
45 inner: RcMut<SymbolInner>,
46}
47
48#[derive(Debug, Deref)]
50pub struct Symbols(Vec<Symbol>);
51
52impl Symbols {
53 pub fn full_names(&self) -> QualifiedNames {
55 self.iter().map(|symbol| symbol.full_name()).collect()
56 }
57}
58
59impl Default for Symbol {
60 fn default() -> Self {
61 Self {
62 visibility: Visibility::default(),
63 inner: RcMut::new(Default::default()),
64 }
65 }
66}
67
68impl PartialEq for Symbol {
69 fn eq(&self, other: &Self) -> bool {
70 self.visibility == other.visibility && self.inner.as_ptr() == other.inner.as_ptr()
72 }
73}
74
75impl From<Vec<Symbol>> for Symbols {
76 fn from(value: Vec<Symbol>) -> Self {
77 Self(value)
78 }
79}
80
81impl std::fmt::Display for Symbols {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 write!(
84 f,
85 "{}",
86 self.0
87 .iter()
88 .map(|symbol| symbol.to_string())
89 .collect::<Vec<_>>()
90 .join("")
91 )
92 }
93}
94
95impl FromIterator<Symbol> for Symbols {
96 fn from_iter<T: IntoIterator<Item = Symbol>>(iter: T) -> Self {
97 Self(iter.into_iter().collect())
98 }
99}
100
101impl Symbol {
102 pub fn new(def: SymbolDefinition, parent: Option<Symbol>) -> Self {
108 Symbol {
109 visibility: def.visibility(),
110 inner: RcMut::new(SymbolInner {
111 def,
112 parent,
113 ..Default::default()
114 }),
115 }
116 }
117
118 pub fn new_builtin(
124 id: Identifier,
125 parameters: Option<ParameterValueList>,
126 f: &'static BuiltinFn,
127 ) -> Symbol {
128 Symbol::new(
129 SymbolDefinition::Builtin(Rc::new(Builtin { id, parameters, f })),
130 None,
131 )
132 }
133
134 pub fn new_call_argument(id: Identifier, value: Value) -> Symbol {
136 Symbol::new(SymbolDefinition::Argument(id, value), None)
137 }
138
139 pub fn print_symbol(
145 &self,
146 f: &mut impl std::fmt::Write,
147 id: Option<&Identifier>,
148 depth: usize,
149 children: bool,
150 ) -> std::fmt::Result {
151 let self_id = &self.id();
152 let id = id.unwrap_or(self_id);
153 if cfg!(feature = "ansi-color") && !self.borrow().used {
154 color_print::cwrite!(
155 f,
156 "{:depth$}<#606060>{visibility}{id:?} {def} [{full_name}]</>",
157 "",
158 visibility = self.visibility(),
159 def = self.inner.borrow().def,
160 full_name = self.full_name(),
161 )?;
162 } else {
163 write!(
164 f,
165 "{:depth$}{id:?} {} [{}]",
166 "",
167 self.inner.borrow().def,
168 self.full_name(),
169 )?;
170 }
171 if children {
172 writeln!(f)?;
173 let indent = 4;
174
175 self.borrow().children.iter().try_for_each(|(id, child)| {
176 child.print_symbol(f, Some(id), depth + indent, true)
177 })?;
178 }
179 Ok(())
180 }
181
182 pub fn add_child(parent: &Symbol, child: Symbol) {
187 child.borrow_mut().parent = Some(parent.clone());
188 let id = child.id();
189 parent.borrow_mut().children.insert(id, child);
190 }
191
192 pub fn move_children(&self, from: &Symbol) {
200 from.borrow().children.iter().for_each(|(id, child)| {
202 child.borrow_mut().parent = Some(self.clone());
203 self.borrow_mut().children.insert(id.clone(), child.clone());
204 });
205 }
206
207 pub fn clone_with_visibility(&self, visibility: Visibility) -> Self {
209 let mut cloned = self.clone();
210 cloned.visibility = visibility;
211 cloned
212 }
213
214 pub fn id(&self) -> Identifier {
216 self.borrow().def.id()
217 }
218
219 pub fn get(&self, id: &Identifier) -> Option<Symbol> {
223 self.borrow().children.get(id).cloned()
224 }
225
226 pub fn is_empty(&self) -> bool {
228 self.borrow().children.is_empty()
229 }
230
231 pub fn visibility(&self) -> Visibility {
233 self.visibility
234 }
235
236 pub fn is_public(&self) -> bool {
238 matches!(self.visibility(), Visibility::Public)
239 }
240
241 pub fn is_private(&self) -> bool {
243 !self.is_public()
244 }
245
246 pub fn search(&self, name: &QualifiedName) -> Option<Symbol> {
250 log::trace!("Searching {name} in {:?}", self.full_name());
251 if let Some(first) = name.first() {
252 if let Some(child) = self.get(first) {
253 let name = &name.remove_first();
254 if name.is_empty() {
255 log::trace!("Found {name:?} in {:?}", self.full_name());
256 Some(child.clone())
257 } else {
258 child.search(name)
259 }
260 } else {
261 log::trace!("No child in {:?} while searching for {name:?}", self.id());
262 None
263 }
264 } else {
265 log::warn!("Cannot search for an anonymous name");
266 None
267 }
268 }
269
270 pub fn can_const(&self) -> bool {
272 matches!(
273 self.borrow().def,
274 SymbolDefinition::Module(..) | SymbolDefinition::SourceFile(..)
275 )
276 }
277
278 pub fn can_value(&self) -> bool {
280 matches!(
281 self.borrow().def,
282 SymbolDefinition::Function(..)
283 | SymbolDefinition::Workbench(..)
284 | SymbolDefinition::SourceFile(..)
285 )
286 }
287
288 pub fn can_prop(&self) -> bool {
290 matches!(self.borrow().def, SymbolDefinition::Workbench(..))
291 }
292
293 pub fn can_pub(&self) -> bool {
295 self.can_const()
296 }
297
298 pub fn set_value(&self, new_value: Value) -> ResolveResult<()> {
300 match &mut self.borrow_mut().def {
301 SymbolDefinition::Constant(_, _, value) => {
302 *value = new_value;
303 Ok(())
304 }
305 _ => Err(ResolveError::NotAValue(self.full_name())),
306 }
307 }
308
309 pub fn get_value(&self) -> ResolveResult<Value> {
311 match &self.borrow().def {
312 SymbolDefinition::Constant(_, _, value) => Ok(value.clone()),
313 _ => Err(ResolveError::NotAValue(self.full_name())),
314 }
315 }
316}
317
318impl FullyQualify for Symbol {
319 fn full_name(&self) -> QualifiedName {
321 let id = self.id();
322 match &self.borrow().parent {
323 Some(parent) => {
324 let mut name = parent.full_name();
325 name.push(id);
326 name
327 }
328
329 None => {
330 let src_ref = id.src_ref();
331 QualifiedName::new(vec![id], src_ref)
332 }
333 }
334 }
335}
336
337impl std::fmt::Display for Symbol {
338 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
339 self.print_symbol(f, None, 0, false)
340 }
341}
342
343impl SrcReferrer for SymbolInner {
344 fn src_ref(&self) -> SrcRef {
345 match &self.def {
346 SymbolDefinition::SourceFile(source_file) => source_file.src_ref(),
347 SymbolDefinition::Module(module) => module.src_ref(),
348 SymbolDefinition::Workbench(workbench) => workbench.src_ref(),
349 SymbolDefinition::Function(function) => function.src_ref(),
350 SymbolDefinition::Builtin(_) => {
351 unreachable!("builtin has no source code reference")
352 }
353 SymbolDefinition::Constant(_, identifier, _)
354 | SymbolDefinition::Argument(identifier, _) => identifier.src_ref(),
355 SymbolDefinition::Alias(_, identifier, _) => identifier.src_ref(),
356 SymbolDefinition::UseAll(_, name) => name.src_ref(),
357 #[cfg(test)]
358 SymbolDefinition::Tester(id) => id.src_ref(),
359 }
360 }
361}