knave_expand/modules/
registry.rs1use std::rc::Rc;
2
3use rustc_hash::FxHashMap;
4
5use super::module_scopes::ModuleScopes;
6use crate::core::{BindingId, ModuleId, ModulePath, Namespace};
7use crate::reader::Symbol;
8use crate::scope::ScopeSet;
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
11enum LoadStatus {
12 Loading,
13 Loaded,
14}
15
16#[derive(serde::Serialize, serde::Deserialize)]
17pub struct ModuleRecord {
18 path: ModulePath,
19 scopes: ModuleScopes,
20 exports: FxHashMap<(Rc<str>, Namespace), BindingId>,
21 status: LoadStatus,
22}
23
24impl ModuleRecord {
25 pub fn path(&self) -> &ModulePath {
26 &self.path
27 }
28
29 pub fn scopes(&self) -> ModuleScopes {
30 self.scopes
31 }
32
33 pub fn symbol(&self) -> Symbol {
34 Symbol::with_scopes(self.path.as_str(), self.scopes.set())
35 }
36
37 pub fn export(&mut self, name: Rc<str>, namespace: Namespace, binding: BindingId) {
38 self.exports.insert((name, namespace), binding);
39 }
40
41 pub fn exported(&self, name: &str, namespace: Namespace) -> Option<BindingId> {
42 self.exports.get(&(Rc::from(name), namespace)).copied()
43 }
44
45 pub fn exports(&self) -> impl Iterator<Item = (&Rc<str>, Namespace, BindingId)> {
46 self.exports
47 .iter()
48 .map(|((name, namespace), binding)| (name, *namespace, *binding))
49 }
50
51 pub fn is_loading(&self) -> bool {
52 self.status == LoadStatus::Loading
53 }
54}
55
56#[derive(Default)]
57pub struct ModuleRegistry {
58 records: Vec<ModuleRecord>,
59 by_path: FxHashMap<ModulePath, ModuleId>,
60}
61
62impl ModuleRegistry {
63 pub fn register(&mut self, path: ModulePath, scopes: ModuleScopes) -> ModuleId {
64 self.adopt(ModuleRecord {
65 path,
66 scopes,
67 exports: FxHashMap::default(),
68 status: LoadStatus::Loading,
69 })
70 }
71
72 pub fn adopt(&mut self, record: ModuleRecord) -> ModuleId {
73 let id = ModuleId::new(self.records.len());
74 self.by_path.insert(record.path.clone(), id);
75 self.records.push(record);
76 id
77 }
78
79 pub fn into_records_after(mut self, id: ModuleId) -> Vec<ModuleRecord> {
80 self.records.split_off(id.index() + 1)
81 }
82
83 pub fn find(&self, path: &ModulePath) -> Option<ModuleId> {
84 self.by_path.get(path).copied()
85 }
86
87 pub fn finish_loading(&mut self, id: ModuleId) {
88 self.records[id.index()].status = LoadStatus::Loaded;
89 }
90
91 pub fn loading_paths(&self) -> Vec<&ModulePath> {
92 self.records
93 .iter()
94 .filter(|record| record.is_loading())
95 .map(ModuleRecord::path)
96 .collect()
97 }
98
99 pub fn with_body_scopes(&self, scopes: &ScopeSet) -> Option<ModuleId> {
100 self.records
101 .iter()
102 .position(|record| record.scopes.set() == *scopes)
103 .map(ModuleId::new)
104 }
105
106 pub fn records(&self) -> impl Iterator<Item = &ModuleRecord> {
107 self.records.iter()
108 }
109
110 pub fn get(&self, id: ModuleId) -> &ModuleRecord {
111 &self.records[id.index()]
112 }
113
114 pub fn get_mut(&mut self, id: ModuleId) -> &mut ModuleRecord {
115 &mut self.records[id.index()]
116 }
117}