swamp_script_semantic/
modules.rs1use crate::ns::{ResolvedModuleNamespace, ResolvedModuleNamespaceRef};
6use crate::{
7 ConstantId, ResolvedConstant, ResolvedConstantRef, ResolvedDefinition, ResolvedExpression,
8 SemanticError,
9};
10use seq_map::SeqMap;
11use seq_set::SeqSet;
12use std::cell::RefCell;
13use std::collections::{HashMap, VecDeque};
14use std::fmt::{Debug, Formatter};
15use std::rc::Rc;
16
17#[derive(Debug)]
18pub struct ResolvedModules {
19 pub modules: HashMap<Vec<String>, ResolvedModuleRef>,
20 pub constants: Vec<ResolvedConstantRef>,
21 pub constants_in_eval_order: Vec<ResolvedConstantRef>,
22}
23
24impl Default for ResolvedModules {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30pub struct ResolvedModule {
31 pub definitions: Vec<ResolvedDefinition>,
32 pub expression: Option<ResolvedExpression>,
33 pub namespace: ResolvedModuleNamespaceRef,
34}
35
36impl Debug for ResolvedModule {
37 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38 for resolved_def in &self.definitions {
39 writeln!(f, "{resolved_def:?}")?;
40 }
41
42 if !self.definitions.is_empty() && self.expression.is_some() {
43 writeln!(f, "---\n")?;
44 }
45
46 if let Some(resolved_expression) = &self.expression {
47 match resolved_expression {
48 ResolvedExpression::Block(expressions) => {
49 for expression in expressions {
50 writeln!(f, "{expression:?}")?;
51 }
52 }
53 _ => writeln!(f, "{resolved_expression:?}")?,
54 }
55 }
56
57 Ok(())
58 }
59}
60
61pub type ResolvedModuleRef = Rc<RefCell<ResolvedModule>>;
62
63impl ResolvedModule {
64 pub fn new(module_path: &[String]) -> Self {
65 let ns_ref = Rc::new(RefCell::new(ResolvedModuleNamespace::new(module_path)));
66 Self {
67 definitions: Vec::new(),
68 namespace: ns_ref,
69 expression: None,
70 }
71 }
72}
73
74impl ResolvedModules {
75 pub fn new() -> Self {
76 Self {
77 modules: HashMap::new(),
78 constants: Vec::new(),
79 constants_in_eval_order: Vec::new(),
80 }
81 }
82 pub fn add(&mut self, module: ResolvedModuleRef) {
83 self.modules.insert(
84 module.clone().borrow().namespace.borrow().path.clone(),
85 module,
86 );
87 }
88
89 pub fn add_constant(&mut self, resolved_constant: ResolvedConstant) -> ResolvedConstantRef {
90 let id = self.constants.len();
91 let mut copy = resolved_constant;
92 copy.id = id as ConstantId;
93 let constant_ref = Rc::new(copy);
94 self.constants.push(constant_ref.clone());
95
96 constant_ref
97 }
98
99 pub fn finalize(&mut self) -> Result<(), SemanticError> {
100 self.constants_in_eval_order = self.eval_ordered_constants()?;
101
102 Ok(())
103 }
104
105 fn eval_ordered_constants(&self) -> Result<Vec<ResolvedConstantRef>, SemanticError> {
106 Self::topological_sort_constants(&self.constants)
107 }
108
109 pub fn topological_sort_constants(
110 constants: &[ResolvedConstantRef],
111 ) -> Result<Vec<ResolvedConstantRef>, SemanticError> {
112 let mut id_to_constant: SeqMap<ConstantId, ResolvedConstantRef> = SeqMap::new();
113 for const_ref in constants {
114 id_to_constant
115 .insert(const_ref.id, Rc::clone(const_ref))
116 .map_err(|_| SemanticError::DuplicateConstantId(const_ref.id))?;
117 }
118
119 let mut adjacency: SeqMap<ConstantId, SeqSet<ConstantId>> = SeqMap::new();
120 let mut number_of_dependencies: SeqMap<ConstantId, usize> = SeqMap::new();
121
122 for const_ref in constants {
123 number_of_dependencies
124 .insert(const_ref.id, 0)
125 .map_err(|_| SemanticError::DuplicateConstantId(const_ref.id))?;
126
127 let mut deps = SeqSet::new();
128 const_ref.expr.collect_constant_dependencies(&mut deps);
129
130 for dep_id in &deps {
131 assert!(id_to_constant.contains_key(dep_id));
132
133 if let Some(dependents) = adjacency.get_mut(dep_id) {
134 dependents.insert(const_ref.id);
135 } else {
136 let mut dependents = SeqSet::new();
137 dependents.insert(const_ref.id);
138 adjacency
139 .insert(*dep_id, dependents)
140 .map_err(|_| SemanticError::DuplicateConstantId(const_ref.id))?;
141 }
142
143 let dependency_count = number_of_dependencies
144 .get_mut(&const_ref.id)
145 .expect("dependency count should have been inserted earlier");
146 *dependency_count += 1;
147 }
148 }
149
150 let mut queue: VecDeque<ConstantId> = number_of_dependencies
151 .iter()
152 .filter_map(|(id, &dependency_count)| {
153 if dependency_count == 0 {
154 Some(*id)
155 } else {
156 None
157 }
158 })
159 .collect();
160
161 let mut sorted_constants: Vec<ResolvedConstantRef> = Vec::new();
162
163 while let Some(current_id) = queue.pop_front() {
164 let current_const = id_to_constant
165 .get(¤t_id)
166 .expect("should have a id to constant lookup");
167
168 sorted_constants.push(Rc::clone(current_const));
169
170 if let Some(dependents) = adjacency.get(¤t_id) {
171 for dependent_id in dependents {
172 let dependency_count = number_of_dependencies
173 .get_mut(dependent_id)
174 .expect("should have number of dependencies");
175 assert!(*dependency_count > 0);
176 *dependency_count -= 1;
177 if *dependency_count == 0 {
178 queue.push_back(*dependent_id);
179 }
180 }
181 }
182 }
183
184 if sorted_constants.len() != constants.len() {
185 let unsorted_ids: Vec<ConstantId> = constants
186 .iter()
187 .map(|c| c.id)
188 .filter(|id| !sorted_constants.iter().any(|c| c.id == *id))
189 .collect();
190
191 return Err(SemanticError::CircularConstantDependency(unsorted_ids));
192 }
193
194 Ok(sorted_constants)
195 }
196
197 pub fn add_empty_module(&mut self, module_path: &[String]) -> ResolvedModuleRef {
198 let ns_ref = Rc::new(RefCell::new(ResolvedModuleNamespace::new(module_path)));
199 let module = ResolvedModule {
200 definitions: vec![],
201 expression: None,
202 namespace: ns_ref,
203 };
204 let module_ref = Rc::new(RefCell::new(module));
205
206 self.modules
207 .insert(Vec::from(module_path), module_ref.clone());
208
209 module_ref
210 }
211
212 #[must_use]
213 pub fn contains_key(&self, module_path: &[String]) -> bool {
214 self.modules.contains_key(module_path)
215 }
216
217 #[must_use]
218 pub fn get(&self, module_path: &[String]) -> Option<ResolvedModuleRef> {
219 self.modules.get(module_path).cloned()
220 }
221}