mxmlextrema_as3parser/tree/
node_assignment.rs

1use crate::ns::*;
2use by_address::ByAddress;
3
4const LARGE_BYTES: usize = 26_000;
5
6/// Represents the mapping of any node to something.
7/// 
8/// A limited subtype of nodes may be mapped to something within this
9/// structure through using the implemented `NodeAssignmentMethod`
10/// methods, such as `.get()` and `.set()`.
11pub struct NodeAssignment<S> {
12    common: NodeAssignment1<S>,
13    large_units: RefCell<HashMap<ByAddress<Rc<CompilationUnit>>, NodeAssignment1<S>>>,
14}
15
16impl<S: Clone> NodeAssignment<S> {
17    pub fn new() -> Self {
18        Self {
19            common: NodeAssignment1::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 `NodeAssignment` 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 NodeAssignmentMethod<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 $node_assignment_id:ident, $($nodetype:ident),*$(,)?) => {
42        $(
43            impl<S: Clone> NodeAssignmentMethod<$nodetype, S> for $node_assignment_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 = NodeAssignment1::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 $node_assignment_id:ident, $($nodetype:ident),*$(,)?) => {
97        $(
98            impl<S: Clone> NodeAssignmentMethod<$nodetype, S> for $node_assignment_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 = NodeAssignment1::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 $node_assignment_1_id:ident, fn $new_id:ident, fn $clear_id:ident, $($nodetype:ident),*$(,)?) => {
152        #[allow(non_snake_case)]
153        struct $node_assignment_1_id<S> {
154            $($nodetype: RefCell<HashMap<NodeAsKey<Rc<$nodetype>>, Option<S>>>,)*
155        }
156
157        impl<S: Clone> $node_assignment_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> NodeAssignmentMethod<$nodetype, S> for $node_assignment_1_id<S> {
171                fn get(&self, node: &Rc<$nodetype>) -> Option<S> {
172                    let m = self.$nodetype.borrow();
173                    let v = m.get(&NodeAsKey(node.clone()));
174                    if let Some(v) = v {
175                        v.clone()
176                    } else {
177                        None
178                    }
179                }
180                fn set(&self, node: &Rc<$nodetype>, symbol: Option<S>) {
181                    self.$nodetype.borrow_mut().insert(NodeAsKey(node.clone()), symbol);
182                }
183                fn delete(&self, node: &Rc<$nodetype>) -> bool {
184                    self.$nodetype.borrow_mut().remove(&NodeAsKey(node.clone())).is_some()
185                }
186                fn has(&self, node: &Rc<$nodetype>) -> bool {
187                    self.$nodetype.borrow().contains_key(&NodeAsKey(node.clone()))
188                }
189            }
190        )*
191    },
192}
193
194impl_semantics_with_loc_call!(
195    struct NodeAssignment,
196    Expression,
197    InitializerField,
198    Directive,
199    MxmlContent,
200    CssDirective,
201    CssMediaQueryCondition,
202    CssSelectorCondition,
203    CssPropertyValue,
204    CssSelector,
205    AsdocReference,
206);
207
208impl_semantics_with_loc_field!(
209    struct NodeAssignment,
210    FunctionCommon,
211    Block,
212    Program,
213    PackageDefinition,
214    SimpleVariableDefinition,
215    Metadata,
216    MetadataEntry,
217    Mxml,
218    MxmlElement,
219    MxmlAttribute,
220    CssProperty,
221    CssRule,
222    CssDocument,
223    QualifiedIdentifier,
224);
225
226impl_semantics_1!(
227    struct NodeAssignment1,
228    fn new,
229    fn clear,
230    Expression,
231    InitializerField,
232    Directive,
233    FunctionCommon,
234    Block,
235    Program,
236    PackageDefinition,
237    SimpleVariableDefinition,
238    QualifiedIdentifier,
239    Metadata,
240    MetadataEntry,
241    AsdocReference,
242    Mxml,
243    MxmlContent,
244    MxmlElement,
245    MxmlAttribute,
246    CssDirective,
247    CssRule,
248    CssMediaQueryCondition,
249    CssSelectorCondition,
250    CssPropertyValue,
251    CssSelector,
252    CssProperty,
253    CssDocument,
254);