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}