1use crate::ns::*;
2use by_address::ByAddress;
3
4const LARGE_BYTES: usize = 26_000;
5
6pub struct TreeSemantics<S> {
12 common: TreeSemantics1<S>,
13 large_units: RefCell<HashMap<ByAddress<Rc<CompilationUnit>>, TreeSemantics1<S>>>,
14}
15
16impl<S: Clone> TreeSemantics<S> {
17 pub fn new() -> Self {
18 Self {
19 common: TreeSemantics1::new(),
20 large_units: RefCell::new(HashMap::new()),
21 }
22 }
23
24 pub fn clear(&self) {
25 self.common.clear();
26 self.large_units.borrow_mut().clear();
27 }
28}
29
30pub trait TreeSemanticsAccessor<T, S: Clone> {
34 fn get(&self, node: &Rc<T>) -> Option<S>;
35 fn set(&self, node: &Rc<T>, symbol: Option<S>);
36 fn delete(&self, node: &Rc<T>) -> bool;
37 fn has(&self, node: &Rc<T>) -> bool;
38}
39
40macro impl_semantics_with_loc_call {
41 (struct $tree_semantics_id:ident, $($nodetype:ident),*$(,)?) => {
42 $(
43 impl<S: Clone> TreeSemanticsAccessor<$nodetype, S> for $tree_semantics_id<S> {
44 fn get(&self, node: &Rc<$nodetype>) -> Option<S> {
45 let cu = node.location().compilation_unit();
46 if cu.text().len() < LARGE_BYTES {
47 self.common.get(node)
48 } else {
49 let large_units = self.large_units.borrow();
50 let m1 = large_units.get(&ByAddress(cu));
51 m1.and_then(|m1| m1.get(node))
52 }
53 }
54 fn set(&self, node: &Rc<$nodetype>, symbol: Option<S>) {
55 let cu = node.location().compilation_unit();
56 if cu.text().len() < LARGE_BYTES {
57 self.common.set(node, symbol);
58 } else {
59 let mut large_units = self.large_units.borrow_mut();
60 let m1 = large_units.get_mut(&ByAddress(cu.clone()));
61 if let Some(m1) = m1 {
62 m1.set(node, symbol);
63 } else {
64 let m1 = TreeSemantics1::new();
65 m1.set(node, symbol);
66 large_units.insert(ByAddress(cu), m1);
67 }
68 }
69 }
70 fn delete(&self, node: &Rc<$nodetype>) -> bool {
71 let cu = node.location().compilation_unit();
72 if cu.text().len() < LARGE_BYTES {
73 self.common.delete(node)
74 } else {
75 let mut large_units = self.large_units.borrow_mut();
76 let m1 = large_units.get_mut(&ByAddress(cu));
77 m1.map(|m1| m1.delete(node)).unwrap_or(false)
78 }
79 }
80 fn has(&self, node: &Rc<$nodetype>) -> bool {
81 let cu = node.location().compilation_unit();
82 if cu.text().len() < LARGE_BYTES {
83 self.common.has(node)
84 } else {
85 let large_units = self.large_units.borrow();
86 let m1 = large_units.get(&ByAddress(cu));
87 m1.map(|m1| m1.has(node)).unwrap_or(false)
88 }
89 }
90 }
91 )*
92 },
93}
94
95macro impl_semantics_with_loc_field {
96 (struct $tree_semantics_id:ident, $($nodetype:ident),*$(,)?) => {
97 $(
98 impl<S: Clone> TreeSemanticsAccessor<$nodetype, S> for $tree_semantics_id<S> {
99 fn get(&self, node: &Rc<$nodetype>) -> Option<S> {
100 let cu = node.location.compilation_unit();
101 if cu.text().len() < LARGE_BYTES {
102 self.common.get(node)
103 } else {
104 let large_units = self.large_units.borrow();
105 let m1 = large_units.get(&ByAddress(cu));
106 m1.and_then(|m1| m1.get(node))
107 }
108 }
109 fn set(&self, node: &Rc<$nodetype>, symbol: Option<S>) {
110 let cu = node.location.compilation_unit();
111 if cu.text().len() < LARGE_BYTES {
112 self.common.set(node, symbol);
113 } else {
114 let mut large_units = self.large_units.borrow_mut();
115 let m1 = large_units.get_mut(&ByAddress(cu.clone()));
116 if let Some(m1) = m1 {
117 m1.set(node, symbol);
118 } else {
119 let m1 = TreeSemantics1::new();
120 m1.set(node, symbol);
121 large_units.insert(ByAddress(cu), m1);
122 }
123 }
124 }
125 fn delete(&self, node: &Rc<$nodetype>) -> bool {
126 let cu = node.location.compilation_unit();
127 if cu.text().len() < LARGE_BYTES {
128 self.common.delete(node)
129 } else {
130 let mut large_units = self.large_units.borrow_mut();
131 let m1 = large_units.get_mut(&ByAddress(cu));
132 m1.map(|m1| m1.delete(node)).unwrap_or(false)
133 }
134 }
135 fn has(&self, node: &Rc<$nodetype>) -> bool {
136 let cu = node.location.compilation_unit();
137 if cu.text().len() < LARGE_BYTES {
138 self.common.has(node)
139 } else {
140 let large_units = self.large_units.borrow();
141 let m1 = large_units.get(&ByAddress(cu));
142 m1.map(|m1| m1.has(node)).unwrap_or(false)
143 }
144 }
145 }
146 )*
147 },
148}
149
150macro impl_semantics_1 {
151 (struct $tree_semantics_1_id:ident, fn $new_id:ident, fn $clear_id:ident, $($nodetype:ident),*$(,)?) => {
152 #[allow(non_snake_case)]
153 struct $tree_semantics_1_id<S> {
154 $($nodetype: RefCell<HashMap<NodeAsKey<Rc<$nodetype>>, Option<S>>>,)*
155 }
156
157 impl<S: Clone> $tree_semantics_1_id<S> {
158 pub fn $new_id() -> Self {
159 Self {
160 $($nodetype: RefCell::new(HashMap::new()),)*
161 }
162 }
163
164 pub fn $clear_id(&self) {
165 $(self.$nodetype.borrow_mut().clear();)*
166 }
167 }
168
169 $(
170 impl<S: Clone> TreeSemanticsAccessor<$nodetype, S> for $tree_semantics_1_id<S> {
171 fn get(&self, node: &Rc<$nodetype>) -> Option<S> {
172 self.$nodetype.borrow().get(&NodeAsKey(node.clone())).map(|v| v.clone().unwrap())
173 }
174 fn set(&self, node: &Rc<$nodetype>, symbol: Option<S>) {
175 self.$nodetype.borrow_mut().insert(NodeAsKey(node.clone()), symbol);
176 }
177 fn delete(&self, node: &Rc<$nodetype>) -> bool {
178 self.$nodetype.borrow_mut().remove(&NodeAsKey(node.clone())).is_some()
179 }
180 fn has(&self, node: &Rc<$nodetype>) -> bool {
181 self.$nodetype.borrow().contains_key(&NodeAsKey(node.clone()))
182 }
183 }
184 )*
185 },
186}
187
188impl_semantics_with_loc_call!(
189 struct TreeSemantics,
190 Expression,
191 InitializerField,
192 Directive,
193 MxmlContent,
194 CssDirective,
195 CssMediaQueryCondition,
196 CssSelectorCondition,
197 CssPropertyValue,
198 CssSelector,
199);
200
201impl_semantics_with_loc_field!(
202 struct TreeSemantics,
203 FunctionCommon,
204 Block,
205 Program,
206 PackageDefinition,
207 SimpleVariableDefinition,
208 Mxml,
209 MxmlElement,
210 MxmlAttribute,
211 CssProperty,
212 CssRule,
213 CssDocument,
214 QualifiedIdentifier,
215);
216
217impl_semantics_1!(
218 struct TreeSemantics1,
219 fn new,
220 fn clear,
221 Expression,
222 InitializerField,
223 Directive,
224 FunctionCommon,
225 Block,
226 Program,
227 PackageDefinition,
228 SimpleVariableDefinition,
229 QualifiedIdentifier,
230 Mxml,
231 MxmlContent,
232 MxmlElement,
233 MxmlAttribute,
234 CssDirective,
235 CssRule,
236 CssMediaQueryCondition,
237 CssSelectorCondition,
238 CssPropertyValue,
239 CssSelector,
240 CssProperty,
241 CssDocument,
242);