microcad_lang/resolve/symbol/
symbol_definition.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4use crate::{builtin::*, rc::*, resolve::*, src_ref::*, syntax::*, value::*};
5
6/// Symbol definition
7#[derive(Clone)]
8pub enum SymbolDef {
9    /// Source file symbol.
10    SourceFile(Rc<SourceFile>),
11    /// Module symbol.
12    Module(Rc<ModuleDefinition>),
13    /// Part symbol.
14    Workbench(Rc<WorkbenchDefinition>),
15    /// Function symbol.
16    Function(Rc<FunctionDefinition>),
17    /// Assignment.
18    Assignment(Rc<Assignment>),
19    /// Builtin symbol.
20    Builtin(Rc<Builtin>),
21    /// Constant.
22    Constant(Visibility, Identifier, Value),
23    /// Argument value.
24    Argument(Identifier, Value),
25    /// Alias of a pub use statement.
26    Alias(Visibility, Identifier, QualifiedName),
27    /// Use all available symbols in the module with the given name.
28    UseAll(Visibility, QualifiedName),
29    /// Just a dummy for testing
30    #[cfg(test)]
31    Tester(Identifier),
32}
33
34impl SymbolDef {
35    /// Returns ID of this definition.
36    pub fn id(&self) -> Identifier {
37        match &self {
38            Self::Workbench(w) => w.id.clone(),
39            Self::Module(m) => m.id.clone(),
40            Self::Function(f) => f.id.clone(),
41            Self::SourceFile(s) => s.id(),
42            Self::Builtin(m) => m.id(),
43            Self::Assignment(a) => a.id.clone(),
44            Self::Constant(_, id, _) | Self::Argument(id, _) | Self::Alias(_, id, _) => id.clone(),
45            Self::UseAll(..) => Identifier::none(),
46            #[cfg(test)]
47            Self::Tester(id) => id.clone(),
48        }
49    }
50
51    /// Return visibility of this symbol.
52    pub fn visibility(&self) -> Visibility {
53        match &self {
54            Self::SourceFile(..) | Self::Builtin(..) => Visibility::Public,
55
56            Self::Argument(..) => Visibility::Private,
57
58            Self::Constant(visibility, ..) => visibility.clone(),
59            Self::Module(md) => md.visibility.clone(),
60            Self::Workbench(wd) => wd.visibility.clone(),
61            Self::Function(fd) => fd.visibility.clone(),
62            Self::Assignment(a) => a.visibility.clone(),
63
64            Self::Alias(visibility, ..) | Self::UseAll(visibility, ..) => visibility.clone(),
65
66            #[cfg(test)]
67            Self::Tester(..) => Visibility::Public,
68        }
69    }
70
71    pub(crate) fn kind_str(&self) -> String {
72        match self {
73            Self::Workbench(w) => format!("{}", w.kind),
74            Self::Module(..) => "Module".to_string(),
75            Self::Function(..) => "Function".to_string(),
76            Self::SourceFile(..) => "SourceFile".to_string(),
77            Self::Builtin(b) => format!("{}", b.kind),
78            Self::Constant(..) => "Constant".to_string(),
79            Self::Assignment(..) => "Assignment".to_string(),
80            Self::Argument(..) => "Argument".to_string(),
81            Self::Alias(..) => "Alias".to_string(),
82            Self::UseAll(..) => "UseAll".to_string(),
83            #[cfg(test)]
84            Self::Tester(..) => "Tester".to_string(),
85        }
86    }
87
88    pub(crate) fn source_hash(&self) -> u64 {
89        match self {
90            Self::SourceFile(sf) => sf.hash,
91            Self::Module(md) => md.src_ref().source_hash(),
92            Self::Workbench(wd) => wd.src_ref().source_hash(),
93            Self::Function(fd) => fd.src_ref().source_hash(),
94            Self::Builtin(_) => 0,
95            Self::Assignment(a) => a.src_ref.source_hash(),
96            Self::Constant(_, id, _) | Self::Argument(id, _) | Self::Alias(_, id, _) => {
97                id.src_ref().source_hash()
98            }
99            Self::UseAll(_, name) => name.src_ref().source_hash(),
100            #[cfg(test)]
101            Self::Tester(..) => 0,
102        }
103    }
104}
105
106impl std::fmt::Display for SymbolDef {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        let kind = self.kind_str();
109        match self {
110            Self::Workbench(..)
111            | Self::Module(..)
112            | Self::Function(..)
113            | Self::SourceFile(..)
114            | Self::Builtin(..) => write!(f, "({kind})"),
115            Self::Constant(.., value) => write!(f, "({kind}) = {value}"),
116            Self::Assignment(.., value) => write!(f, "({kind}) = {value}"),
117            Self::Argument(.., value) => write!(f, "({kind}) = {value}"),
118            Self::Alias(.., name) => write!(f, "({kind}) => {name}"),
119            Self::UseAll(.., name) => write!(f, "({kind}) => {name}"),
120            #[cfg(test)]
121            Self::Tester(id) => write!(f, "(Tester) => {id}"),
122        }
123    }
124}
125
126impl std::fmt::Debug for SymbolDef {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        let kind = self.kind_str();
129        match self {
130            Self::Workbench(..)
131            | Self::Module(..)
132            | Self::Function(..)
133            | Self::SourceFile(..)
134            | Self::Builtin(..) => write!(f, "({kind})"),
135            Self::Constant(.., value) => write!(f, "({kind}) = {value}"),
136            Self::Assignment(.., expr) => write!(f, "({kind}) = {expr:?}"),
137            Self::Argument(.., value) => write!(f, "({kind}) = {value}"),
138            Self::Alias(.., name) => write!(f, "({kind}) => {name:?}"),
139            Self::UseAll(.., name) => write!(f, "({kind}) => {name:?}"),
140            #[cfg(test)]
141            Self::Tester(id) => write!(f, "({kind}) => {id:?}"),
142        }
143    }
144}
145
146impl Doc for SymbolDef {
147    fn doc(&self) -> Option<DocBlock> {
148        match self {
149            SymbolDef::SourceFile(sf) => sf.doc(),
150            SymbolDef::Module(md) => md.doc(),
151            SymbolDef::Workbench(wd) => wd.doc(),
152            SymbolDef::Function(fd) => fd.doc(),
153            _ => None,
154        }
155    }
156}
157
158impl Info for SymbolDef {
159    fn info(&self) -> SymbolInfo {
160        match self {
161            SymbolDef::SourceFile(sf) => sf.into(),
162            SymbolDef::Module(md) => md.into(),
163            SymbolDef::Workbench(wd) => wd.into(),
164            SymbolDef::Function(fd) => fd.into(),
165            SymbolDef::Builtin(bi) => bi.into(),
166            SymbolDef::Assignment(a) => a.into(),
167
168            SymbolDef::Constant(visibility, id, value) => {
169                SymbolInfo::new_constant(visibility, id, value)
170            }
171            SymbolDef::Argument(id, value) => SymbolInfo::new_arg(id, value),
172
173            SymbolDef::Alias(..) => unimplemented!(),
174            SymbolDef::UseAll(..) => unimplemented!(),
175
176            #[cfg(test)]
177            SymbolDef::Tester(_) => unreachable!(),
178        }
179    }
180}