1#![deny(missing_docs, unsafe_code, missing_debug_implementations)]
7
8use ahash::RandomState;
9use im::HashMap;
10use std::borrow::Borrow;
11use std::fmt::{self, Debug, Formatter};
12use std::hash::Hash;
13use std::hash::{BuildHasher, Hasher};
14
15pub use symbolmap_trait::{MutSymbolMap, SymbolMap, SymbolStack};
16
17#[cfg(feature = "elysees")]
21#[allow(unused)]
22type Arc<T> = elysees::Arc<T>;
23#[cfg(not(feature = "elysees"))]
24#[allow(unused)]
25type Arc<T> = std::sync::Arc<T>;
26
27pub struct SymbolTable<K: Hash + Eq, V, S: BuildHasher = RandomState> {
31 symbols: HashMap<K, V, S>,
33 depth: usize,
35 prev: Option<Arc<SymbolTable<K, V, S>>>,
37}
38
39impl<K: Hash + Eq, V, S: BuildHasher + Default> Default for SymbolTable<K, V, S> {
40 #[inline]
41 fn default() -> SymbolTable<K, V, S> {
42 SymbolTable {
43 symbols: HashMap::default(),
44 depth: 0,
45 prev: None,
46 }
47 }
48}
49
50impl<K: Hash + Eq, V> SymbolTable<K, V> {
51 #[inline]
53 pub fn new() -> SymbolTable<K, V> {
54 Self::default()
55 }
56}
57
58impl<K: Hash + Eq, V, S: BuildHasher> SymbolTable<K, V, S> {
59 #[inline]
61 pub fn hasher(&self) -> &std::sync::Arc<S> {
62 self.symbols.hasher()
63 }
64 #[inline]
66 pub fn with_hasher<RS>(hasher: RS) -> SymbolTable<K, V, S>
67 where
68 std::sync::Arc<S>: From<RS>,
69 {
70 SymbolTable {
71 symbols: HashMap::with_hasher(hasher),
72 depth: 0,
73 prev: None,
74 }
75 }
76}
77
78impl<K: Hash + Eq, V: PartialEq, S: BuildHasher> PartialEq for SymbolTable<K, V, S> {
79 #[inline]
80 fn eq(&self, other: &Self) -> bool {
81 self.depth == other.depth && self.symbols == other.symbols && self.prev == other.prev
83 }
84}
85
86impl<K: Hash + Eq, V: Eq, S: BuildHasher> Eq for SymbolTable<K, V, S> {}
87
88impl<K: Hash + Eq, V: Hash, S: BuildHasher> Hash for SymbolTable<K, V, S> {
89 fn hash<H: Hasher>(&self, hasher: &mut H) {
90 self.symbols.hash(hasher);
92 self.depth.hash(hasher);
93 self.prev.hash(hasher);
94 }
95}
96
97impl<K: Hash + Eq + Debug, V: Debug, S: BuildHasher> Debug for SymbolTable<K, V, S> {
98 #[inline]
99 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
100 fmt.debug_struct("SymbolTable")
101 .field("symbols", &self.symbols)
102 .field("depth", &self.depth)
103 .field("prev", &self.prev)
104 .finish()
105 }
106}
107
108impl<K: Hash + Eq, V, S: BuildHasher> SymbolTable<K, V, S> {
109 #[inline]
111 pub fn get_prev(&self) -> Option<&Arc<SymbolTable<K, V, S>>> {
112 self.prev.as_ref()
113 }
114}
115
116impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher> Clone for SymbolTable<K, V, S> {
117 #[inline]
118 fn clone(&self) -> SymbolTable<K, V, S> {
119 SymbolTable {
120 symbols: self.symbols.clone(),
121 depth: self.depth,
122 prev: self.prev.clone(),
123 }
124 }
125}
126
127impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher> SymbolTable<K, V, S> {
128 #[inline]
130 pub fn extend(self) -> SymbolTable<K, V, S> {
131 let symbols = self.symbols.clone();
132 let depth = self.depth + 1;
133 SymbolTable {
134 symbols,
135 depth,
136 prev: Some(Arc::new(self)),
137 }
138 }
139}
140
141impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher> SymbolMap<K> for SymbolTable<K, V, S> {
142 type Value = V;
143 #[inline]
144 fn insert(&mut self, key: K, value: Self::Value) {
145 self.symbols.insert(key, value);
146 }
147 #[inline]
148 fn get<Q>(&self, key: &Q) -> Option<&Self::Value>
149 where
150 Q: ?Sized + Hash + Eq,
151 K: Borrow<Q>,
152 {
153 self.symbols.get(key)
154 }
155 #[inline]
156 fn contains_key<Q>(&self, key: &Q) -> bool
157 where
158 Q: ?Sized + Hash + Eq,
159 K: Borrow<Q>,
160 {
161 self.symbols.contains_key(key)
162 }
163 #[inline]
164 fn is_empty(&self) -> bool {
165 self.symbols.is_empty()
166 }
167 #[inline]
168 fn try_get_mut<Q>(&mut self, key: &Q) -> Option<&mut Self::Value>
169 where
170 Q: ?Sized + Hash + Eq,
171 K: Borrow<Q>,
172 {
173 self.symbols.get_mut(key)
174 }
175 #[inline]
176 fn push(&mut self) {
177 self.prev = Some(Arc::new((*self).clone()));
178 self.depth += 1;
179 }
180 #[inline]
181 fn pop(&mut self) {
182 if let Some(prev) = self.prev.as_deref() {
183 *self = (*prev).clone();
184 }
185 }
186 #[inline]
187 fn depth(&self) -> usize {
188 self.depth
189 }
190}
191
192impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher> MutSymbolMap<K> for SymbolTable<K, V, S> {}
193
194impl<K: Hash + Eq + Clone, V: Clone, S: BuildHasher> SymbolStack<K> for SymbolTable<K, V, S> {
195 #[inline]
196 fn prev(&self) -> Option<&Self> {
197 self.prev.as_deref()
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use symbolmap_trait::testing;
205 #[test]
206 fn basic_symbol_table_test() {
207 testing::basic_symbol_table_test(&mut SymbolTable::new())
208 }
209}