Skip to main content

knave_expand/modules/
registry.rs

1use 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}