From b656700294444142a6cb70071ec6c8c8d9cc0871 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 26 May 2023 15:19:07 -0600 Subject: [PATCH] read from machine stack in stackful pre-order iterator (#1812) --- src/heap_iter.rs | 452 +++++++++++++++++++--------- src/heap_print.rs | 80 +++-- src/machine/arithmetic_ops.rs | 2 +- src/machine/attributed_variables.rs | 6 +- src/machine/gc.rs | 6 +- src/machine/loader.rs | 4 +- src/machine/machine_state.rs | 6 +- src/machine/machine_state_impl.rs | 4 +- src/machine/system_calls.rs | 4 +- src/machine/unify.rs | 8 +- 10 files changed, 367 insertions(+), 205 deletions(-) diff --git a/src/heap_iter.rs b/src/heap_iter.rs index e957225c..96aef41d 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -19,28 +19,45 @@ enum IterStackLocTag { PendingMark, } +#[derive(BitfieldSpecifier, Clone, Copy, Debug, PartialEq, Eq)] +#[bits = 1] +pub enum HeapOrStackTag { + Heap, + Stack, +} + #[bitfield] #[repr(u64)] #[derive(Clone, Copy, Debug)] pub struct IterStackLoc { - value: B62, + pub value: B61, tag: IterStackLocTag, + heap_or_stack: HeapOrStackTag, } impl IterStackLoc { #[inline] - pub fn iterable_heap_loc(h: usize) -> Self { - IterStackLoc::new().with_tag(IterStackLocTag::Iterable).with_value(h as u64) + pub fn iterable_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self { + IterStackLoc::new() + .with_tag(IterStackLocTag::Iterable) + .with_heap_or_stack(heap_or_stack) + .with_value(h as u64) } #[inline] - pub fn mark_heap_loc(h: usize) -> Self { - IterStackLoc::new().with_tag(IterStackLocTag::Marked).with_value(h as u64) + fn mark_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self { + IterStackLoc::new() + .with_tag(IterStackLocTag::Marked) + .with_heap_or_stack(heap_or_stack) + .with_value(h as u64) } #[inline] - pub fn pending_mark_heap_loc(h: usize) -> Self { - IterStackLoc::new().with_tag(IterStackLocTag::PendingMark).with_value(h as u64) + fn pending_mark_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self { + IterStackLoc::new() + .with_tag(IterStackLocTag::PendingMark) + .with_heap_or_stack(heap_or_stack) + .with_value(h as u64) } #[inline] @@ -52,39 +69,35 @@ impl IterStackLoc { pub fn is_pending_mark(self) -> bool { self.tag() == IterStackLocTag::PendingMark } -} -#[inline] -fn forward_if_referent_marked(heap: &mut [HeapCellValue], h: usize) { - read_heap_cell!(heap[h], - (HeapCellValueTag::Str - | HeapCellValueTag::Lis - | HeapCellValueTag::AttrVar - | HeapCellValueTag::Var - | HeapCellValueTag::PStrLoc, vh) => { - if heap[vh].get_mark_bit() { - heap[h].set_forwarding_bit(true); + #[inline] + pub fn as_ref(self) -> Ref { + match self.heap_or_stack() { + HeapOrStackTag::Heap => { + Ref::heap_cell(self.value() as usize) + } + HeapOrStackTag::Stack => { + Ref::stack_cell(self.value() as usize) } } - _ => {} - ) + } } #[derive(Debug)] pub struct StackfulPreOrderHeapIter<'a> { pub heap: &'a mut Vec, - machine_stack: Option<&'a Stack>, + pub machine_stack: &'a mut Stack, stack: Vec, - h: usize, + h: IterStackLoc, } impl<'a> Drop for StackfulPreOrderHeapIter<'a> { fn drop(&mut self) { while let Some(h) = self.stack.pop() { - let h = h.value() as usize; + let cell = self.read_cell_mut(h); - self.heap[h].set_forwarding_bit(false); - self.heap[h].set_mark_bit(false); + cell.set_forwarding_bit(false); + cell.set_mark_bit(false); } self.heap.pop(); @@ -92,53 +105,93 @@ impl<'a> Drop for StackfulPreOrderHeapIter<'a> { } pub trait FocusedHeapIter: Iterator { - fn focus(&self) -> usize; + fn focus(&self) -> IterStackLoc; } impl<'a> FocusedHeapIter for StackfulPreOrderHeapIter<'a> { #[inline] - fn focus(&self) -> usize { + fn focus(&self) -> IterStackLoc { self.h } } impl<'a> StackfulPreOrderHeapIter<'a> { #[inline] - fn new(heap: &'a mut Vec, cell: HeapCellValue) -> Self { - let h = heap.len(); + fn new(heap: &'a mut Vec, stack: &'a mut Stack, cell: HeapCellValue) -> Self { + let h = IterStackLoc::iterable_loc(heap.len(), HeapOrStackTag::Heap); heap.push(cell); Self { heap, h, - machine_stack: None, - stack: vec![IterStackLoc::iterable_heap_loc(h)], + machine_stack: stack, + stack: vec![h], } } - pub fn iterate_over_machine_stack(&mut self, stack: &'a Stack) { - self.machine_stack = Some(stack); + #[inline] + fn forward_if_referent_marked(&mut self, loc: IterStackLoc) { + read_heap_cell!(self.read_cell(loc), + (HeapCellValueTag::Str | + HeapCellValueTag::Lis | + HeapCellValueTag::AttrVar | + HeapCellValueTag::Var | + HeapCellValueTag::PStrLoc, vh) => { + if self.heap[vh].get_mark_bit() { + self.read_cell_mut(loc).set_forwarding_bit(true); + } + } + (HeapCellValueTag::StackVar, vs) => { + if self.machine_stack[vs].get_mark_bit() { + self.read_cell_mut(loc).set_forwarding_bit(true); + } + } + _ => {} + ); + } + + #[inline] + pub fn push_stack(&mut self, h: IterStackLoc) { + self.stack.push(h); } #[inline] - pub fn push_stack(&mut self, h: usize) { - self.stack.push(IterStackLoc::iterable_heap_loc(h)); + pub fn read_cell_mut(&mut self, loc: IterStackLoc) -> &mut HeapCellValue { + match loc.heap_or_stack() { + HeapOrStackTag::Heap => { + &mut self.heap[loc.value() as usize] + } + HeapOrStackTag::Stack => { + &mut self.machine_stack[loc.value() as usize] + } + } } #[inline] - pub fn stack_last(&self) -> Option { + pub fn read_cell(&self, loc: IterStackLoc) -> HeapCellValue { + match loc.heap_or_stack() { + HeapOrStackTag::Heap => { + self.heap[loc.value() as usize] + } + HeapOrStackTag::Stack => { + self.machine_stack[loc.value() as usize] + } + } + } + + #[inline] + pub fn stack_last(&self) -> Option { for h in self.stack.iter().rev() { let is_readable_marked = h.is_marked(); - let h = h.value() as usize; - let cell = self.heap[h]; + let cell = self.read_cell(*h); if cell.get_forwarding_bit() { - return Some(h); + return Some(*h); } else if cell.get_mark_bit() && !is_readable_marked { continue; } - return Some(h); + return Some(*h); } None @@ -148,10 +201,9 @@ impl<'a> StackfulPreOrderHeapIter<'a> { pub fn pop_stack(&mut self) -> Option { while let Some(h) = self.stack.pop() { let is_readable_marked = h.is_marked(); - let h = h.value() as usize; - self.h = h; - let cell = &mut self.heap[h]; + self.h = h; + let cell = self.read_cell_mut(h); if cell.get_forwarding_bit() { cell.set_forwarding_bit(false); @@ -166,50 +218,29 @@ impl<'a> StackfulPreOrderHeapIter<'a> { None } - fn push_if_unmarked(&mut self, h: usize) { - if !self.heap[h].get_mark_bit() { - self.heap[h].set_mark_bit(true); - self.stack.push(IterStackLoc::iterable_heap_loc(h)); - } - } - - fn stack_deref(&self, s: usize) -> Option { - if let Some(stack) = &self.machine_stack { - let mut cell = stack[s]; + fn push_if_unmarked(&mut self, loc: IterStackLoc) { + let cell = self.read_cell_mut(loc); - while cell.is_stack_var() { - let s = cell.get_value(); - - if cell == stack[s] { - break; - } - - cell = stack[s]; - } - - return Some(cell); + if !cell.get_mark_bit() { + cell.set_mark_bit(true); + self.stack.push(IterStackLoc::iterable_loc(loc.value() as usize, loc.heap_or_stack())); } - - None } fn follow(&mut self) -> Option { while let Some(h) = self.stack.pop() { if h.is_pending_mark() { - let h = h.value() as usize; - self.push_if_unmarked(h); - self.stack.push(IterStackLoc::mark_heap_loc(h)); + self.stack.push(IterStackLoc::mark_loc(h.value() as usize, h.heap_or_stack())); - forward_if_referent_marked(&mut self.heap, h); + self.forward_if_referent_marked(h); continue; } - let is_readable_marked = h.is_marked(); - let h = h.value() as usize; - self.h = h; - let cell = &mut self.heap[h]; + + let is_readable_marked = h.is_marked(); + let cell = self.read_cell_mut(h); if cell.get_forwarding_bit() { let copy = *cell; @@ -220,62 +251,73 @@ impl<'a> StackfulPreOrderHeapIter<'a> { continue; } - let cell = if cell.get_tag() == HeapCellValueTag::StackVar { - let cell = *cell; - self.stack_deref(cell.get_value()).unwrap_or(cell) - } else { - *cell - }; - - read_heap_cell!(cell, + read_heap_cell!(*cell, (HeapCellValueTag::Str | HeapCellValueTag::PStrLoc, vh) => { - self.push_if_unmarked(vh); - self.stack.push(IterStackLoc::mark_heap_loc(vh)); + let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap); + + self.push_if_unmarked(loc); + self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap)); } (HeapCellValueTag::Lis, vh) => { - self.push_if_unmarked(vh); + let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap); + + self.push_if_unmarked(loc); - self.stack.push(IterStackLoc::pending_mark_heap_loc(vh + 1)); - self.stack.push(IterStackLoc::mark_heap_loc(vh)); + self.stack.push(IterStackLoc::pending_mark_loc(vh + 1, HeapOrStackTag::Heap)); + self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap)); - forward_if_referent_marked(&mut self.heap, vh); + self.forward_if_referent_marked(loc); - return Some(self.heap[h]); + return Some(self.read_cell(h)); } (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, vh) => { - self.push_if_unmarked(vh); - self.stack.push(IterStackLoc::mark_heap_loc(vh)); - forward_if_referent_marked(&mut self.heap, vh); + let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap); + + self.push_if_unmarked(loc); + self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap)); + self.forward_if_referent_marked(loc); + } + (HeapCellValueTag::StackVar, vs) => { + let loc = IterStackLoc::iterable_loc(vs, HeapOrStackTag::Stack); + + self.push_if_unmarked(loc); + self.stack.push(IterStackLoc::mark_loc(vs, HeapOrStackTag::Stack)); + self.forward_if_referent_marked(loc); } (HeapCellValueTag::PStrOffset, offset) => { - self.push_if_unmarked(offset); - self.stack.push(IterStackLoc::iterable_heap_loc(h+1)); + self.push_if_unmarked(IterStackLoc::iterable_loc(offset, HeapOrStackTag::Heap)); + self.stack.push(IterStackLoc::iterable_loc((h.value()+1) as usize, HeapOrStackTag::Heap)); - return Some(self.heap[h]); + return Some(self.read_cell(h)); } (HeapCellValueTag::PStr) => { - self.push_if_unmarked(h); + let tail_loc = IterStackLoc::iterable_loc((h.value()+1) as usize, HeapOrStackTag::Heap); - self.stack.push(IterStackLoc::iterable_heap_loc(h+1)); - forward_if_referent_marked(&mut self.heap, h+1); + self.push_if_unmarked(IterStackLoc::iterable_loc(h.value() as usize, HeapOrStackTag::Heap)); + self.stack.push(tail_loc); + self.forward_if_referent_marked(tail_loc); - return Some(self.heap[h]); + return Some(self.read_cell(h)); } (HeapCellValueTag::Atom, (_name, arity)) => { - for h in (h + 2 .. h + arity + 1).rev() { - self.stack.push(IterStackLoc::pending_mark_heap_loc(h)); + let l = h.value() as usize; + + for l in (l + 2 .. l + arity + 1).rev() { + self.stack.push(IterStackLoc::pending_mark_loc(l, HeapOrStackTag::Heap)); } if arity > 0 { - self.push_if_unmarked(h+1); - self.stack.push(IterStackLoc::mark_heap_loc(h+1)); - forward_if_referent_marked(&mut self.heap, h+1); + let first_arg_loc = IterStackLoc::iterable_loc(l+1, HeapOrStackTag::Heap); + + self.push_if_unmarked(first_arg_loc); + self.stack.push(IterStackLoc::mark_loc(l+1, HeapOrStackTag::Heap)); + self.forward_if_referent_marked(first_arg_loc); } - return Some(self.heap[h]); + return Some(self.read_cell(h)); } _ => { - return Some(cell); + return Some(*cell); } ) } @@ -303,19 +345,20 @@ pub(crate) fn stackless_preorder_iter( } #[inline(always)] -pub(crate) fn stackful_preorder_iter( - heap: &mut Vec, +pub(crate) fn stackful_preorder_iter<'a>( + heap: &'a mut Vec, + stack: &'a mut Stack, cell: HeapCellValue, -) -> StackfulPreOrderHeapIter { - StackfulPreOrderHeapIter::new(heap, cell) +) -> StackfulPreOrderHeapIter<'a> { + StackfulPreOrderHeapIter::new(heap, stack, cell) } #[derive(Debug)] pub(crate) struct PostOrderIterator { - focus: usize, + focus: IterStackLoc, base_iter: Iter, base_iter_valid: bool, - parent_stack: Vec<(usize, HeapCellValue, usize)>, // number of children, parent node, focus. + parent_stack: Vec<(usize, HeapCellValue, IterStackLoc)>, // number of children, parent node, focus. } impl Deref for PostOrderIterator { @@ -329,7 +372,7 @@ impl Deref for PostOrderIterator { impl PostOrderIterator { pub(crate) fn new(base_iter: Iter) -> Self { PostOrderIterator { - focus: 0, + focus: IterStackLoc::iterable_loc(0, HeapOrStackTag::Heap), base_iter, base_iter_valid: true, parent_stack: vec![], @@ -386,7 +429,7 @@ impl Iterator for PostOrderIterator { impl FocusedHeapIter for PostOrderIterator { #[inline(always)] - fn focus(&self) -> usize { + fn focus(&self) -> IterStackLoc { self.focus } } @@ -402,7 +445,8 @@ impl PostOrderIterator { if let Some((_child_count, item, focus)) = self.parent_stack.last() { read_heap_cell!(item, (HeapCellValueTag::Atom, (_name, arity)) => { - return focus + arity >= idx_loc && *focus < idx_loc; + let focus = focus.value() as usize; + return focus + arity >= idx_loc && focus < idx_loc; } _ => {} ); @@ -435,9 +479,10 @@ impl<'a> LeftistPostOrderHeapIter<'a> { #[inline] pub(crate) fn stackful_post_order_iter<'a>( heap: &'a mut Heap, + stack: &'a mut Stack, cell: HeapCellValue, ) -> LeftistPostOrderHeapIter<'a> { - PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, cell)) + PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, stack, cell)) } #[cfg(test)] @@ -1416,7 +1461,11 @@ mod tests { .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + str_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1447,7 +1496,11 @@ mod tests { )); for _ in 0..20 { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + str_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1475,7 +1528,12 @@ mod tests { { wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); + let mut var = heap_loc_as_cell!(0); // self-referencing variables are copied with their forwarding @@ -1497,7 +1555,11 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1517,7 +1579,11 @@ mod tests { wam.machine_st.heap.push(empty_list_as_cell!()); { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1549,7 +1615,11 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(0)); { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); // the cycle will be iterated twice before being detected. assert_eq!( @@ -1577,7 +1647,11 @@ mod tests { } { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); // cut the iteration short to check that all cells are // unmarked and unforwarded by the Drop instance of @@ -1611,7 +1685,11 @@ mod tests { let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!( @@ -1631,7 +1709,11 @@ mod tests { let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; { - let mut iter = stackful_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_preorder_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell); @@ -1650,7 +1732,12 @@ mod tests { wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64))); { - let mut iter = stackful_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_preorder_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); + let pstr_offset_cell = pstr_offset_as_cell!(0); // pstr_offset_cell.set_forwarding_bit(true); @@ -1675,7 +1762,12 @@ mod tests { wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64))); { - let mut iter = stackful_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_preorder_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); + let pstr_offset_cell = pstr_offset_as_cell!(0); // pstr_offset_cell.set_forwarding_bit(true); @@ -1688,7 +1780,7 @@ mod tests { let h = iter.focus(); - assert_eq!(h, 5); + assert_eq!(h.value(), 5); assert_eq!(unmark_cell_bits!(iter.heap[4]), pstr_offset_as_cell!(0)); assert_eq!(unmark_cell_bits!(iter.heap[5]), fixnum_as_cell!(Fixnum::build_with(1i64))); @@ -1708,7 +1800,11 @@ mod tests { wam.machine_st.heap.extend(functor); { - let mut iter = StackfulPreOrderHeapIter::new(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = StackfulPreOrderHeapIter::new( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1767,7 +1863,11 @@ mod tests { wam.machine_st.heap[4] = list_loc_as_cell!(1); { - let mut iter = stackful_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_preorder_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1834,6 +1934,7 @@ mod tests { { let mut iter = StackfulPreOrderHeapIter::new( &mut wam.machine_st.heap, + &mut wam.machine_st.stack, heap_loc_as_cell!(0), ); @@ -1865,6 +1966,7 @@ mod tests { { let mut iter = stackful_preorder_iter( &mut wam.machine_st.heap, + &mut wam.machine_st.stack, heap_loc_as_cell!(0), ); @@ -1899,6 +2001,7 @@ mod tests { { let mut iter = stackful_preorder_iter( &mut wam.machine_st.heap, + &mut wam.machine_st.stack, heap_loc_as_cell!(0), ); @@ -1933,7 +2036,11 @@ mod tests { .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + str_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1964,7 +2071,11 @@ mod tests { )); for _ in 0..20 { // 0000 { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + str_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -1994,7 +2105,12 @@ mod tests { { wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); + let mut var = heap_loc_as_cell!(0); // self-referencing variables are copied with their forwarding @@ -2016,7 +2132,11 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2036,7 +2156,11 @@ mod tests { wam.machine_st.heap.push(empty_list_as_cell!()); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2068,7 +2192,11 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(0)); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); // the cycle will be iterated twice before being detected. assert_eq!( @@ -2098,6 +2226,7 @@ mod tests { { let mut iter = stackful_post_order_iter( &mut wam.machine_st.heap, + &mut wam.machine_st.stack, heap_loc_as_cell!(0), ); @@ -2133,7 +2262,11 @@ mod tests { let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2152,7 +2285,11 @@ mod tests { let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2171,7 +2308,11 @@ mod tests { wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0i64))); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64))); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); @@ -2186,7 +2327,11 @@ mod tests { wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(1i64))); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + pstr_loc_as_cell!(0), + ); assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1i64))); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_as_cell!(0)); @@ -2210,7 +2355,11 @@ mod tests { wam.machine_st.heap.extend(functor); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2270,7 +2419,11 @@ mod tests { wam.machine_st.heap[4] = list_loc_as_cell!(1); { - let mut iter = stackful_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackful_post_order_iter( + &mut wam.machine_st.heap, + &mut wam.machine_st.stack, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2377,7 +2530,10 @@ mod tests { )); for _ in 0..20 { - let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0)); + let mut iter = stackless_post_order_iter( + &mut wam.machine_st.heap, + str_loc_as_cell!(0), + ); assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0)); @@ -2407,7 +2563,10 @@ mod tests { { wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackless_post_order_iter( + &mut wam.machine_st.heap, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), @@ -2423,7 +2582,10 @@ mod tests { wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); - let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0)); + let mut iter = stackless_post_order_iter( + &mut wam.machine_st.heap, + heap_loc_as_cell!(0), + ); assert_eq!( unmark_cell_bits!(iter.next().unwrap()), diff --git a/src/heap_print.rs b/src/heap_print.rs index c0ea5fa3..910600ab 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -116,7 +116,9 @@ impl<'a> StackfulPreOrderHeapIter<'a> { let mut parent_spec = DirectedOp::Left(atom!("-"), OpDesc::build_with(200, FY as u8)); loop { - read_heap_cell!(self.heap[h], + let cell = self.read_cell(h); + + read_heap_cell!(cell, (HeapCellValueTag::Str, s) => { read_heap_cell!(self.heap[s], (HeapCellValueTag::Atom, (name, _arity)) => { @@ -125,7 +127,7 @@ impl<'a> StackfulPreOrderHeapIter<'a> { if needs_bracketing(spec, &parent_spec) { return false; } else { - h = s + 1; + h = IterStackLoc::iterable_loc(s + 1, HeapOrStackTag::Heap); parent_spec = DirectedOp::Right(name, spec); continue; } @@ -140,7 +142,7 @@ impl<'a> StackfulPreOrderHeapIter<'a> { ) } _ => { - return property_check(self.heap[h]); + return property_check(cell); } ) } @@ -150,12 +152,12 @@ impl<'a> StackfulPreOrderHeapIter<'a> { where P: Fn(HeapCellValue) -> bool, { - let addr = match self.stack_last() { - Some(h) => self.heap[h], + let cell = match self.stack_last() { + Some(h) => self.read_cell(h), None => return false, }; - property_check(addr) + property_check(cell) } } @@ -475,7 +477,6 @@ pub struct HCPrinter<'a, Outputter> { outputter: Outputter, iter: StackfulPreOrderHeapIter<'a>, atom_tbl: &'a mut AtomTable, - stack: &'a Stack, op_dir: &'a OpDir, state_stack: Vec, toplevel_spec: Option, @@ -541,16 +542,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn new( heap: &'a mut Heap, atom_tbl: &'a mut AtomTable, - stack: &'a Stack, + stack: &'a mut Stack, op_dir: &'a OpDir, output: Outputter, cell: HeapCellValue, ) -> Self { HCPrinter { outputter: output, - iter: stackful_preorder_iter(heap, cell), + iter: stackful_preorder_iter(heap, stack, cell), atom_tbl, - stack, op_dir, state_stack: vec![], toplevel_spec: None, @@ -758,14 +758,14 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { fn format_numbered_vars(&mut self) -> bool { let h = self.iter.stack_last().unwrap(); - let addr = self.iter.heap[h]; - let addr = heap_bound_store( + let cell = self.iter.read_cell(h); + let cell = heap_bound_store( &self.iter.heap, - heap_bound_deref(&self.iter.heap, addr), + heap_bound_deref(&self.iter.heap, cell), ); // 7.10.4 - if let Some(var) = numbervar(&self.numbervars_offset, addr) { + if let Some(var) = numbervar(&self.numbervars_offset, cell) { self.iter.pop_stack(); self.state_stack.push(TokenOrRedirect::NumberedVar(var)); return true; @@ -809,11 +809,11 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { }; } - fn offset_as_string(&mut self, h: usize) -> Option { - let addr = self.iter.heap[h]; + fn offset_as_string(&mut self, h: IterStackLoc) -> Option { + let cell = self.iter.read_cell(h); - if let Some(var) = self.var_names.get(&addr) { - read_heap_cell!(addr, + if let Some(var) = self.var_names.get(&cell) { + read_heap_cell!(cell, (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => { return Some(format!("{}", var.as_str())); } @@ -824,7 +824,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { ); } - read_heap_cell!(addr, + read_heap_cell!(cell, (HeapCellValueTag::Lis | HeapCellValueTag::Str, h) => { Some(format!("{}", h)) } @@ -1167,7 +1167,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { fn print_list_like(&mut self, mut max_depth: usize) { let focus = self.iter.focus(); - let mut heap_pstr_iter = HeapPStrIter::new(self.iter.heap, focus); + let mut heap_pstr_iter = HeapPStrIter::new(self.iter.heap, focus.value() as usize); if heap_pstr_iter.next().is_some() { while let Some(_) = heap_pstr_iter.next() {} @@ -1179,7 +1179,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let end_cell = heap_pstr_iter.focus; if self.check_max_depth(&mut max_depth) { - self.remove_list_children(focus); + self.remove_list_children(focus.value() as usize); self.state_stack.push(TokenOrRedirect::Atom(atom!("..."))); return; } @@ -1187,26 +1187,26 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let at_cdr = self.outputter.ends_with("|"); if !at_cdr && !self.ignore_ops && end_cell.is_string_terminator(&self.iter.heap) { - self.remove_list_children(focus); - return self.print_proper_string(focus, max_depth); + self.remove_list_children(focus.value() as usize); + return self.print_proper_string(focus.value() as usize, max_depth); } if self.ignore_ops { self.at_cdr(","); - self.remove_list_children(focus); + self.remove_list_children(focus.value() as usize); - if !self.print_string_as_functor(focus, max_depth) { + if !self.print_string_as_functor(focus.value() as usize, max_depth) { if end_cell == empty_list_as_cell!() { append_str!(self, "[]"); } else { self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); - self.iter.push_stack(end_h); + self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap)); } } } else { let value = heap_bound_store( self.iter.heap, - heap_bound_deref(self.iter.heap, self.iter.heap[focus]), + heap_bound_deref(self.iter.heap, self.iter.read_cell(focus)), ); read_heap_cell!(value, @@ -1217,7 +1217,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let switch = Rc::new(Cell::new((!at_cdr, 0))); self.state_stack.push(TokenOrRedirect::CloseList(switch.clone())); - let (h, offset) = pstr_loc_and_offset(self.iter.heap, focus); + let (h, offset) = pstr_loc_and_offset(self.iter.heap, focus.value() as usize); let pstr = cell_as_string!(self.iter.heap[h]); let pstr = pstr.as_str_from(offset.get_num() as usize); @@ -1239,7 +1239,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.state_stack.push(TokenOrRedirect::HeadTailSeparator); } else if end_cell != empty_list_as_cell!() { if tag == HeapCellValueTag::PStrOffset { - self.iter.push_stack(end_h); + self.iter.push_stack(IterStackLoc::iterable_loc(end_h, HeapOrStackTag::Heap)); } self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth)); @@ -1597,8 +1597,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn print(mut self) -> Outputter { let spec = self.toplevel_spec.take(); - - self.iter.iterate_over_machine_stack(self.stack); self.handle_heap_term(spec, false, self.max_depth); while let Some(loc_data) = self.state_stack.pop() { @@ -1670,7 +1668,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1699,7 +1697,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1723,7 +1721,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1736,7 +1734,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1769,7 +1767,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), @@ -1788,7 +1786,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), @@ -1805,7 +1803,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1837,7 +1835,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0) @@ -1860,7 +1858,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), pstr_loc_as_cell!(0) @@ -1888,7 +1886,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.atom_tbl, - &wam.machine_st.stack, + &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), heap_loc_as_cell!(0), diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index 774b848f..f5aa982f 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1106,7 +1106,7 @@ impl MachineState { pub(crate) fn arith_eval_by_metacall(&mut self, value: HeapCellValue) -> Result { let stub_gen = || functor_stub(atom!("is"), 2); - let mut iter = stackful_post_order_iter(&mut self.heap, value); + let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, value); while let Some(value) = iter.next() { if value.get_forwarding_bit() { diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index 57ea1c22..633378a0 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -136,7 +136,7 @@ impl MachineState { let mut seen_set = IndexSet::new(); let mut seen_vars = vec![]; - let mut iter = stackful_preorder_iter(&mut self.heap, cell); + let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, cell); while let Some(value) = iter.next() { read_heap_cell!(value, @@ -147,7 +147,7 @@ impl MachineState { let value = unmark_cell_bits!(value); - if h != iter.focus() { + if h != iter.focus().value() as usize { let deref_value = heap_bound_store(iter.heap, heap_bound_deref(iter.heap, value)); if deref_value.is_compound(iter.heap) { @@ -167,7 +167,7 @@ impl MachineState { loop { read_heap_cell!(iter.heap[l], (HeapCellValueTag::Lis) => { - iter.push_stack(l); + iter.push_stack(IterStackLoc::iterable_loc(l, HeapOrStackTag::Heap)); // l = elem + 1; break; } diff --git a/src/machine/gc.rs b/src/machine/gc.rs index 8a884950..1de28ffe 100644 --- a/src/machine/gc.rs +++ b/src/machine/gc.rs @@ -3,7 +3,7 @@ use crate::machine::heap::*; use crate::types::*; #[cfg(test)] -use crate::heap_iter::FocusedHeapIter; +use crate::heap_iter::{IterStackLoc, FocusedHeapIter, HeapOrStackTag}; use core::marker::PhantomData; @@ -75,8 +75,8 @@ pub(crate) struct StacklessPreOrderHeapIter<'a, UMP: UnmarkPolicy> { #[cfg(test)] impl<'a> FocusedHeapIter for StacklessPreOrderHeapIter<'a, IteratorUMP> { #[inline] - fn focus(&self) -> usize { - self.current + fn focus(&self) -> IterStackLoc { + IterStackLoc::iterable_loc(self.current, HeapOrStackTag::Heap) } } diff --git a/src/machine/loader.rs b/src/machine/loader.rs index 616fe7ee..989b963b 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -536,7 +536,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let term_addr = machine_st[heap_term_loc]; let mut term_stack = vec![]; - let mut iter = stackful_post_order_iter(&mut machine_st.heap, term_addr); + let mut iter = stackful_post_order_iter(&mut machine_st.heap, &mut machine_st.stack, term_addr); while let Some(addr) = iter.next() { let addr = unmark_cell_bits!(addr); @@ -568,7 +568,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { term_stack.push(Term::Literal(Cell::default(), Literal::try_from(addr).unwrap())); } (HeapCellValueTag::Atom, (name, arity)) => { - let h = iter.focus(); + let h = iter.focus().value() as usize; let mut arity = arity; if iter.heap.len() > h + arity + 1 { diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 6deab8d1..08c12ccd 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -558,10 +558,10 @@ impl MachineState { let mut singleton_var_set: IndexMap = IndexMap::new(); - for addr in stackful_preorder_iter(&mut self.heap, term) { - let addr = unmark_cell_bits!(addr); + for cell in stackful_preorder_iter(&mut self.heap, &mut self.stack, term) { + let cell = unmark_cell_bits!(cell); - if let Some(var) = addr.as_var() { + if let Some(var) = cell.as_var() { if !singleton_var_set.contains_key(&var) { singleton_var_set.insert(var, true); } else { diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index b457ecae..b4dc3fea 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1125,7 +1125,7 @@ impl MachineState { return false; } - let mut iter = stackful_preorder_iter(&mut self.heap, value); + let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value); while let Some(value) = iter.next() { if value.get_forwarding_bit() { @@ -1626,7 +1626,7 @@ impl MachineState { return true; } - let mut iter = stackful_preorder_iter(&mut self.heap, value); + let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value); while let Some(value) = iter.next() { let value = unmark_cell_bits!(value); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index e457a611..61bd9b67 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -532,7 +532,7 @@ impl MachineState { seen_set: &mut IndexSet, value: HeapCellValue, ) { - let mut iter = stackful_preorder_iter(&mut self.heap, value); + let mut iter = stackful_preorder_iter(&mut self.heap, &mut self.stack, value); while let Some(value) = iter.next() { let value = unmark_cell_bits!(value); @@ -722,7 +722,7 @@ impl MachineState { let mut seen_set = IndexSet::new(); { - let mut iter = stackful_post_order_iter(&mut self.heap, term); + let mut iter = stackful_post_order_iter(&mut self.heap, &mut self.stack, term); while let Some(value) = iter.next() { if iter.parent_stack_len() >= max_depth { diff --git a/src/machine/unify.rs b/src/machine/unify.rs index 19445fe4..d6401b92 100644 --- a/src/machine/unify.rs +++ b/src/machine/unify.rs @@ -651,10 +651,12 @@ fn bind_with_occurs_check(unifier: &mut U, r: Ref, value: HeapCellVa let mut occurs_triggered = false; if !value.is_constant() { - for addr in stackful_preorder_iter(&mut unifier.heap, value) { - let addr = unmark_cell_bits!(addr); + let machine_st: &mut MachineState = unifier.deref_mut(); - if let Some(inner_r) = addr.as_var() { + for cell in stackful_preorder_iter(&mut machine_st.heap, &mut machine_st.stack, value) { + let cell = unmark_cell_bits!(cell); + + if let Some(inner_r) = cell.as_var() { if r == inner_r { occurs_triggered = true; break; -- 2.54.0