fix cyclic detection of partial strings in StackfulPreOrderHeapIter (#3050)

This commit is contained in:
Mark Thom
2025-08-21 22:52:25 -07:00
parent c5389dbbf2
commit b2cfc8b6f2
2 changed files with 26 additions and 31 deletions

View File

@@ -445,24 +445,17 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
let cell = *cell; let cell = *cell;
let tail_idx = self.heap.scan_slice_to_str(vh).tail_idx; let tail_idx = self.heap.scan_slice_to_str(vh).tail_idx;
// forward the current PStrLoc cell if the zero if self.heap[tail_idx - 1].get_mark_bit() {
// byte at the end of the string buffer self.read_cell_mut(h).set_forwarding_bit(true);
// is marked self.stack.push(h);
let buf_bytes = self.heap[tail_idx - 1].into_bytes();
if buf_bytes[7] != 0u8 { continue;
let cell = self.read_cell_mut(h); } else {
cell.set_forwarding_bit(true); self.heap[tail_idx - 1].set_mark_bit(true);
} }
// now mark it as if were a HeapCellValue, even self.stack.push(IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap));
// though it's not! this is fine as long as its tag self.stack.push(IterStackLoc::pending_mark_loc(tail_idx, HeapOrStackTag::Heap));
// is never inspected, which it isn't.
self.push_if_unmarked(
IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap),
);
self.stack.push(IterStackLoc::mark_loc(tail_idx, HeapOrStackTag::Heap));
return Some(cell); return Some(cell);
} }
@@ -1959,10 +1952,6 @@ mod tests {
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
pstr_loc_as_cell!(heap_index!(3) + 2) 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); 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.heap.slice_to_str(0, "a string".len()), "a string");
assert_eq!(iter.next().unwrap(), pstr_loc_as_cell!(0)); assert_eq!(
assert_eq!(iter.next().unwrap(), empty_list_as_cell!()); 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); assert_eq!(iter.next(), None);
} }
@@ -2554,10 +2549,6 @@ mod tests {
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
pstr_loc_as_cell!(heap_index!(3) + 2) 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!( assert_eq!(
unmark_cell_bits!(iter.next().unwrap()), unmark_cell_bits!(iter.next().unwrap()),
pstr_loc_as_cell!(heap_index!(3)) pstr_loc_as_cell!(heap_index!(3))

View File

@@ -904,16 +904,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
debug_assert!(cell.is_ref()); debug_assert!(cell.is_ref());
let h = if cell.get_tag() == HeapCellValueTag::PStrLoc { let h = if cell.get_tag() == HeapCellValueTag::PStrLoc {
self.iter.focus().value() self.state_stack
.push(TokenOrRedirect::Atom(atom!("...")));
return None;
} else { } else {
cell.get_value() cell.get_value()
} as usize; } as usize;
self.iter.push_stack(IterStackLoc::iterable_loc(
h,
HeapOrStackTag::Heap,
));
// as usual, the WAM's // as usual, the WAM's
// optimization of the Lis tag // optimization of the Lis tag
// (conflating the location of // (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() { if let Some(cell) = self.iter.next() {
orig_cell = cell; orig_cell = cell;
continue; continue;
} }
return Some(cell);
}; };
} }
} }