Find the first `EnterMark` in the stack, and accumulates every `NodeItem` before it. Returns a tuple that contains: - The pre-order index of the [`TreeNode`] we marked. - The accumulated identifier of the children of the marked [`TreeNode`]. - An accumulated boolean flag from the children of the marked [`TreeNode`] if all children are valid for CSE (i.e. it is safe to extract the [`TreeNode`] as a
(
&mut self,
can_normalize: bool,
)
| 313 | /// visiting traversal and no need to test the expression's validity beforehand with |
| 314 | /// an extra traversal). |
| 315 | fn pop_enter_mark( |
| 316 | &mut self, |
| 317 | can_normalize: bool, |
| 318 | ) -> (usize, Option<Identifier<'n, N>>, bool) { |
| 319 | let mut node_ids: Vec<Identifier<'n, N>> = vec![]; |
| 320 | let mut is_valid = true; |
| 321 | |
| 322 | while let Some(item) = self.visit_stack.pop() { |
| 323 | match item { |
| 324 | VisitRecord::EnterMark(down_index) => { |
| 325 | if can_normalize { |
| 326 | node_ids.sort_by_key(|i| i.hash); |
| 327 | } |
| 328 | let node_id = node_ids |
| 329 | .into_iter() |
| 330 | .fold(None, |accum, item| Some(item.combine(accum))); |
| 331 | return (down_index, node_id, is_valid); |
| 332 | } |
| 333 | VisitRecord::NodeItem(sub_node_id, sub_node_is_valid) => { |
| 334 | node_ids.push(sub_node_id); |
| 335 | is_valid &= sub_node_is_valid; |
| 336 | } |
| 337 | } |
| 338 | } |
| 339 | unreachable!("EnterMark should paired with NodeItem"); |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | impl<'n, N, C> TreeNodeVisitor<'n> for CSEVisitor<'_, 'n, N, C> |