sim_kernel/library/registry/
query.rs1use std::collections::BTreeSet;
2use std::sync::Arc;
3
4use crate::{
5 catalog::CatalogSnapshot,
6 id::{
7 ClassId, CodecId, FunctionId, MacroId, NumberDomainId, RuntimeId, ShapeId, SiteId, Symbol,
8 },
9 value::Value,
10};
11
12use super::Registry;
13use crate::library::{
14 ExportKind, LibBootDependency, LibBootReceipt, LibManifest, LibSourceSpec, LoadedLib,
15 RegisteredTest, Test,
16};
17
18impl Registry {
19 pub fn catalog_snapshot(&self) -> CatalogSnapshot {
21 CatalogSnapshot::from_store(&self.catalog)
22 }
23
24 pub fn libs(&self) -> &[LoadedLib] {
26 &self.libs
27 }
28
29 pub fn boot_receipt(
31 &self,
32 lib_id: crate::LibId,
33 requested_source: LibSourceSpec,
34 resolved_source: LibSourceSpec,
35 ) -> Option<LibBootReceipt> {
36 let loaded = self.libs.iter().find(|loaded| loaded.id == lib_id)?;
37 let dependencies = self
38 .load_dependencies
39 .get(&lib_id)
40 .into_iter()
41 .flat_map(|dependencies| dependencies.iter())
42 .filter_map(|dependency| {
43 let symbol = self
44 .libs
45 .iter()
46 .find(|loaded| loaded.id == *dependency)?
47 .manifest
48 .id
49 .clone();
50 Some(LibBootDependency {
51 lib_id: *dependency,
52 symbol,
53 })
54 })
55 .collect();
56 Some(LibBootReceipt {
57 lib_id,
58 requested_source,
59 resolved_source,
60 manifest: loaded.manifest.clone(),
61 dependencies,
62 exports: loaded.exports.clone(),
63 })
64 }
65
66 pub fn subset_for_libs(&self, libs: &[Symbol]) -> Self {
68 if libs.is_empty() {
69 return Self::default();
70 }
71
72 let allowed = libs.iter().cloned().collect::<BTreeSet<_>>();
73 let mut registry = self.clone();
74 registry
75 .libs
76 .retain(|loaded| allowed.contains(&loaded.manifest.id));
77 registry
78 .libs_by_symbol
79 .retain(|symbol, _| allowed.contains(symbol));
80 let allowed_ids = registry
81 .libs
82 .iter()
83 .map(|loaded| loaded.id)
84 .collect::<BTreeSet<_>>();
85 registry
86 .load_deltas
87 .retain(|lib_id, _| allowed_ids.contains(lib_id));
88 registry.load_dependencies.retain(|lib_id, dependencies| {
89 if !allowed_ids.contains(lib_id) {
90 return false;
91 }
92 dependencies.retain(|dependency| allowed_ids.contains(dependency));
93 true
94 });
95
96 let exported_symbols = registry
97 .libs
98 .iter()
99 .flat_map(|loaded| loaded.exports.iter())
100 .map(|record| (record.kind.clone(), record.symbol.clone()))
101 .collect::<BTreeSet<_>>();
102
103 registry.export_symbols.retain(|kind, symbols| {
104 symbols.retain(|symbol, _| exported_symbols.contains(&(kind.clone(), symbol.clone())));
105 !symbols.is_empty()
106 });
107
108 registry.class_symbol_cache.retain(|symbol, _| {
109 exported_symbols.contains(&(ExportKind::named(ExportKind::CLASS), symbol.clone()))
110 });
111 registry.function_symbol_cache.retain(|symbol, _| {
112 exported_symbols.contains(&(ExportKind::named(ExportKind::FUNCTION), symbol.clone()))
113 });
114 registry.macro_symbol_cache.retain(|symbol, _| {
115 exported_symbols.contains(&(ExportKind::named(ExportKind::MACRO), symbol.clone()))
116 });
117 registry.shape_symbol_cache.retain(|symbol, _| {
118 exported_symbols.contains(&(ExportKind::named(ExportKind::SHAPE), symbol.clone()))
119 });
120 registry.codec_symbol_cache.retain(|symbol, _| {
121 exported_symbols.contains(&(ExportKind::named(ExportKind::CODEC), symbol.clone()))
122 });
123 registry.number_domain_symbol_cache.retain(|symbol, _| {
124 exported_symbols
125 .contains(&(ExportKind::named(ExportKind::NUMBER_DOMAIN), symbol.clone()))
126 });
127 registry.site_symbol_cache.retain(|symbol, _| {
128 exported_symbols.contains(&(ExportKind::named(ExportKind::SITE), symbol.clone()))
129 });
130 registry.plain_value_cache.retain(|symbol, _| {
131 exported_symbols.contains(&(ExportKind::named(ExportKind::VALUE), symbol.clone()))
132 });
133
134 registry.class_value_cache.retain(|id, _| {
135 registry
136 .class_symbol_cache
137 .values()
138 .any(|value| value == id)
139 });
140 registry.function_value_cache.retain(|id, _| {
141 registry
142 .function_symbol_cache
143 .values()
144 .any(|value| value == id)
145 });
146 registry.macro_value_cache.retain(|id, _| {
147 registry
148 .macro_symbol_cache
149 .values()
150 .any(|value| value == id)
151 });
152 registry.shape_value_cache.retain(|id, _| {
153 registry
154 .shape_symbol_cache
155 .values()
156 .any(|value| value == id)
157 });
158 registry.codec_value_cache.retain(|id, _| {
159 registry
160 .codec_symbol_cache
161 .values()
162 .any(|value| value == id)
163 });
164 registry.number_domain_value_cache.retain(|id, _| {
165 registry
166 .number_domain_symbol_cache
167 .values()
168 .any(|value| value == id)
169 });
170 registry
171 .site_value_cache
172 .retain(|id, _| registry.site_symbol_cache.values().any(|value| value == id));
173 registry.tests.retain(|_, test| allowed.contains(&test.lib));
174 registry
175 .tests_by_lib
176 .retain(|symbol, _| allowed.contains(symbol));
177 registry.retain_catalog_rows_for_subset();
178 registry.rebuild_projection_caches_from_catalog();
179 registry
180 }
181
182 pub fn lib(&self, symbol: &Symbol) -> Option<&LoadedLib> {
184 let id = self.libs_by_symbol.get(symbol)?;
185 self.libs.iter().find(|loaded| loaded.id == *id)
186 }
187
188 pub(crate) fn lib_mut(&mut self, symbol: &Symbol) -> Option<&mut LoadedLib> {
189 let id = *self.libs_by_symbol.get(symbol)?;
190 self.libs.iter_mut().find(|loaded| loaded.id == id)
191 }
192
193 pub fn export_symbols(
195 &self,
196 ) -> &std::collections::BTreeMap<ExportKind, std::collections::BTreeMap<Symbol, crate::RuntimeId>>
197 {
198 &self.export_symbols
199 }
200
201 pub fn classes(&self) -> &std::collections::BTreeMap<Symbol, ClassId> {
203 &self.class_symbol_cache
204 }
205
206 pub fn functions(&self) -> &std::collections::BTreeMap<Symbol, FunctionId> {
208 &self.function_symbol_cache
209 }
210
211 pub fn macros(&self) -> &std::collections::BTreeMap<Symbol, MacroId> {
213 &self.macro_symbol_cache
214 }
215
216 pub fn shapes(&self) -> &std::collections::BTreeMap<Symbol, ShapeId> {
218 &self.shape_symbol_cache
219 }
220
221 pub fn codecs(&self) -> &std::collections::BTreeMap<Symbol, CodecId> {
223 &self.codec_symbol_cache
224 }
225
226 pub fn number_domains(&self) -> &std::collections::BTreeMap<Symbol, NumberDomainId> {
228 &self.number_domain_symbol_cache
229 }
230
231 pub fn sites(&self) -> &std::collections::BTreeMap<Symbol, SiteId> {
233 &self.site_symbol_cache
234 }
235
236 pub fn tests(&self) -> &std::collections::BTreeMap<Symbol, RegisteredTest> {
238 &self.tests
239 }
240
241 pub fn tests_for_lib(&self, symbol: &Symbol) -> Option<&[Symbol]> {
243 self.tests_by_lib.get(symbol).map(Vec::as_slice)
244 }
245
246 pub fn class_value(&self, id: ClassId) -> Option<&Value> {
248 self.catalog_value_by_runtime_id(RuntimeId::Class(id))
249 }
250
251 pub fn function_value(&self, id: FunctionId) -> Option<&Value> {
253 self.catalog_value_by_runtime_id(RuntimeId::Function(id))
254 }
255
256 pub fn macro_value(&self, id: MacroId) -> Option<&Value> {
258 self.catalog_value_by_runtime_id(RuntimeId::Macro(id))
259 }
260
261 pub fn shape_value(&self, id: ShapeId) -> Option<&Value> {
263 self.catalog_value_by_runtime_id(RuntimeId::Shape(id))
264 }
265
266 pub fn codec_value(&self, id: CodecId) -> Option<&Value> {
268 self.catalog_value_by_runtime_id(RuntimeId::Codec(id))
269 }
270
271 pub fn number_domain_value(&self, id: NumberDomainId) -> Option<&Value> {
273 self.catalog_value_by_runtime_id(RuntimeId::NumberDomain(id))
274 }
275
276 pub fn site_value(&self, id: RuntimeId) -> Option<&Value> {
278 match id {
279 RuntimeId::Site(_) => self.catalog_value_by_runtime_id(id),
280 _ => None,
281 }
282 }
283
284 pub fn class_by_symbol(&self, symbol: &Symbol) -> Option<&Value> {
286 self.catalog_value_by_export(&ExportKind::named(ExportKind::CLASS), symbol)
287 }
288
289 pub fn function_by_symbol(&self, symbol: &Symbol) -> Option<&Value> {
291 self.catalog_value_by_export(&ExportKind::named(ExportKind::FUNCTION), symbol)
292 }
293
294 pub fn macro_by_symbol(&self, symbol: &Symbol) -> Option<&Value> {
296 self.catalog_value_by_export(&ExportKind::named(ExportKind::MACRO), symbol)
297 }
298
299 pub fn shape_by_symbol(&self, symbol: &Symbol) -> Option<&Value> {
301 self.catalog_value_by_export(&ExportKind::named(ExportKind::SHAPE), symbol)
302 }
303
304 pub fn codec_by_symbol(&self, symbol: &Symbol) -> Option<&Value> {
306 self.catalog_value_by_export(&ExportKind::named(ExportKind::CODEC), symbol)
307 }
308
309 pub fn number_domain_by_symbol(&self, symbol: &Symbol) -> Option<&Value> {
311 self.catalog_value_by_export(&ExportKind::named(ExportKind::NUMBER_DOMAIN), symbol)
312 }
313
314 pub fn site_by_symbol(&self, symbol: &Symbol) -> Option<&Value> {
316 self.catalog_value_by_export(&ExportKind::named(ExportKind::SITE), symbol)
317 }
318
319 pub fn manifest_by_symbol(&self, symbol: &Symbol) -> Option<&LibManifest> {
321 self.lib(symbol).map(|loaded| &loaded.manifest)
322 }
323
324 pub fn test_by_symbol(&self, symbol: &Symbol) -> Option<&Arc<dyn Test>> {
326 self.tests.get(symbol).map(|test| &test.test)
327 }
328
329 pub fn registered_test(&self, symbol: &Symbol) -> Option<&RegisteredTest> {
331 self.tests.get(symbol)
332 }
333
334 pub fn value_by_symbol(&self, symbol: &Symbol) -> Option<&Value> {
336 self.catalog_value_by_export(&ExportKind::named(ExportKind::VALUE), symbol)
337 }
338
339 pub fn export_symbol_for_value(&self, value: &Value) -> Option<Symbol> {
342 self.class_symbol_cache
343 .iter()
344 .find_map(|(symbol, id)| {
345 self.class_value_cache
346 .get(id)
347 .filter(|candidate| *candidate == value)
348 .map(|_| symbol.clone())
349 })
350 .or_else(|| {
351 self.function_symbol_cache.iter().find_map(|(symbol, id)| {
352 self.function_value_cache
353 .get(id)
354 .filter(|candidate| *candidate == value)
355 .map(|_| symbol.clone())
356 })
357 })
358 .or_else(|| {
359 self.macro_symbol_cache.iter().find_map(|(symbol, id)| {
360 self.macro_value_cache
361 .get(id)
362 .filter(|candidate| *candidate == value)
363 .map(|_| symbol.clone())
364 })
365 })
366 .or_else(|| {
367 self.shape_symbol_cache.iter().find_map(|(symbol, id)| {
368 self.shape_value_cache
369 .get(id)
370 .filter(|candidate| *candidate == value)
371 .map(|_| symbol.clone())
372 })
373 })
374 .or_else(|| {
375 self.codec_symbol_cache.iter().find_map(|(symbol, id)| {
376 self.codec_value_cache
377 .get(id)
378 .filter(|candidate| *candidate == value)
379 .map(|_| symbol.clone())
380 })
381 })
382 .or_else(|| {
383 self.number_domain_symbol_cache
384 .iter()
385 .find_map(|(symbol, id)| {
386 self.number_domain_value_cache
387 .get(id)
388 .filter(|candidate| *candidate == value)
389 .map(|_| symbol.clone())
390 })
391 })
392 .or_else(|| {
393 self.plain_value_cache
394 .iter()
395 .find_map(|(symbol, candidate)| (candidate == value).then(|| symbol.clone()))
396 })
397 }
398}