knave_expand/modules/
registry.rs1use 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}