Skip to main content

knave_expand/modules/
registry.rs

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