rue_hir/
database.rs

1use std::collections::HashMap;
2
3use id_arena::Arena;
4use indexmap::IndexSet;
5use rue_diagnostic::SourceKind;
6use rue_types::{Type, TypeId};
7
8use crate::{Hir, HirId, Import, ImportId, ModuleSymbol, Scope, ScopeId, Symbol, SymbolId};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum Declaration {
12    Symbol(SymbolId),
13    Type(TypeId),
14}
15
16#[derive(Debug, Clone)]
17pub struct Test {
18    pub name: Option<String>,
19    pub path: SourceKind,
20    pub symbol: SymbolId,
21}
22
23#[derive(Debug, Default, Clone)]
24pub struct Database {
25    hir: Arena<Hir>,
26    scopes: Arena<Scope>,
27    imports: Arena<Import>,
28    symbols: Arena<Symbol>,
29    types: Arena<Type>,
30    relevant_declarations: IndexSet<Declaration>,
31    declared_by: HashMap<Declaration, IndexSet<Declaration>>,
32    referenced_by: HashMap<Declaration, IndexSet<Declaration>>,
33    relevant_imports: IndexSet<ImportId>,
34    import_references: HashMap<ImportId, IndexSet<Declaration>>,
35    tests: Vec<Test>,
36}
37
38impl Database {
39    pub fn new() -> Self {
40        Self::default()
41    }
42
43    pub fn alloc_hir(&mut self, hir: Hir) -> HirId {
44        self.hir.alloc(hir)
45    }
46
47    pub fn hir(&self, id: HirId) -> &Hir {
48        &self.hir[id]
49    }
50
51    pub fn hir_mut(&mut self, id: HirId) -> &mut Hir {
52        &mut self.hir[id]
53    }
54
55    pub fn alloc_scope(&mut self, scope: Scope) -> ScopeId {
56        self.scopes.alloc(scope)
57    }
58
59    pub fn scope(&self, id: ScopeId) -> &Scope {
60        &self.scopes[id]
61    }
62
63    pub fn scope_mut(&mut self, id: ScopeId) -> &mut Scope {
64        &mut self.scopes[id]
65    }
66
67    pub fn alloc_import(&mut self, import: Import) -> ImportId {
68        self.imports.alloc(import)
69    }
70
71    pub fn import(&self, id: ImportId) -> &Import {
72        &self.imports[id]
73    }
74
75    pub fn import_mut(&mut self, id: ImportId) -> &mut Import {
76        &mut self.imports[id]
77    }
78
79    pub fn alloc_symbol(&mut self, symbol: Symbol) -> SymbolId {
80        self.symbols.alloc(symbol)
81    }
82
83    pub fn symbol(&self, id: SymbolId) -> &Symbol {
84        &self.symbols[id]
85    }
86
87    pub fn symbol_mut(&mut self, id: SymbolId) -> &mut Symbol {
88        &mut self.symbols[id]
89    }
90
91    pub fn module(&self, id: SymbolId) -> &ModuleSymbol {
92        match self.symbol(id) {
93            Symbol::Module(module) => module,
94            _ => unreachable!(),
95        }
96    }
97
98    pub fn module_mut(&mut self, id: SymbolId) -> &mut ModuleSymbol {
99        match self.symbol_mut(id) {
100            Symbol::Module(module) => module,
101            _ => unreachable!(),
102        }
103    }
104
105    pub fn alloc_type(&mut self, ty: Type) -> TypeId {
106        self.types.alloc(ty)
107    }
108
109    pub fn ty(&self, id: TypeId) -> &Type {
110        &self.types[id]
111    }
112
113    pub fn ty_mut(&mut self, id: TypeId) -> &mut Type {
114        &mut self.types[id]
115    }
116
117    pub fn types(&self) -> &Arena<Type> {
118        &self.types
119    }
120
121    pub fn types_mut(&mut self) -> &mut Arena<Type> {
122        &mut self.types
123    }
124
125    pub fn add_relevant_declaration(&mut self, declaration: Declaration) {
126        self.relevant_declarations.insert(declaration);
127    }
128
129    pub fn relevant_declarations(&self) -> impl Iterator<Item = Declaration> {
130        self.relevant_declarations.iter().copied()
131    }
132
133    pub fn add_reference(&mut self, outer: Declaration, inner: Declaration) {
134        self.referenced_by.entry(inner).or_default().insert(outer);
135    }
136
137    pub fn add_declaration(&mut self, outer: Declaration, inner: Declaration) {
138        self.declared_by.entry(inner).or_default().insert(outer);
139    }
140
141    pub fn reference_parents(&self, declaration: Declaration) -> Vec<Declaration> {
142        self.referenced_by
143            .get(&declaration)
144            .cloned()
145            .unwrap_or_default()
146            .into_iter()
147            .collect()
148    }
149
150    pub fn declaration_parents(&self, declaration: Declaration) -> Vec<Declaration> {
151        self.declared_by
152            .get(&declaration)
153            .cloned()
154            .unwrap_or_default()
155            .into_iter()
156            .collect()
157    }
158
159    pub fn add_relevant_import(&mut self, import: ImportId) {
160        self.relevant_imports.insert(import);
161    }
162
163    pub fn relevant_imports(&self) -> impl Iterator<Item = ImportId> {
164        self.relevant_imports.iter().copied()
165    }
166
167    pub fn add_import_reference(&mut self, import: ImportId, declaration: Declaration) {
168        self.import_references
169            .entry(import)
170            .or_default()
171            .insert(declaration);
172    }
173
174    pub fn import_references(&self, import: ImportId) -> Vec<Declaration> {
175        self.import_references
176            .get(&import)
177            .cloned()
178            .unwrap_or_default()
179            .into_iter()
180            .collect()
181    }
182
183    pub fn add_test(&mut self, test: Test) {
184        self.tests.push(test);
185    }
186
187    pub fn tests(&self) -> impl Iterator<Item = &Test> {
188        self.tests.iter()
189    }
190
191    pub fn debug_symbol(&self, id: SymbolId) -> String {
192        let name = self.symbol(id).name();
193
194        if let Some(name) = name {
195            format!("{}<{}>", name.text(), id.index())
196        } else {
197            format!("<{}>", id.index())
198        }
199    }
200
201    pub fn debug_hir(&self, id: HirId) -> String {
202        match self.hir(id) {
203            Hir::Unresolved => "{unknown}".to_string(),
204            Hir::Nil => "nil".to_string(),
205            Hir::String(value) => format!("\"{value}\""),
206            Hir::Int(value) => format!("{value}"),
207            Hir::Bytes(value) => {
208                if value.is_empty() {
209                    "nil".to_string()
210                } else {
211                    format!("0x{}", hex::encode(value))
212                }
213            }
214            Hir::Bool(value) => format!("{value}"),
215            Hir::Pair(first, rest) => {
216                format!("({}, {})", self.debug_hir(*first), self.debug_hir(*rest))
217            }
218            Hir::Reference(symbol) => self.debug_symbol(*symbol),
219            Hir::Block(block) => block
220                .body
221                .map_or("{empty}".to_string(), |body| self.debug_hir(body)),
222            Hir::Lambda(lambda) => self.debug_symbol(*lambda),
223            Hir::If(condition, then, else_, inline) => format!(
224                "{}if {} {{ {} }} else {{ {} }}",
225                if *inline { "inline " } else { "" },
226                self.debug_hir(*condition),
227                self.debug_hir(*then),
228                self.debug_hir(*else_)
229            ),
230            Hir::FunctionCall(call) => format!(
231                "{}({})",
232                self.debug_hir(call.function),
233                call.args
234                    .iter()
235                    .enumerate()
236                    .map(|(i, arg)| {
237                        let arg = self.debug_hir(*arg);
238
239                        if i == call.args.len() - 1 && !call.nil_terminated {
240                            format!("...{arg}")
241                        } else {
242                            arg
243                        }
244                    })
245                    .collect::<Vec<_>>()
246                    .join(", ")
247            ),
248            Hir::Unary(op, hir) => format!("({op} {})", self.debug_hir(*hir)),
249            Hir::Binary(op, left, right) => {
250                format!(
251                    "({} {} {})",
252                    self.debug_hir(*left),
253                    op,
254                    self.debug_hir(*right)
255                )
256            }
257            Hir::CoinId(parent, puzzle, amount) => {
258                format!(
259                    "coinid({}, {}, {})",
260                    self.debug_hir(*parent),
261                    self.debug_hir(*puzzle),
262                    self.debug_hir(*amount)
263                )
264            }
265            Hir::Substr(hir, start, end) => {
266                if let Some(end) = end {
267                    format!(
268                        "substr({}, {}, {})",
269                        self.debug_hir(*hir),
270                        self.debug_hir(*start),
271                        self.debug_hir(*end)
272                    )
273                } else {
274                    format!(
275                        "substr({}, {})",
276                        self.debug_hir(*hir),
277                        self.debug_hir(*start)
278                    )
279                }
280            }
281            Hir::G1Map(data, dst) => {
282                if let Some(dst) = dst {
283                    format!(
284                        "g1_map({}, {})",
285                        self.debug_hir(*data),
286                        self.debug_hir(*dst)
287                    )
288                } else {
289                    format!("g1_map({})", self.debug_hir(*data))
290                }
291            }
292            Hir::G2Map(data, dst) => {
293                if let Some(dst) = dst {
294                    format!(
295                        "g2_map({}, {})",
296                        self.debug_hir(*data),
297                        self.debug_hir(*dst)
298                    )
299                } else {
300                    format!("g2_map({})", self.debug_hir(*data))
301                }
302            }
303            Hir::Modpow(base, exponent, modulus) => {
304                format!(
305                    "modpow({}, {}, {})",
306                    self.debug_hir(*base),
307                    self.debug_hir(*exponent),
308                    self.debug_hir(*modulus)
309                )
310            }
311            Hir::BlsPairingIdentity(args) => {
312                format!(
313                    "bls_pairing_identity({})",
314                    args.iter()
315                        .map(|arg| self.debug_hir(*arg))
316                        .collect::<Vec<_>>()
317                        .join(", ")
318                )
319            }
320            Hir::BlsVerify(sig, args) => {
321                format!(
322                    "bls_verify({}, {})",
323                    self.debug_hir(*sig),
324                    args.iter()
325                        .map(|arg| self.debug_hir(*arg))
326                        .collect::<Vec<_>>()
327                        .join(", ")
328                )
329            }
330            Hir::Secp256K1Verify(sig, pk, msg) => {
331                format!(
332                    "secp256k1_verify({}, {}, {})",
333                    self.debug_hir(*sig),
334                    self.debug_hir(*pk),
335                    self.debug_hir(*msg)
336                )
337            }
338            Hir::Secp256R1Verify(sig, pk, msg) => {
339                format!(
340                    "secp256r1_verify({}, {}, {})",
341                    self.debug_hir(*sig),
342                    self.debug_hir(*pk),
343                    self.debug_hir(*msg)
344                )
345            }
346            Hir::InfinityG1 => "INFINITY_G1".to_string(),
347            Hir::InfinityG2 => "INFINITY_G2".to_string(),
348            Hir::ClvmOp(op, args) => {
349                format!("{:?}({})", op, self.debug_hir(*args))
350            }
351        }
352    }
353}