logic_eval_util/
symbol.rs1use crate::Map;
2use std::{borrow::Borrow, hash::Hash};
3
4#[derive(Debug)]
5pub struct SymbolTable<K, V> {
6 map: Map<K, Vec<Symbol<V>>>,
7}
8
9impl<K, V> SymbolTable<K, V> {
10 pub fn clear(&mut self) {
11 self.map.clear();
12 }
13
14 pub fn is_empty(&self) -> bool {
15 self.map.is_empty()
16 }
17
18 pub fn push_transparent_block(&mut self) {
19 for v in self.map.values_mut() {
20 v.push(Symbol::Transparent);
21 }
22 }
23
24 pub fn push_opaque_block(&mut self) {
25 for v in self.map.values_mut() {
26 v.push(Symbol::Opaque);
27 }
28 }
29
30 pub fn pop_block(&mut self) {
31 for v in self.map.values_mut() {
32 while let Some(Symbol::Data(_)) = v.pop() {}
33 }
34 self.map.retain(|_, v| !v.is_empty());
35 }
36}
37
38impl<K: Hash + Eq, V> SymbolTable<K, V> {
39 pub fn push(&mut self, name: K, symbol: V) {
40 if let Some(v) = self.map.get_mut(&name) {
41 v.push(Symbol::Data(symbol));
42 } else {
43 self.map.insert(name, vec![Symbol::Data(symbol)]);
44 }
45 }
46
47 pub fn pop<Q>(&mut self, name: &Q) -> Option<V>
48 where
49 K: Borrow<Q>,
50 Q: Hash + Eq + ?Sized,
51 {
52 match self.map.get_mut(name)?.pop()? {
53 Symbol::Data(v) => Some(v),
54 Symbol::Transparent | Symbol::Opaque => None,
55 }
56 }
57
58 pub fn get<Q>(&self, name: &Q) -> Option<&V>
59 where
60 K: Borrow<Q>,
61 Q: Hash + Eq + ?Sized,
62 {
63 self.map.get(name)?.iter().rev().find_map(|x| match x {
64 Symbol::Data(v) => Some(Some(v)),
65 Symbol::Transparent => None, Symbol::Opaque => Some(None), })?
68 }
69
70 pub fn get_mut<Q>(&mut self, name: &Q) -> Option<&mut V>
71 where
72 K: Borrow<Q>,
73 Q: Hash + Eq + ?Sized,
74 {
75 self.map
76 .get_mut(name)?
77 .iter_mut()
78 .rev()
79 .find_map(|x| match x {
80 Symbol::Data(v) => Some(Some(v)),
81 Symbol::Transparent => None, Symbol::Opaque => Some(None), })?
84 }
85}
86
87impl<K, V> Default for SymbolTable<K, V> {
88 fn default() -> Self {
89 Self {
90 map: Map::default(),
91 }
92 }
93}
94
95#[derive(Debug)]
96enum Symbol<T> {
97 Data(T),
98 Transparent,
99 Opaque,
100}