conjure_core/ast/
symbol_table.rs1use super::serde::{RcRefCellAsId, RcRefCellAsInner};
6use std::cell::RefCell;
7use std::collections::btree_map::Entry;
8use std::collections::BTreeSet;
9use std::collections::{BTreeMap, VecDeque};
10use std::rc::Rc;
11use std::sync::atomic::{AtomicU32, Ordering};
12
13use super::declaration::Declaration;
14use super::serde::{DefaultWithId, HasId, ObjId};
15use super::types::Typeable;
16use itertools::izip;
17use serde::{Deserialize, Serialize};
18use serde_with::serde_as;
19use uniplate::Tree;
20use uniplate::{Biplate, Uniplate};
21
22use super::name::Name;
23use super::{Domain, Expression, ReturnType, SubModel};
24use derivative::Derivative;
25
26thread_local! {
35static ID_COUNTER: AtomicU32 = const { AtomicU32::new(0) };
36}
37
38#[derive(Derivative)]
73#[derivative(PartialEq)]
74#[derive(Debug, Eq)]
75#[serde_as]
76#[derive(Serialize, Deserialize)]
77pub struct SymbolTable {
78 #[serde_as(as = "Vec<(_,RcRefCellAsInner)>")]
79 table: BTreeMap<Name, Rc<Declaration>>,
80
81 #[derivative(PartialEq = "ignore")] id: ObjId,
84
85 #[serde_as(as = "Option<RcRefCellAsId>")]
86 parent: Option<Rc<RefCell<SymbolTable>>>,
87
88 next_machine_name: RefCell<i32>,
89}
90
91impl SymbolTable {
92 pub fn new() -> SymbolTable {
94 SymbolTable::new_inner(None)
95 }
96
97 pub fn with_parent(parent: Rc<RefCell<SymbolTable>>) -> SymbolTable {
99 SymbolTable::new_inner(Some(parent))
100 }
101
102 fn new_inner(parent: Option<Rc<RefCell<SymbolTable>>>) -> SymbolTable {
103 let id = ID_COUNTER.with(|x| x.fetch_add(1, Ordering::Relaxed));
104 SymbolTable {
105 id,
106 table: BTreeMap::new(),
107 next_machine_name: RefCell::new(0),
108 parent,
109 }
110 }
111
112 pub fn lookup_local(&self, name: &Name) -> Option<Rc<Declaration>> {
116 self.table.get(name).cloned()
117 }
118
119 pub fn lookup(&self, name: &Name) -> Option<Rc<Declaration>> {
123 self.lookup_local(name).or_else(|| {
124 self.parent
125 .as_ref()
126 .and_then(|parent| (*parent).borrow().lookup(name))
127 })
128 }
129
130 pub fn insert(&mut self, declaration: Rc<Declaration>) -> Option<()> {
134 let name = declaration.name().clone();
135 if let Entry::Vacant(e) = self.table.entry(name) {
136 e.insert(declaration);
137 Some(())
138 } else {
139 None
140 }
141 }
142
143 pub fn update_insert(&mut self, declaration: Rc<Declaration>) {
145 let name = declaration.name().clone();
146 self.table.insert(name, declaration);
147 }
148
149 pub fn return_type(&self, name: &Name) -> Option<ReturnType> {
151 self.lookup(name).and_then(|x| x.return_type())
152 }
153
154 pub fn return_type_local(&self, name: &Name) -> Option<ReturnType> {
156 self.lookup_local(name).and_then(|x| x.return_type())
157 }
158
159 pub fn domain(&self, name: &Name) -> Option<Domain> {
164 let decl = self.lookup(name)?;
168
169 decl.domain().cloned()
170 }
171
172 pub fn resolve_domain(&self, name: &Name) -> Option<Domain> {
176 match self.domain(name) {
177 Some(Domain::DomainReference(name)) => self
178 .lookup(&name)
179 .and_then(|decl| decl.as_domain_letting().cloned()),
180 result => result,
181 }
182 }
183
184 pub fn into_iter_local(self) -> LocalIntoIter {
186 LocalIntoIter {
187 inner: self.table.into_iter(),
188 }
189 }
190
191 pub fn extend(&mut self, other: SymbolTable) {
194 if other.table.keys().count() > self.table.keys().count() {
195 let new_vars = other.table.keys().collect::<BTreeSet<_>>();
196 let old_vars = self.table.keys().collect::<BTreeSet<_>>();
197
198 for added_var in new_vars.difference(&old_vars) {
199 let mut next_var = self.next_machine_name.borrow_mut();
200 match *added_var {
201 Name::UserName(_) => {}
202 Name::MachineName(m) => {
203 if *m >= *next_var {
204 *next_var = *m + 1;
205 }
206 }
207 }
208 }
209 }
210
211 self.table.extend(other.table);
212 }
213
214 pub fn gensym(&self) -> Name {
216 let num = *self.next_machine_name.borrow();
217 *(self.next_machine_name.borrow_mut()) += 1;
218 Name::MachineName(num) }
220
221 pub fn parent_mut_unchecked(&mut self) -> &mut Option<Rc<RefCell<SymbolTable>>> {
225 &mut self.parent
226 }
227}
228
229impl IntoIterator for SymbolTable {
230 type Item = (Name, Rc<Declaration>);
231
232 type IntoIter = IntoIter;
233
234 fn into_iter(self) -> Self::IntoIter {
236 IntoIter {
237 inner: self.table.into_iter(),
238 parent: self.parent,
239 }
240 }
241}
242
243pub struct LocalIntoIter {
245 inner: std::collections::btree_map::IntoIter<Name, Rc<Declaration>>,
247}
248
249impl Iterator for LocalIntoIter {
250 type Item = (Name, Rc<Declaration>);
251
252 fn next(&mut self) -> Option<Self::Item> {
253 self.inner.next()
254 }
255}
256
257pub struct IntoIter {
259 inner: std::collections::btree_map::IntoIter<Name, Rc<Declaration>>,
261
262 parent: Option<Rc<RefCell<SymbolTable>>>,
264}
265
266impl Iterator for IntoIter {
267 type Item = (Name, Rc<Declaration>);
268
269 fn next(&mut self) -> Option<Self::Item> {
270 let mut val = self.inner.next();
271
272 while val.is_none() {
276 let parent = self.parent.clone()?;
277 let parent_ref = (*parent).borrow();
278 self.parent = parent_ref.parent.clone();
279 self.inner = parent_ref.table.clone().into_iter();
280
281 val = self.inner.next();
282 }
283
284 val
285 }
286}
287
288impl HasId for SymbolTable {
289 fn id(&self) -> ObjId {
290 self.id
291 }
292}
293
294impl DefaultWithId for SymbolTable {
295 fn default_with_id(id: ObjId) -> Self {
296 Self {
297 table: BTreeMap::new(),
298 id,
299 parent: None,
300 next_machine_name: RefCell::new(0),
301 }
302 }
303}
304
305impl Clone for SymbolTable {
306 fn clone(&self) -> Self {
307 Self {
308 table: self.table.clone(),
309 id: ID_COUNTER.with(|x| x.fetch_add(1, Ordering::Relaxed)),
310 parent: self.parent.clone(),
311 next_machine_name: self.next_machine_name.clone(),
312 }
313 }
314}
315
316impl Default for SymbolTable {
317 fn default() -> Self {
318 Self::new_inner(None)
319 }
320}
321
322impl Uniplate for SymbolTable {
323 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
324 let self2 = self.clone();
326 (Tree::Zero, Box::new(move |_| self2.clone()))
327 }
328}
329
330impl Biplate<Expression> for SymbolTable {
331 fn biplate(&self) -> (Tree<Expression>, Box<dyn Fn(Tree<Expression>) -> Self>) {
332 let (child_trees, ctxs): (VecDeque<_>, Vec<_>) = self
333 .table
334 .values()
335 .map(|decl| <Declaration as Biplate<Expression>>::biplate(decl.as_ref()))
336 .unzip();
337
338 let tree = Tree::Many(child_trees);
339
340 let self2 = self.clone();
341 let ctx = Box::new(move |tree| {
342 let Tree::Many(exprs) = tree else {
343 panic!("unexpected children structure");
344 };
345
346 let mut self3 = self2.clone();
347 let self3_iter = self3.table.iter_mut();
348 for (ctx, tree, (_, decl)) in izip!(&ctxs, exprs, self3_iter) {
349 *decl = Rc::new(ctx(tree));
352 }
353
354 self3
355 });
356
357 (tree, ctx)
358 }
359}
360
361impl Biplate<SubModel> for SymbolTable {
362 fn biplate(&self) -> (Tree<SubModel>, Box<dyn Fn(Tree<SubModel>) -> Self>) {
364 let (exprs, exprs_ctx) = <SymbolTable as Biplate<Expression>>::biplate(self);
365 let (submodel_tree, submodel_ctx) =
366 <VecDeque<Expression> as Biplate<SubModel>>::biplate(&exprs.into_iter().collect());
367
368 let ctx = Box::new(move |x| {
369 exprs_ctx(Tree::Many(
370 submodel_ctx(x).into_iter().map(Tree::One).collect(),
371 ))
372 });
373 (submodel_tree, ctx)
374 }
375}