1use std::cell::Cell;
3use std::marker::PhantomData;
4
5use hermes_support::location::{SMLoc, SMRange};
6
7use crate::context::{GCLock, NodeListElement};
8use crate::NodeId;
9use crate::node::{EmptyStatement, Node};
10use crate::visitor::{Path, TransformResult, VisitorMut};
11
12pub type NodeLabel = hermes_atom_table::AtomBytes;
14
15pub type NodeString = hermes_atom_table::AtomBytes;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum Strictness {
21 NotSet,
23 NonStrictMode,
25 StrictMode,
27}
28
29pub const INVALID_LABEL: u32 = u32::MAX;
31
32#[derive(Debug)]
37pub struct NodeMetadata<'gc> {
38 pub(crate) phantom: PhantomData<&'gc Node<'gc>>,
39 pub range: Cell<SMRange>,
41 pub debug_loc: Cell<SMLoc>,
44 pub parens: Cell<u8>,
46 pub id: Cell<NodeId>,
50}
51
52impl<'gc> NodeMetadata<'gc> {
53 pub fn new(range: SMRange) -> Self {
56 NodeMetadata {
57 phantom: PhantomData,
58 range: Cell::new(range),
59 debug_loc: Cell::new(range.start),
60 parens: Cell::new(0),
61 id: Cell::new(NodeId::UNASSIGNED),
62 }
63 }
64
65 pub fn new_with_debug(range: SMRange, debug_loc: SMLoc) -> Self {
67 NodeMetadata {
68 phantom: PhantomData,
69 range: Cell::new(range),
70 debug_loc: Cell::new(debug_loc),
71 parens: Cell::new(0),
72 id: Cell::new(NodeId::UNASSIGNED),
73 }
74 }
75
76 pub(crate) fn duplicate(&self) -> NodeMetadata<'gc> {
81 NodeMetadata {
82 phantom: self.phantom,
83 range: Cell::new(self.range.get()),
84 debug_loc: Cell::new(self.debug_loc.get()),
85 parens: Cell::new(self.parens.get()),
86 id: Cell::new(NodeId::UNASSIGNED),
87 }
88 }
89
90 #[doc(hidden)]
93 pub fn duplicate_pub_for_test(&self) -> NodeMetadata<'gc> {
94 self.duplicate()
95 }
96}
97
98#[derive(Debug, Copy, Clone)]
109pub struct NodeList<'gc> {
110 pub(crate) head: *const NodeListElement<'gc>,
113}
114
115impl<'gc> NodeList<'gc> {
116 pub fn empty() -> Self {
119 NodeList {
120 head: std::ptr::null(),
121 }
122 }
123
124 pub fn from_iter<'a, I: IntoIterator<Item = &'a Node<'a>>>(
128 lock: &'a GCLock<'_, '_>,
129 nodes: I,
130 ) -> NodeList<'a> {
131 let mut it = nodes.into_iter();
132 match it.next() {
133 Some(first) => {
134 let head_elem: &'a NodeListElement<'a> =
137 lock.append_list_element(None, first);
138 let mut prev_elem = head_elem;
139 for next in it {
141 let next_elem =
142 lock.append_list_element(Some(prev_elem), next);
143 prev_elem = next_elem;
144 }
145 NodeList { head: head_elem }
146 }
147 _ => {
148 NodeList::empty()
150 }
151 }
152 }
153
154 pub fn is_empty(&self) -> bool {
157 self.head.is_null()
158 }
159
160 pub fn iter(self) -> NodeListIter<'gc> {
162 NodeListIter {
163 ptr: self.head,
164 _pd: PhantomData,
165 }
166 }
167}
168
169impl<'gc> IntoIterator for NodeList<'gc> {
170 type Item = &'gc Node<'gc>;
171 type IntoIter = NodeListIter<'gc>;
172
173 fn into_iter(self) -> Self::IntoIter {
174 self.iter()
175 }
176}
177
178pub struct NodeListIter<'gc> {
180 ptr: *const NodeListElement<'gc>,
183 _pd: PhantomData<&'gc Node<'gc>>,
184}
185
186impl<'gc> Iterator for NodeListIter<'gc> {
187 type Item = &'gc Node<'gc>;
188 fn next(&mut self) -> Option<&'gc Node<'gc>> {
189 if self.ptr.is_null() {
190 None
191 } else {
192 let (node, next) = crate::context::list_elem_parts(self.ptr);
197 self.ptr = next;
198 Some(node)
199 }
200 }
201}
202
203fn empty_statement<'gc>(gc: &'gc GCLock<'_, '_>, at: SMRange) -> &'gc Node<'gc> {
206 let range = SMRange {
207 start: at.start,
208 end: at.start,
209 };
210 gc.alloc(Node::EmptyStatement(EmptyStatement::new(NodeMetadata::new(range))))
211}
212
213pub(crate) trait NodeChild<'gc>: Sized {
218 type Out;
219 fn visit_child_mut<V: VisitorMut<'gc>>(
220 self,
221 ctx: &'gc GCLock<'_, '_>,
222 visitor: &mut V,
223 path: Path<'gc>,
224 ) -> TransformResult<Self::Out>;
225 fn duplicate(self) -> Self::Out;
226}
227
228impl<'gc> NodeChild<'gc> for &'gc Node<'gc> {
229 type Out = &'gc Node<'gc>;
230 fn visit_child_mut<V: VisitorMut<'gc>>(
231 self,
232 ctx: &'gc GCLock<'_, '_>,
233 visitor: &mut V,
234 path: Path<'gc>,
235 ) -> TransformResult<Self::Out> {
236 match visitor.call(ctx, self, Some(path)) {
237 TransformResult::Removed => {
239 TransformResult::Changed(empty_statement(ctx, self.range()))
240 }
241 TransformResult::Expanded(_) => {
242 panic!("cannot expand a single required child into multiple nodes")
243 }
244 other => other,
245 }
246 }
247 fn duplicate(self) -> Self::Out {
248 self
249 }
250}
251
252impl<'gc> NodeChild<'gc> for Option<&'gc Node<'gc>> {
253 type Out = Option<&'gc Node<'gc>>;
254 fn visit_child_mut<V: VisitorMut<'gc>>(
255 self,
256 ctx: &'gc GCLock<'_, '_>,
257 visitor: &mut V,
258 path: Path<'gc>,
259 ) -> TransformResult<Self::Out> {
260 use TransformResult::*;
261 match self {
262 None => Unchanged,
263 Some(inner) => match visitor.call(ctx, inner, Some(path)) {
266 Unchanged => Unchanged,
267 Removed => Changed(None),
268 Changed(new_node) => Changed(Some(new_node)),
269 Expanded(_) => {
270 panic!("cannot expand a single optional child into multiple nodes")
271 }
272 },
273 }
274 }
275 fn duplicate(self) -> Self::Out {
276 self
277 }
278}
279
280impl<'gc> NodeChild<'gc> for NodeList<'gc> {
281 type Out = NodeList<'gc>;
282 fn visit_child_mut<V: VisitorMut<'gc>>(
283 self,
284 ctx: &'gc GCLock<'_, '_>,
285 visitor: &mut V,
286 path: Path<'gc>,
287 ) -> TransformResult<Self::Out> {
288 use TransformResult::*;
289 let mut index = 0usize;
290 let mut it = self.iter();
291 while let Some(elem) = it.next() {
293 let res = visitor.call(ctx, elem, Some(path));
294 if let Unchanged = res {
295 index += 1;
296 continue;
297 }
298 let mut result: Vec<&'gc Node<'gc>> = self.iter().take(index).collect();
301 match res {
302 Changed(new_node) => result.push(new_node),
303 Expanded(new_nodes) => result.extend(new_nodes),
304 Removed => {}
305 Unchanged => unreachable!("checked above"),
306 }
307 for elem in it.by_ref() {
308 match visitor.call(ctx, elem, Some(path)) {
309 Unchanged => result.push(elem),
310 Changed(new_node) => result.push(new_node),
311 Expanded(new_nodes) => result.extend(new_nodes),
312 Removed => {}
313 }
314 }
315 return Changed(NodeList::from_iter(ctx, result));
316 }
317 Unchanged
318 }
319 fn duplicate(self) -> Self::Out {
320 self
321 }
322}
323
324impl<'gc> Node<'gc> {
325 pub fn visit_mut<V: VisitorMut<'gc>>(
328 &'gc self,
329 ctx: &'gc GCLock<'_, '_>,
330 visitor: &mut V,
331 path: Option<Path<'gc>>,
332 ) -> Option<&'gc Node<'gc>> {
333 match visitor.call(ctx, self, path) {
334 TransformResult::Unchanged => Some(self),
335 TransformResult::Removed => None,
336 TransformResult::Changed(new_node) => Some(new_node),
337 TransformResult::Expanded(_) => panic!("cannot expand the root node into multiple"),
338 }
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::*;
345 #[test]
346 fn strictness_and_constants() {
347 assert_eq!(INVALID_LABEL, u32::MAX);
348 assert_ne!(Strictness::StrictMode, Strictness::NotSet);
349 fn _same(_a: NodeString, b: NodeLabel) -> NodeString { b }
351 }
352}