erg_compiler/module/
index.rs1use std::collections::hash_map::{Iter, Keys, Values};
2use std::fmt;
3
4use erg_common::dict::Dict;
5use erg_common::pathutil::NormalizedPathBuf;
6use erg_common::set;
7use erg_common::set::Set;
8use erg_common::shared::{MappedRwLockReadGuard, RwLockReadGuard, Shared};
9use erg_common::Str;
10
11use crate::varinfo::{AbsLocation, VarInfo};
12
13pub struct Members<'a>(MappedRwLockReadGuard<'a, Dict<AbsLocation, ModuleIndexValue>>);
14
15impl Members<'_> {
16 pub fn iter(&self) -> Iter<'_, AbsLocation, ModuleIndexValue> {
17 self.0.iter()
18 }
19
20 pub fn keys(&self) -> Keys<'_, AbsLocation, ModuleIndexValue> {
21 self.0.keys()
22 }
23
24 pub fn values(&self) -> Values<'_, AbsLocation, ModuleIndexValue> {
25 self.0.values()
26 }
27}
28
29#[derive(Debug, Clone)]
30pub struct ModuleIndexValue {
31 pub name: Str,
32 pub vi: VarInfo,
33 pub referrers: Set<AbsLocation>,
34}
35
36impl fmt::Display for ModuleIndexValue {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 write!(
39 f,
40 "{{ name: {}, vi: {}, referrers: {} }}",
41 self.name, self.vi, self.referrers
42 )
43 }
44}
45
46impl ModuleIndexValue {
47 pub const fn new(name: Str, vi: VarInfo, referrers: Set<AbsLocation>) -> Self {
48 Self {
49 name,
50 vi,
51 referrers,
52 }
53 }
54
55 pub fn push_ref(&mut self, referrer: AbsLocation) {
56 self.referrers.insert(referrer);
57 }
58}
59
60#[derive(Debug, Clone, Default)]
61pub struct ModuleIndex {
62 members: Dict<AbsLocation, ModuleIndexValue>,
63}
64
65impl fmt::Display for ModuleIndex {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 self.members.fmt(f)
68 }
69}
70
71impl ModuleIndex {
72 pub fn new() -> Self {
73 Self {
74 members: Dict::new(),
75 }
76 }
77
78 pub fn inc_ref(&mut self, name: &Str, vi: &VarInfo, referrer: AbsLocation) {
79 let referee = vi.def_loc.clone();
80 if let Some(referrers) = self.members.get_mut(&referee) {
81 referrers.push_ref(referrer);
82 } else {
83 let value = ModuleIndexValue::new(name.clone(), vi.clone(), set! {referrer});
84 self.members.insert(referee, value);
85 }
86 }
87
88 pub fn register(&mut self, name: Str, vi: &VarInfo) {
89 if self.members.contains_key(&vi.def_loc) {
90 return;
91 }
92 let referee = vi.def_loc.clone();
93 let value = ModuleIndexValue::new(name, vi.clone(), set! {});
94 self.members.insert(referee, value);
95 }
96
97 pub fn get_refs(&self, referee: &AbsLocation) -> Option<&ModuleIndexValue> {
98 self.members.get(referee)
99 }
100
101 pub fn initialize(&mut self) {
102 self.members.clear();
103 }
104
105 pub fn remove_path(&mut self, path: &NormalizedPathBuf) {
106 self.members.retain(|loc, value| {
107 value
108 .referrers
109 .retain(|ref_loc| ref_loc.module.as_deref() != Some(path));
110 loc.module.as_deref() != Some(path)
111 });
112 }
113
114 pub fn rename_path(&mut self, old: &NormalizedPathBuf, new: NormalizedPathBuf) {
115 let mut new_members = Dict::new();
116 for (loc, mut value) in std::mem::take(&mut self.members) {
117 if value.vi.def_loc.module.as_deref() == Some(old) {
118 value.vi.def_loc.module = Some(new.clone());
119 }
120 let mut new_referrers = set! {};
121 for referee in value.referrers.into_iter() {
122 if referee.module.as_deref() == Some(old) {
123 new_referrers.insert(AbsLocation {
124 module: Some(new.clone()),
125 ..referee
126 });
127 } else {
128 new_referrers.insert(referee);
129 }
130 }
131 value.referrers = new_referrers;
132 if loc.module.as_deref() != Some(old) {
133 new_members.insert(loc.clone(), value.clone());
134 } else {
135 new_members.insert(
136 AbsLocation {
137 module: Some(new.clone()),
138 ..loc
139 },
140 value,
141 );
142 }
143 }
144 self.members = new_members;
145 }
146}
147
148#[derive(Debug, Clone, Default)]
149pub struct SharedModuleIndex(Shared<ModuleIndex>);
150
151impl fmt::Display for SharedModuleIndex {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 self.0.borrow().fmt(f)
154 }
155}
156
157impl SharedModuleIndex {
158 pub fn new() -> Self {
159 Self(Shared::new(ModuleIndex::new()))
160 }
161
162 pub fn inc_ref(&self, name: &Str, vi: &VarInfo, referrer: AbsLocation) {
163 self.0.borrow_mut().inc_ref(name, vi, referrer);
164 }
165
166 pub fn register(&self, name: Str, vi: &VarInfo) {
167 self.0.borrow_mut().register(name, vi);
168 }
169
170 pub fn get_refs(
171 &self,
172 referee: &AbsLocation,
173 ) -> Option<MappedRwLockReadGuard<'_, ModuleIndexValue>> {
174 RwLockReadGuard::try_map(self.0.borrow(), |index| index.get_refs(referee)).ok()
175 }
176
177 pub fn members(&self) -> Members<'_> {
178 Members(RwLockReadGuard::map(self.0.borrow(), |mi| &mi.members))
179 }
180
181 pub fn initialize(&self) {
182 self.0.borrow_mut().initialize();
183 }
184
185 pub fn remove_path(&self, path: &NormalizedPathBuf) {
186 self.0.borrow_mut().remove_path(path);
187 }
188
189 pub fn rename_path(&self, old: &NormalizedPathBuf, new: NormalizedPathBuf) {
190 self.0.borrow_mut().rename_path(old, new);
191 }
192}