1use crate::bug;
6use crate::representation::{Representation, get_repr_rule};
7use std::any::TypeId;
8
9use std::collections::BTreeSet;
10use std::collections::btree_map::Entry;
11use std::collections::{BTreeMap, VecDeque};
12use std::hash::{Hash, Hasher};
13use std::sync::Arc;
14use std::sync::atomic::{AtomicU32, Ordering};
15
16use super::comprehension::Comprehension;
17use super::serde::{AsId, DefaultWithId, HasId, IdPtr, ObjId, PtrAsInner};
18use super::{
19 DeclarationPtr, DomainPtr, Expression, GroundDomain, Moo, Name, ReturnType, SubModel, Typeable,
20};
21use itertools::{Itertools as _, izip};
22use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
23use serde::{Deserialize, Serialize};
24use serde_with::serde_as;
25use tracing::trace;
26use uniplate::{Biplate, Tree, Uniplate};
27
28static SYMBOL_TABLE_ID_COUNTER: AtomicU32 = const { AtomicU32::new(0) };
33
34#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35pub struct SymbolTablePtr
36where
37 Self: Send + Sync,
38{
39 inner: Arc<SymbolTablePtrInner>,
40}
41
42impl SymbolTablePtr {
43 pub fn new() -> Self {
45 Self::new_with_data(SymbolTable::new())
46 }
47
48 pub fn with_parent(symbols: SymbolTablePtr) -> Self {
50 Self::new_with_data(SymbolTable::with_parent(symbols))
51 }
52
53 fn new_with_data(data: SymbolTable) -> Self {
54 let object_id = SYMBOL_TABLE_ID_COUNTER.fetch_add(1, Ordering::Relaxed);
55 let id = ObjId {
56 object_id,
57 type_name: SymbolTablePtr::TYPE_NAME.into(),
58 };
59 Self::new_with_id_and_data(id, data)
60 }
61
62 fn new_with_id_and_data(id: ObjId, data: SymbolTable) -> Self {
63 Self {
64 inner: Arc::new(SymbolTablePtrInner {
65 id,
66 value: RwLock::new(data),
67 }),
68 }
69 }
70
71 pub fn read(&self) -> RwLockReadGuard<'_, SymbolTable> {
78 self.inner.value.read()
79 }
80
81 pub fn write(&self) -> RwLockWriteGuard<'_, SymbolTable> {
94 self.inner.value.write()
95 }
96
97 pub fn detach(&self) -> Self {
100 Self::new_with_data(self.read().clone())
101 }
102}
103
104impl Default for SymbolTablePtr {
105 fn default() -> Self {
106 Self::new()
107 }
108}
109
110impl HasId for SymbolTablePtr {
111 const TYPE_NAME: &'static str = "SymbolTable";
112
113 fn id(&self) -> ObjId {
114 self.inner.id.clone()
115 }
116}
117
118impl DefaultWithId for SymbolTablePtr {
119 fn default_with_id(id: ObjId) -> Self {
120 Self::new_with_id_and_data(id, SymbolTable::default())
121 }
122}
123
124impl IdPtr for SymbolTablePtr {
125 type Data = SymbolTable;
126
127 fn get_data(&self) -> Self::Data {
128 self.read().clone()
129 }
130
131 fn with_id_and_data(id: ObjId, data: Self::Data) -> Self {
132 Self::new_with_id_and_data(id, data)
133 }
134}
135
136impl Uniplate for SymbolTablePtr {
142 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
143 let symtab = self.read();
144 let (tree, recons) = Biplate::<SymbolTablePtr>::biplate(&symtab as &SymbolTable);
145
146 let self2 = self.clone();
147 (
148 tree,
149 Box::new(move |x| {
150 let self3 = self2.clone();
151 *(self3.write()) = recons(x);
152 self3
153 }),
154 )
155 }
156}
157
158impl<To> Biplate<To> for SymbolTablePtr
159where
160 SymbolTable: Biplate<To>,
161 To: Uniplate,
162{
163 fn biplate(&self) -> (Tree<To>, Box<dyn Fn(Tree<To>) -> Self>) {
164 if TypeId::of::<To>() == TypeId::of::<Self>() {
165 unsafe {
166 let self_as_to = std::mem::transmute::<&Self, &To>(self).clone();
167 (
168 Tree::One(self_as_to),
169 Box::new(move |x| {
170 let Tree::One(x) = x else { panic!() };
171
172 let x_as_self = std::mem::transmute::<&To, &Self>(&x);
173 x_as_self.clone()
174 }),
175 )
176 }
177 } else {
178 let decl = self.read();
180 let (tree, recons) = Biplate::<To>::biplate(&decl as &SymbolTable);
181
182 let self2 = self.clone();
183 (
184 tree,
185 Box::new(move |x| {
186 let self3 = self2.clone();
187 *(self3.write()) = recons(x);
188 self3
189 }),
190 )
191 }
192 }
193}
194
195#[derive(Debug)]
196struct SymbolTablePtrInner {
197 id: ObjId,
198 value: RwLock<SymbolTable>,
199}
200
201impl Hash for SymbolTablePtrInner {
202 fn hash<H: Hasher>(&self, state: &mut H) {
203 self.id.hash(state);
204 }
205}
206
207impl PartialEq for SymbolTablePtrInner {
208 fn eq(&self, other: &Self) -> bool {
209 self.value.read().eq(&other.value.read())
210 }
211}
212
213impl Eq for SymbolTablePtrInner {}
214
215#[serde_as]
250#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
251pub struct SymbolTable {
252 #[serde_as(as = "Vec<(_,PtrAsInner)>")]
253 table: BTreeMap<Name, DeclarationPtr>,
254
255 #[serde_as(as = "Option<AsId>")]
256 parent: Option<SymbolTablePtr>,
257
258 next_machine_name: i32,
259}
260
261impl SymbolTable {
262 pub fn new() -> SymbolTable {
264 SymbolTable::new_inner(None)
265 }
266
267 pub fn with_parent(parent: SymbolTablePtr) -> SymbolTable {
269 SymbolTable::new_inner(Some(parent))
270 }
271
272 fn new_inner(parent: Option<SymbolTablePtr>) -> SymbolTable {
273 let id = SYMBOL_TABLE_ID_COUNTER.fetch_add(1, Ordering::Relaxed);
274 trace!(
275 "new symbol table: id = {id} parent_id = {}",
276 parent
277 .as_ref()
278 .map(|x| x.id().to_string())
279 .unwrap_or(String::from("none"))
280 );
281 SymbolTable {
282 table: BTreeMap::new(),
283 next_machine_name: 0,
284 parent,
285 }
286 }
287
288 pub fn lookup_local(&self, name: &Name) -> Option<DeclarationPtr> {
292 self.table.get(name).cloned()
293 }
294
295 pub fn lookup(&self, name: &Name) -> Option<DeclarationPtr> {
299 self.lookup_local(name).or_else(|| {
300 self.parent
301 .as_ref()
302 .and_then(|parent| parent.read().lookup(name))
303 })
304 }
305
306 pub fn insert(&mut self, declaration: DeclarationPtr) -> Option<()> {
310 let name = declaration.name().clone();
311 if let Entry::Vacant(e) = self.table.entry(name) {
312 e.insert(declaration);
313 Some(())
314 } else {
315 None
316 }
317 }
318
319 pub fn update_insert(&mut self, declaration: DeclarationPtr) {
321 let name = declaration.name().clone();
322 self.table.insert(name, declaration);
323 }
324
325 pub fn return_type(&self, name: &Name) -> Option<ReturnType> {
327 self.lookup(name).map(|x| x.return_type())
328 }
329
330 pub fn return_type_local(&self, name: &Name) -> Option<ReturnType> {
332 self.lookup_local(name).map(|x| x.return_type())
333 }
334
335 pub fn domain(&self, name: &Name) -> Option<DomainPtr> {
340 if let Name::WithRepresentation(name, _) = name {
341 self.lookup(name)?.domain()
342 } else {
343 self.lookup(name)?.domain()
344 }
345 }
346
347 pub fn resolve_domain(&self, name: &Name) -> Option<Moo<GroundDomain>> {
351 self.domain(name)?.resolve()
352 }
353
354 pub fn into_iter_local(self) -> impl Iterator<Item = (Name, DeclarationPtr)> {
356 self.table.into_iter()
357 }
358
359 pub fn iter_local(&self) -> impl Iterator<Item = (&Name, &DeclarationPtr)> {
361 self.table.iter()
362 }
363
364 pub fn extend(&mut self, other: SymbolTable) {
367 if other.table.keys().count() > self.table.keys().count() {
368 let new_vars = other.table.keys().collect::<BTreeSet<_>>();
369 let old_vars = self.table.keys().collect::<BTreeSet<_>>();
370
371 for added_var in new_vars.difference(&old_vars) {
372 let next_var = &mut self.next_machine_name;
373 if let Name::Machine(m) = *added_var
374 && *m >= *next_var
375 {
376 *next_var = *m + 1;
377 }
378 }
379 }
380
381 self.table.extend(other.table);
382 }
383
384 pub fn gensym(&mut self, domain: &DomainPtr) -> DeclarationPtr {
387 let num = self.next_machine_name;
388 self.next_machine_name += 1;
389 let decl = DeclarationPtr::new_find(Name::Machine(num), domain.clone());
390 self.insert(decl.clone());
391 decl
392 }
393
394 pub fn parent_mut_unchecked(&mut self) -> &mut Option<SymbolTablePtr> {
398 &mut self.parent
399 }
400
401 pub fn parent(&self) -> &Option<SymbolTablePtr> {
403 &self.parent
404 }
405
406 pub fn get_representation(
412 &self,
413 name: &Name,
414 representation: &[&str],
415 ) -> Option<Vec<Box<dyn Representation>>> {
416 let decl = self.lookup(name)?;
428 let var = &decl.as_var()?;
429
430 var.representations
431 .iter()
432 .find(|x| &x.iter().map(|r| r.repr_name()).collect_vec()[..] == representation)
433 .cloned()
434 }
435
436 pub fn representations_for(&self, name: &Name) -> Option<Vec<Vec<Box<dyn Representation>>>> {
442 let decl = self.lookup(name)?;
443 decl.as_var().map(|x| x.representations.clone())
444 }
445
446 pub fn get_or_add_representation(
463 &mut self,
464 name: &Name,
465 representation: &[&str],
466 ) -> Option<Vec<Box<dyn Representation>>> {
467 let mut decl = self.lookup(name)?;
469
470 if let Some(var) = decl.as_var()
471 && let Some(existing_reprs) = var
472 .representations
473 .iter()
474 .find(|x| &x.iter().map(|r| r.repr_name()).collect_vec()[..] == representation)
475 .cloned()
476 {
477 return Some(existing_reprs); }
479 if representation.len() != 1 {
483 bug!("nested representations not implemented")
484 }
485 let repr_name_str = representation[0];
486 let repr_init_fn = get_repr_rule(repr_name_str)?;
487
488 let reprs = vec![repr_init_fn(name, self)?];
489
490 let mut var = decl.as_var_mut()?;
492
493 for repr_instance in &reprs {
494 repr_instance
495 .declaration_down()
496 .ok()?
497 .into_iter()
498 .for_each(|x| self.update_insert(x));
499 }
500
501 var.representations.push(reprs.clone());
502
503 Some(reprs)
504 }
505}
506
507impl IntoIterator for SymbolTable {
508 type Item = (Name, DeclarationPtr);
509
510 type IntoIter = SymbolTableIter;
511
512 fn into_iter(self) -> Self::IntoIter {
514 SymbolTableIter {
515 inner: self.table.into_iter(),
516 parent: self.parent,
517 }
518 }
519}
520
521pub struct SymbolTableIter {
523 inner: std::collections::btree_map::IntoIter<Name, DeclarationPtr>,
525
526 parent: Option<SymbolTablePtr>,
528}
529
530impl Iterator for SymbolTableIter {
531 type Item = (Name, DeclarationPtr);
532
533 fn next(&mut self) -> Option<Self::Item> {
534 let mut val = self.inner.next();
535
536 while val.is_none() {
540 let parent = self.parent.clone()?;
541
542 let guard = parent.read();
543 self.inner = guard.table.clone().into_iter();
544 self.parent.clone_from(&guard.parent);
545
546 val = self.inner.next();
547 }
548
549 val
550 }
551}
552
553impl Default for SymbolTable {
554 fn default() -> Self {
555 Self::new_inner(None)
556 }
557}
558
559impl Uniplate for SymbolTable {
562 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
563 let self2 = self.clone();
565 (Tree::Zero, Box::new(move |_| self2.clone()))
566 }
567}
568
569impl Biplate<SymbolTablePtr> for SymbolTable {
570 fn biplate(
571 &self,
572 ) -> (
573 Tree<SymbolTablePtr>,
574 Box<dyn Fn(Tree<SymbolTablePtr>) -> Self>,
575 ) {
576 let self2 = self.clone();
577 (Tree::Zero, Box::new(move |_| self2.clone()))
578 }
579}
580
581impl Biplate<Expression> for SymbolTable {
582 fn biplate(&self) -> (Tree<Expression>, Box<dyn Fn(Tree<Expression>) -> Self>) {
583 let (child_trees, ctxs): (VecDeque<_>, Vec<_>) = self
584 .table
585 .values()
586 .map(Biplate::<Expression>::biplate)
587 .unzip();
588
589 let tree = Tree::Many(child_trees);
590
591 let self2 = self.clone();
592 let ctx = Box::new(move |tree| {
593 let Tree::Many(exprs) = tree else {
594 panic!("unexpected children structure");
595 };
596
597 let mut self3 = self2.clone();
598 let self3_iter = self3.table.iter_mut();
599 for (ctx, tree, (_, decl)) in izip!(&ctxs, exprs, self3_iter) {
600 *decl = ctx(tree)
603 }
604
605 self3
606 });
607
608 (tree, ctx)
609 }
610}
611
612impl Biplate<Comprehension> for SymbolTable {
613 fn biplate(
614 &self,
615 ) -> (
616 Tree<Comprehension>,
617 Box<dyn Fn(Tree<Comprehension>) -> Self>,
618 ) {
619 let (expr_tree, expr_ctx) = <SymbolTable as Biplate<Expression>>::biplate(self);
620
621 let (exprs, recons_expr_tree) = expr_tree.list();
622
623 let (comprehension_tree, comprehension_ctx) =
624 <VecDeque<Expression> as Biplate<Comprehension>>::biplate(&exprs);
625
626 let ctx = Box::new(move |x| {
627 let exprs = comprehension_ctx(x);
629
630 let expr_tree = recons_expr_tree(exprs);
632
633 expr_ctx(expr_tree)
635 });
636
637 (comprehension_tree, ctx)
638 }
639}
640
641impl Biplate<SubModel> for SymbolTable {
642 fn biplate(&self) -> (Tree<SubModel>, Box<dyn Fn(Tree<SubModel>) -> Self>) {
644 let (expr_tree, expr_ctx) = <SymbolTable as Biplate<Expression>>::biplate(self);
645
646 let (exprs, recons_expr_tree) = expr_tree.list();
647
648 let (submodel_tree, submodel_ctx) =
649 <VecDeque<Expression> as Biplate<SubModel>>::biplate(&exprs);
650
651 let ctx = Box::new(move |x| {
652 let exprs = submodel_ctx(x);
654
655 let expr_tree = recons_expr_tree(exprs);
657
658 expr_ctx(expr_tree)
660 });
661 (submodel_tree, ctx)
662 }
663}