zypo_lib/parser/scope.rs
1//! Contains the primary scoping structure and various trait implementations.
2use std::collections::HashMap;
3use std::hash::Hash;
4
5/// Structure for storing an AST node as a hashmap node inside of a vector.
6///
7/// To use this structure, a node type has to implament [Hash] and [Eq] (similar
8/// to [PartialEq]).
9pub struct Scope<K: Hash + Eq, V>(Vec<HashMap<K, V>>);
10
11impl<K: Hash + Eq, V> Scope<K, V> {
12 /// Creates a new, empty scope.
13 #[inline]
14 pub fn new() -> Self {
15 Self(vec![HashMap::new()])
16 }
17
18 /// Creates a new scope at top of stack, acting as a new scope.
19 #[inline]
20 pub fn enter_scope(&mut self) {
21 self.0.push(HashMap::<K, V>::new());
22 }
23
24 /// Leaves the scope by popping the top value of the [HashMap] vector stack.
25 #[inline]
26 pub fn leave_scope(&mut self) {
27 self.0.pop();
28 }
29
30 /// Scans bottom-up from the scope stack to find the specified `item`
31 /// argument. This method recurses down the branches of the stack until it
32 /// finds the item (linear search).
33 #[inline]
34 pub fn get(&self, item: &K) -> Option<&V> {
35 for stack_item in self.0.iter().rev() {
36 let cur_item = stack_item.get(item);
37 if cur_item.is_some() {
38 return cur_item;
39 }
40 }
41
42 None
43 }
44
45 /// Inserts a new item into the stack.
46 ///
47 /// NOTE: This will panic if a fatal error occurs if inserting into a broken
48 /// stack.
49 #[inline]
50 pub fn insert(&mut self, key: K, value: V) -> Option<V> {
51 self.0.last_mut().unwrap().insert(key, value)
52 }
53
54 /// Gets the depth of the entire [Scope] data structure.
55 pub fn depth(&self) -> usize {
56 self.0.len()
57 }
58}