logic_eval_util/
symbol.rs

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