1use std::collections::HashMap;
10use std::sync::Arc;
11use std::sync::RwLock;
12use std::sync::Weak;
13use crate::error::*;
14use crate::utils::*;
15
16#[derive(Clone, Debug)]
22pub enum ModNodeRef<T, U>
23{
24 Arc(Arc<RwLock<ModNode<T, U>>>),
26 Weak(Weak<RwLock<ModNode<T, U>>>),
28}
29
30impl<T, U> ModNodeRef<T, U>
31{
32 pub fn to_arc(&self) -> Option<Arc<RwLock<ModNode<T, U>>>>
33 {
34 match self {
35 ModNodeRef::Arc(arc) => Some(arc.clone()),
36 ModNodeRef::Weak(weak) => weak.upgrade(),
37 }
38 }
39}
40
41#[derive(Clone, Debug)]
46pub struct UsedVar<T, U>
47{
48 mod1: ModNodeRef<T, U>,
49 ident: String,
50}
51
52impl<T, U> UsedVar<T, U>
53{
54 pub fn new(mod1: ModNodeRef<T, U>, ident: String) -> Self
56 { UsedVar { mod1, ident, } }
57
58 pub fn mod1(&self) -> &ModNodeRef<T, U>
60 { &self.mod1 }
61
62 pub fn ident(&self) -> &String
64 { &self.ident }
65}
66
67#[derive(Clone, Debug)]
74pub struct ModNode<T, U>
75{
76 used_mods: HashMap<String, ModNodeRef<T, U>>,
77 used_vars: HashMap<String, UsedVar<T, U>>,
78 mods: HashMap<String, Arc<RwLock<ModNode<T, U>>>>,
79 vars: HashMap<String, T>,
80 parent: Option<Weak<RwLock<ModNode<T, U>>>>,
81 value: U,
82}
83
84impl<T, U> ModNode<T, U>
85{
86 pub fn new(value: U) -> Self
88 {
89 ModNode {
90 used_mods: HashMap::new(),
91 used_vars: HashMap::new(),
92 mods: HashMap::new(),
93 vars: HashMap::new(),
94 parent: None,
95 value,
96 }
97 }
98
99 pub fn used_mods(&self) -> &HashMap<String, ModNodeRef<T, U>>
101 { &self.used_mods }
102
103 pub fn has_used_mod(&self, ident: &String) -> bool
105 { self.used_mods.contains_key(ident) }
106
107 pub fn used_mod(&self, ident: &String) -> Option<&ModNodeRef<T, U>>
110 { self.used_mods.get(ident) }
111
112 fn mod_to_mod_ref(mod1: &Arc<RwLock<ModNode<T, U>>>, mod2: Arc<RwLock<ModNode<T, U>>>) -> Result<ModNodeRef<T, U>>
113 {
114 let mut node = Some(mod1.clone());
115 loop {
116 match &node {
117 Some(tmp_node) => {
118 if Arc::ptr_eq(&tmp_node, &mod2) {
119 return Ok(ModNodeRef::Weak(Arc::downgrade(&mod2)));
120 }
121 let parent = {
122 let tmp_node_g = rw_lock_read(&**tmp_node)?;
123 tmp_node_g.parent()
124 };
125 node = parent;
126 },
127 None => break,
128 }
129 }
130 Ok(ModNodeRef::Arc(mod2.clone()))
131 }
132
133 pub fn add_used_mod(mod1: &Arc<RwLock<ModNode<T, U>>>, ident: String, used_mod: Arc<RwLock<ModNode<T, U>>>) -> Result<()>
135 {
136 let used_mod_ref = Self::mod_to_mod_ref(mod1, used_mod)?;
137 let mut mod_g = rw_lock_write(&**mod1)?;
138 mod_g.used_mods.insert(ident, used_mod_ref);
139 Ok(())
140 }
141
142 pub fn remove_used_mod(&mut self, ident: &String)
144 { self.used_mods.remove(ident); }
145
146 pub fn used_vars(&self) -> &HashMap<String, UsedVar<T, U>>
148 { &self.used_vars }
149
150 pub fn has_used_var(&self, ident: &String) -> bool
152 { self.used_vars.contains_key(ident) }
153
154 pub fn used_var(&self, ident: &String) -> Option<&UsedVar<T, U>>
157 { self.used_vars.get(ident) }
158
159 pub fn add_used_var(mod1: &Arc<RwLock<ModNode<T, U>>>, ident: String, used_var_mod: Arc<RwLock<ModNode<T, U>>>, used_var_ident: String) -> Result<()>
161 {
162 let used_var_mod_ref = Self::mod_to_mod_ref(mod1, used_var_mod)?;
163 let mut mod_g = rw_lock_write(&**mod1)?;
164 mod_g.used_vars.insert(ident, UsedVar::new(used_var_mod_ref, used_var_ident));
165 Ok(())
166 }
167
168 pub fn remove_used_var(&mut self, ident: &String)
170 { self.used_vars.remove(ident); }
171
172 pub fn mods(&self) -> &HashMap<String, Arc<RwLock<ModNode<T, U>>>>
174 { &self.mods }
175
176 pub fn has_mod(&self, ident: &String) -> bool
178 { self.mods.contains_key(ident) }
179
180 pub fn mod1(&self, ident: &String) -> Option<&Arc<RwLock<ModNode<T, U>>>>
182 { self.mods.get(ident) }
183
184 pub fn add_mod(parent: &Arc<RwLock<ModNode<T, U>>>, ident: String, child: Arc<RwLock<ModNode<T, U>>>) -> Result<()>
186 {
187 {
188 let mut child_g = rw_lock_write(&*child)?;
189 if child_g.parent.is_some() {
190 return Err(Error::AlreadyAddedModNode);
191 }
192 child_g.parent = Some(Arc::downgrade(&parent));
193 }
194 let mut parent_g = rw_lock_write(&**parent)?;
195 parent_g.remove_mod(&ident)?;
196 parent_g.mods.insert(ident, child);
197 Ok(())
198 }
199
200 pub fn remove_mod(&mut self, ident: &String) -> Result<()>
202 {
203 match self.mods.get(ident) {
204 Some(child) => {
205 {
206 let mut child_g = rw_lock_write(&*child)?;
207 child_g.parent = None;
208 }
209 self.mods.remove(ident);
210 Ok(())
211 },
212 None => Ok(()),
213 }
214 }
215
216 pub fn vars(&self) -> &HashMap<String, T>
218 { &self.vars }
219
220 pub fn has_var(&self, ident: &String) -> bool
222 { self.vars.contains_key(ident) }
223
224 pub fn var(&self, ident: &String) -> Option<&T>
226 { self.vars.get(ident) }
227
228 pub fn add_var(&mut self, ident: String, value: T)
230 { self.vars.insert(ident, value); }
231
232 pub fn remove_var(&mut self, ident: &String)
234 { self.vars.remove(ident); }
235
236 pub fn parent(&self) -> Option<Arc<RwLock<ModNode<T, U>>>>
238 {
239 match &self.parent{
240 Some(parent) => parent.upgrade(),
241 None => None,
242 }
243 }
244
245 pub fn value(&self) -> &U
247 { &self.value }
248
249 pub fn set_value(&mut self, value: U)
251 { self.value = value; }
252
253 pub fn mod_from(root: &Arc<RwLock<ModNode<T, U>>>, idents: &[String], are_used_mods: bool) -> Result<Option<Arc<RwLock<ModNode<T, U>>>>>
258 {
259 let mut node = root.clone();
260 let mut is_first = true;
261 for ident in idents {
262 let child: Arc<RwLock<ModNode<T, U>>>;
263 {
264 let node_g = rw_lock_read(&*node)?;
265 child = match node_g.mods.get(ident) {
266 Some(tmp_child) => tmp_child.clone(),
267 None => {
268 if is_first && are_used_mods {
269 match node_g.used_mods.get(ident) {
270 Some(tmp_child) => {
271 match tmp_child.to_arc() {
272 Some(child_arc) => child_arc,
273 None => return Ok(None),
274 }
275 },
276 None => return Ok(None),
277 }
278 } else {
279 return Ok(None);
280 }
281 },
282 };
283 };
284 node = child;
285 is_first = false;
286 }
287 Ok(Some(node))
288 }
289}
290
291#[cfg(test)]
292mod tests;