as3_parser/tree/
tree_semantics.rs

1use crate::ns::*;
2use by_address::ByAddress;
3
4const LARGE_BYTES: usize = 26_000;
5
6/// Represents a mapping of nodes to something.
7/// 
8/// A limited set of nodes may be mapped to something within this
9/// structure through using the implemented `TreeSemanticsAccessor`
10/// methods, such as `.get()` and `.set()`.
11pub 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
30/// Defines access methods for the `TreeSemantics` structure,
31/// used for attaching semantics to the syntactic tree,
32/// where `T` is the node type, and `S` is the symbol type.
33pub 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);