1use rustc_hash::FxHashMap;
2use rustc_hash::FxHashSet;
3use serde::Deserialize;
4use serde::Serialize;
5use std::cell::Cell;
6use std::cell::RefCell;
7use std::cell::RefMut;
8use std::rc::Rc;
9
10#[derive(Clone, Default)]
11pub struct SymbolIdGenerator(Rc<Cell<usize>>);
12
13impl SymbolIdGenerator {
14 pub fn next(&self) -> usize {
15 let id = self.0.get();
16 self.0.set(id + 1);
17 id
18 }
19}
20
21#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
22pub struct Symbol {
23 pub id: usize, }
25
26#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
27pub enum ScopeType {
28 Module,
29 Closure,
30 Block,
31}
32
33#[derive(Default)]
34pub struct ScopeData {
35 parent: Option<Scope>,
36 pub symbols: FxHashMap<String, Symbol>,
37 pub boxed_var_decls: FxHashSet<Symbol>, pub boxed_var_captures: FxHashSet<Symbol>, }
40
41#[derive(Clone)]
42pub struct Scope {
43 pub typ: ScopeType,
44 symbol_id_generator: SymbolIdGenerator,
45 data: Rc<RefCell<ScopeData>>,
46}
47
48impl Scope {
49 pub fn new(typ: ScopeType) -> Self {
50 Self {
51 typ,
52 data: Default::default(),
53 symbol_id_generator: Default::default(),
54 }
55 }
56
57 pub fn new_child(&self, typ: ScopeType) -> Self {
58 Self {
59 typ,
60 symbol_id_generator: self.symbol_id_generator.clone(),
61 data: Rc::new(RefCell::new(ScopeData {
62 parent: Some(self.clone()),
63 ..Default::default()
64 })),
65 }
66 }
67
68 pub fn add_symbol(&self, name: String) -> bool {
69 self
70 .data
71 .borrow_mut()
72 .symbols
73 .insert(name, Symbol {
74 id: self.symbol_id_generator.next(),
75 })
76 .is_none()
77 }
78
79 pub fn has_symbol(&self, name: &str) -> bool {
80 self.data.borrow().symbols.contains_key(name)
81 }
82
83 pub fn get_symbol(&self, name: &str) -> Symbol {
84 self.data.borrow().symbols.get(name).unwrap().clone()
85 }
86
87 pub fn declaration_is_boxed(&self, symbol: Symbol) -> bool {
88 self.data.borrow().boxed_var_decls.contains(&symbol)
89 }
90
91 pub fn captures_box_of(&self, symbol: Symbol) -> bool {
92 self.data.borrow().boxed_var_captures.contains(&symbol)
93 }
94
95 pub fn borrow(&self) -> RefMut<ScopeData> {
96 self.data.borrow_mut()
97 }
98
99 pub fn borrow_mut(&self) -> RefMut<ScopeData> {
100 self.data.borrow_mut()
101 }
102
103 pub fn find_symbol_declaration(&self, name: &str) -> Option<(Scope, Symbol)> {
104 let mut cur = Some(self.clone());
105 while let Some(scope) = cur {
106 if let Some(symbol) = scope.data.borrow_mut().symbols.get(name) {
107 return Some((scope.clone(), *symbol));
108 };
109 cur = scope.parent();
110 }
111 None
112 }
113
114 pub fn find_nearest_scope<P: Fn(ScopeType) -> bool>(&self, pred: P) -> Option<Scope> {
115 let mut cur = Some(self.clone());
116 while let Some(scope) = cur {
117 if pred(scope.typ) {
118 return Some(scope.clone());
119 };
120 cur = scope.parent();
121 }
122 None
123 }
124
125 pub fn find_nearest_closure(&self) -> Option<Scope> {
126 self.find_nearest_scope(|t| t == ScopeType::Closure)
127 }
128
129 pub fn parent(&self) -> Option<Scope> {
130 self.data.borrow().parent.clone()
131 }
132}
133
134impl PartialEq for Scope {
135 fn eq(&self, other: &Self) -> bool {
136 Rc::ptr_eq(&self.data, &other.data)
137 }
138}
139
140impl Eq for Scope {}