1use crate::bug;
6use crate::representation::{Representation, get_repr_rule};
7
8use super::comprehension::Comprehension;
9use super::serde::RcRefCellAsId;
10use std::cell::RefCell;
11use std::collections::BTreeSet;
12use std::collections::btree_map::Entry;
13use std::collections::{BTreeMap, VecDeque};
14use std::hash::{Hash, Hasher};
15use std::rc::Rc;
16use std::sync::atomic::{AtomicU32, Ordering};
17
18use super::declaration::{DeclarationPtr, serde::DeclarationPtrFull};
19use super::serde::{DefaultWithId, HasId, ObjId};
20use itertools::{Itertools as _, izip};
21use serde::{Deserialize, Serialize};
22use serde_with::serde_as;
23use tracing::trace;
24use uniplate::Tree;
25use uniplate::{Biplate, Uniplate};
26
27use super::name::Name;
28use super::{DomainPtr, Expression, GroundDomain, Moo, ReturnType, SubModel, Typeable};
29use derivative::Derivative;
30
31thread_local! {
40static ID_COUNTER: AtomicU32 = const { AtomicU32::new(0) };
41}
42
43#[derive(Derivative)]
78#[derivative(PartialEq)]
79#[derive(Debug, Eq)]
80#[serde_as]
81#[derive(Serialize, Deserialize)]
82pub struct SymbolTable {
83 #[serde_as(as = "Vec<(_,DeclarationPtrFull)>")]
84 table: BTreeMap<Name, DeclarationPtr>,
85
86 #[derivative(PartialEq = "ignore")] id: ObjId,
89
90 #[serde_as(as = "Option<RcRefCellAsId>")]
91 parent: Option<Rc<RefCell<SymbolTable>>>,
92
93 next_machine_name: RefCell<i32>,
94}
95
96impl Hash for SymbolTable {
97 fn hash<H: Hasher>(&self, state: &mut H) {
98 self.id.hash(state);
99 }
100}
101
102impl SymbolTable {
103 pub fn new() -> SymbolTable {
105 SymbolTable::new_inner(None)
106 }
107
108 pub fn with_parent(parent: Rc<RefCell<SymbolTable>>) -> SymbolTable {
110 SymbolTable::new_inner(Some(parent))
111 }
112
113 fn new_inner(parent: Option<Rc<RefCell<SymbolTable>>>) -> SymbolTable {
114 let id = ID_COUNTER.with(|x| x.fetch_add(1, Ordering::Relaxed));
115 trace!(
116 "new symbol table: id = {id} parent_id = {}",
117 parent
118 .as_ref()
119 .map(|x| x.borrow().id().to_string())
120 .unwrap_or(String::from("none"))
121 );
122 SymbolTable {
123 id: ObjId {
124 type_name: SymbolTable::TYPE_NAME.into(),
125 object_id: id,
126 },
127 table: BTreeMap::new(),
128 next_machine_name: RefCell::new(0),
129 parent,
130 }
131 }
132
133 pub fn lookup_local(&self, name: &Name) -> Option<DeclarationPtr> {
137 self.table.get(name).cloned()
138 }
139
140 pub fn lookup(&self, name: &Name) -> Option<DeclarationPtr> {
144 self.lookup_local(name).or_else(|| {
145 self.parent
146 .as_ref()
147 .and_then(|parent| (*parent).borrow().lookup(name))
148 })
149 }
150
151 pub fn insert(&mut self, declaration: DeclarationPtr) -> Option<()> {
155 let name = declaration.name().clone();
156 if let Entry::Vacant(e) = self.table.entry(name) {
157 e.insert(declaration);
158 Some(())
159 } else {
160 None
161 }
162 }
163
164 pub fn update_insert(&mut self, declaration: DeclarationPtr) {
166 let name = declaration.name().clone();
167 self.table.insert(name, declaration);
168 }
169
170 pub fn return_type(&self, name: &Name) -> Option<ReturnType> {
172 self.lookup(name).map(|x| x.return_type())
173 }
174
175 pub fn return_type_local(&self, name: &Name) -> Option<ReturnType> {
177 self.lookup_local(name).map(|x| x.return_type())
178 }
179
180 pub fn domain(&self, name: &Name) -> Option<DomainPtr> {
185 if let Name::WithRepresentation(name, _) = name {
186 self.lookup(name)?.domain()
187 } else {
188 self.lookup(name)?.domain()
189 }
190 }
191
192 pub fn resolve_domain(&self, name: &Name) -> Option<Moo<GroundDomain>> {
196 self.domain(name)?.resolve()
197 }
198
199 pub fn into_iter_local(self) -> LocalIntoIter {
201 LocalIntoIter {
202 inner: self.table.into_iter(),
203 }
204 }
205
206 pub fn extend(&mut self, other: SymbolTable) {
209 if other.table.keys().count() > self.table.keys().count() {
210 let new_vars = other.table.keys().collect::<BTreeSet<_>>();
211 let old_vars = self.table.keys().collect::<BTreeSet<_>>();
212
213 for added_var in new_vars.difference(&old_vars) {
214 let mut next_var = self.next_machine_name.borrow_mut();
215 if let Name::Machine(m) = *added_var
216 && *m >= *next_var
217 {
218 *next_var = *m + 1;
219 }
220 }
221 }
222
223 self.table.extend(other.table);
224 }
225
226 pub fn gensym(&mut self, domain: &DomainPtr) -> DeclarationPtr {
229 let num = *self.next_machine_name.borrow();
230 *(self.next_machine_name.borrow_mut()) += 1;
231 let decl = DeclarationPtr::new_var(Name::Machine(num), domain.clone());
232 self.insert(decl.clone());
233 decl
234 }
235
236 pub fn parent_mut_unchecked(&mut self) -> &mut Option<Rc<RefCell<SymbolTable>>> {
240 &mut self.parent
241 }
242
243 pub fn get_representation(
249 &self,
250 name: &Name,
251 representation: &[&str],
252 ) -> Option<Vec<Box<dyn Representation>>> {
253 let decl = self.lookup(name)?;
265 let var = &decl.as_var()?;
266
267 var.representations
268 .iter()
269 .find(|x| &x.iter().map(|r| r.repr_name()).collect_vec()[..] == representation)
270 .cloned()
271 }
272
273 pub fn representations_for(&self, name: &Name) -> Option<Vec<Vec<Box<dyn Representation>>>> {
279 let decl = self.lookup(name)?;
280 decl.as_var().map(|x| x.representations.clone())
281 }
282
283 pub fn get_or_add_representation(
300 &mut self,
301 name: &Name,
302 representation: &[&str],
303 ) -> Option<Vec<Box<dyn Representation>>> {
304 let mut decl = self.lookup(name)?;
306
307 if let Some(var) = decl.as_var()
308 && let Some(existing_reprs) = var
309 .representations
310 .iter()
311 .find(|x| &x.iter().map(|r| r.repr_name()).collect_vec()[..] == representation)
312 .cloned()
313 {
314 return Some(existing_reprs); }
316 if representation.len() != 1 {
320 bug!("nested representations not implemented")
321 }
322 let repr_name_str = representation[0];
323 let repr_init_fn = get_repr_rule(repr_name_str)?;
324
325 let reprs = vec![repr_init_fn(name, self)?];
326
327 let mut var = decl.as_var_mut()?;
329
330 for repr_instance in &reprs {
331 repr_instance
332 .declaration_down()
333 .ok()?
334 .into_iter()
335 .for_each(|x| self.update_insert(x));
336 }
337
338 var.representations.push(reprs.clone());
339
340 Some(reprs)
341 }
342}
343
344impl IntoIterator for SymbolTable {
345 type Item = (Name, DeclarationPtr);
346
347 type IntoIter = IntoIter;
348
349 fn into_iter(self) -> Self::IntoIter {
351 IntoIter {
352 inner: self.table.into_iter(),
353 parent: self.parent,
354 }
355 }
356}
357
358pub struct LocalIntoIter {
360 inner: std::collections::btree_map::IntoIter<Name, DeclarationPtr>,
362}
363
364impl Iterator for LocalIntoIter {
365 type Item = (Name, DeclarationPtr);
366
367 fn next(&mut self) -> Option<Self::Item> {
368 self.inner.next()
369 }
370}
371
372pub struct IntoIter {
374 inner: std::collections::btree_map::IntoIter<Name, DeclarationPtr>,
376
377 parent: Option<Rc<RefCell<SymbolTable>>>,
379}
380
381impl Iterator for IntoIter {
382 type Item = (Name, DeclarationPtr);
383
384 fn next(&mut self) -> Option<Self::Item> {
385 let mut val = self.inner.next();
386
387 while val.is_none() {
391 let parent = self.parent.clone()?;
392 let parent_ref = (*parent).borrow();
393 self.parent.clone_from(&parent_ref.parent);
394 self.inner = parent_ref.table.clone().into_iter();
395
396 val = self.inner.next();
397 }
398
399 val
400 }
401}
402
403impl HasId for SymbolTable {
404 const TYPE_NAME: &'static str = "SymbolTable";
405 fn id(&self) -> ObjId {
406 self.id.clone()
407 }
408}
409
410impl DefaultWithId for SymbolTable {
411 fn default_with_id(id: ObjId) -> Self {
412 Self {
413 table: BTreeMap::new(),
414 id,
415 parent: None,
416 next_machine_name: RefCell::new(0),
417 }
418 }
419}
420
421impl Clone for SymbolTable {
422 fn clone(&self) -> Self {
423 Self {
424 table: self.table.clone(),
425 id: ObjId {
426 type_name: SymbolTable::TYPE_NAME.into(),
427 object_id: ID_COUNTER.with(|x| x.fetch_add(1, Ordering::Relaxed)),
428 },
429 parent: self.parent.clone(),
430 next_machine_name: self.next_machine_name.clone(),
431 }
432 }
433}
434
435impl Default for SymbolTable {
436 fn default() -> Self {
437 Self::new_inner(None)
438 }
439}
440
441impl SymbolTable {
442 #[doc(hidden)]
443 pub fn clone_with_same_id(&self) -> Self {
447 Self {
452 table: self.table.clone(),
453 id: self.id.clone(),
454 parent: self.parent.clone(),
455 next_machine_name: self.next_machine_name.clone(),
456 }
457 }
458}
459
460impl Uniplate for SymbolTable {
461 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
462 let self2 = self.clone_with_same_id();
464 (Tree::Zero, Box::new(move |_| self2.clone_with_same_id()))
465 }
466}
467
468impl Biplate<Expression> for SymbolTable {
469 fn biplate(&self) -> (Tree<Expression>, Box<dyn Fn(Tree<Expression>) -> Self>) {
470 let (child_trees, ctxs): (VecDeque<_>, Vec<_>) = self
471 .table
472 .values()
473 .map(Biplate::<Expression>::biplate)
474 .unzip();
475
476 let tree = Tree::Many(child_trees);
477
478 let self2 = self.clone();
479 let ctx = Box::new(move |tree| {
480 let Tree::Many(exprs) = tree else {
481 panic!("unexpected children structure");
482 };
483
484 let mut self3 = self2.clone();
485 let self3_iter = self3.table.iter_mut();
486 for (ctx, tree, (_, decl)) in izip!(&ctxs, exprs, self3_iter) {
487 *decl = ctx(tree)
490 }
491
492 self3
493 });
494
495 (tree, ctx)
496 }
497}
498
499impl Biplate<Comprehension> for SymbolTable {
500 fn biplate(
501 &self,
502 ) -> (
503 Tree<Comprehension>,
504 Box<dyn Fn(Tree<Comprehension>) -> Self>,
505 ) {
506 let (expr_tree, expr_ctx) = <SymbolTable as Biplate<Expression>>::biplate(self);
507
508 let (exprs, recons_expr_tree) = expr_tree.list();
509
510 let (comprehension_tree, comprehension_ctx) =
511 <VecDeque<Expression> as Biplate<Comprehension>>::biplate(&exprs);
512
513 let ctx = Box::new(move |x| {
514 let exprs = comprehension_ctx(x);
516
517 let expr_tree = recons_expr_tree(exprs);
519
520 expr_ctx(expr_tree)
522 });
523
524 (comprehension_tree, ctx)
525 }
526}
527
528impl Biplate<SubModel> for SymbolTable {
529 fn biplate(&self) -> (Tree<SubModel>, Box<dyn Fn(Tree<SubModel>) -> Self>) {
531 let (expr_tree, expr_ctx) = <SymbolTable as Biplate<Expression>>::biplate(self);
532
533 let (exprs, recons_expr_tree) = expr_tree.list();
534
535 let (submodel_tree, submodel_ctx) =
536 <VecDeque<Expression> as Biplate<SubModel>>::biplate(&exprs);
537
538 let ctx = Box::new(move |x| {
539 let exprs = submodel_ctx(x);
541
542 let expr_tree = recons_expr_tree(exprs);
544
545 expr_ctx(expr_tree)
547 });
548 (submodel_tree, ctx)
549 }
550}