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 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 self.heap[tail_idx - 1].get_mark_bit() {
self.read_cell_mut(h).set_forwarding_bit(true);
self.stack.push(h);
if buf_bytes[7] != 0u8 {
let cell = self.read_cell_mut(h);
cell.set_forwarding_bit(true);
continue;
} else {
self.heap[tail_idx - 1].set_mark_bit(true);
}
// 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.
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))

View File

@@ -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);
};
}
}