From b2cfc8b6f2fbcd26cbe99f98b4a03679dab8671b Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 21 Aug 2025 22:52:25 -0700 Subject: [PATCH] fix cyclic detection of partial strings in StackfulPreOrderHeapIter (#3050) --- src/heap_iter.rs | 43 +++++++++++++++++-------------------------- src/heap_print.rs | 16 ++++++++++------ 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/heap_iter.rs b/src/heap_iter.rs index 97489a6b..583d297d 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -445,24 +445,17 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists> let cell = *cell; let tail_idx = self.heap.scan_slice_to_str(vh).tail_idx; - // forward the current PStrLoc cell if the zero - // byte at the end of the string buffer - // is marked - let buf_bytes = self.heap[tail_idx - 1].into_bytes(); - - if buf_bytes[7] != 0u8 { - let cell = self.read_cell_mut(h); - cell.set_forwarding_bit(true); - } + if self.heap[tail_idx - 1].get_mark_bit() { + self.read_cell_mut(h).set_forwarding_bit(true); + self.stack.push(h); - // now mark it as if were a HeapCellValue, even - // though it's not! this is fine as long as its tag - // is never inspected, which it isn't. + continue; + } else { + self.heap[tail_idx - 1].set_mark_bit(true); + } - self.push_if_unmarked( - IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap), - ); - self.stack.push(IterStackLoc::mark_loc(tail_idx, HeapOrStackTag::Heap)); + self.stack.push(IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap)); + self.stack.push(IterStackLoc::pending_mark_loc(tail_idx, HeapOrStackTag::Heap)); return Some(cell); } @@ -1959,10 +1952,6 @@ mod tests { unmark_cell_bits!(iter.next().unwrap()), pstr_loc_as_cell!(heap_index!(3) + 2) ); - assert_eq!( - unmark_cell_bits!(iter.next().unwrap()), - pstr_loc_as_cell!(heap_index!(3) + 2) - ); assert_eq!(iter.next(), None); } @@ -2177,8 +2166,14 @@ mod tests { ); assert_eq!(iter.heap.slice_to_str(0, "a string".len()), "a string"); - assert_eq!(iter.next().unwrap(), pstr_loc_as_cell!(0)); - assert_eq!(iter.next().unwrap(), empty_list_as_cell!()); + assert_eq!( + unmark_cell_bits!(iter.next().unwrap()), + pstr_loc_as_cell!(0) + ); + assert_eq!( + unmark_cell_bits!(iter.next().unwrap()), + empty_list_as_cell!() + ); assert_eq!(iter.next(), None); } @@ -2554,10 +2549,6 @@ mod tests { unmark_cell_bits!(iter.next().unwrap()), pstr_loc_as_cell!(heap_index!(3) + 2) ); - assert_eq!( - unmark_cell_bits!(iter.next().unwrap()), - pstr_loc_as_cell!(heap_index!(3) + 2) - ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), pstr_loc_as_cell!(heap_index!(3)) diff --git a/src/heap_print.rs b/src/heap_print.rs index 2186c8ed..53dbbe63 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -904,16 +904,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { debug_assert!(cell.is_ref()); let h = if cell.get_tag() == HeapCellValueTag::PStrLoc { - self.iter.focus().value() + self.state_stack + .push(TokenOrRedirect::Atom(atom!("..."))); + return None; } else { cell.get_value() } as usize; - self.iter.push_stack(IterStackLoc::iterable_loc( - h, - HeapOrStackTag::Heap, - )); - // as usual, the WAM's // optimization of the Lis tag // (conflating the location of @@ -934,10 +931,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } + self.iter.push_stack(IterStackLoc::iterable_loc( + h, + HeapOrStackTag::Heap, + )); + if let Some(cell) = self.iter.next() { orig_cell = cell; continue; } + + return Some(cell); }; } } -- 2.54.0