#![allow(dead_code)] use crate::atom_table::*; use crate::machine::heap::*; use crate::types::*; #[cfg(test)] use crate::heap_iter::{FocusedHeapIter, HeapOrStackTag, IterStackLoc}; pub(crate) trait UnmarkPolicy { fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter) -> Option where Self: Sized; fn invert_marker(iter: &mut StacklessPreOrderHeapIter) where Self: Sized; fn mark_phase(&self) -> bool; #[inline] fn report_var_link(iter: &StacklessPreOrderHeapIter) -> bool where Self: Sized, { iter.heap[iter.next as usize].get_mark_bit() == iter.iter_state.mark_phase() } #[inline(always)] fn record_focus(_iter: &mut StacklessPreOrderHeapIter) where Self: Sized, { } } pub(crate) struct IteratorUMP { mark_phase: bool, } fn invert_marker(iter: &mut StacklessPreOrderHeapIter) { if iter.heap[iter.start].get_forwarding_bit() { while !iter.backward() {} } iter.heap[iter.start].set_forwarding_bit(true); iter.next = iter.heap[iter.start].get_value(); iter.current = iter.start; while iter.forward().is_some() {} } impl UnmarkPolicy for IteratorUMP { #[inline(always)] fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter) -> Option { iter.forward_var() } #[inline] fn invert_marker(iter: &mut StacklessPreOrderHeapIter) { iter.iter_state.mark_phase = false; invert_marker(iter); } #[inline] fn mark_phase(&self) -> bool { self.mark_phase } } struct MarkerUMP {} impl UnmarkPolicy for MarkerUMP { #[inline(always)] fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter) -> Option { if iter.heap[iter.current + 1].get_forwarding_bit() { return iter.forward_var(); } let temp = iter.heap[iter.current].get_value(); iter.heap[iter.current].set_value(iter.next); iter.current += 1; iter.next = iter.heap[iter.current].get_value(); iter.heap[iter.current].set_value(temp); iter.heap[iter.current].set_forwarding_bit(true); // forward the attr vars list. None } fn invert_marker(_iter: &mut StacklessPreOrderHeapIter) {} #[inline(always)] fn mark_phase(&self) -> bool { true } } #[derive(Debug)] pub(crate) struct StacklessPreOrderHeapIter<'a, UMP: UnmarkPolicy> { pub(crate) heap: &'a mut [HeapCellValue], start: usize, current: usize, next: u64, iter_state: UMP, } #[cfg(test)] impl<'a> FocusedHeapIter for StacklessPreOrderHeapIter<'a, IteratorUMP> { #[inline] fn focus(&self) -> IterStackLoc { IterStackLoc::iterable_loc(self.current, HeapOrStackTag::Heap) } } impl<'a, UMP: UnmarkPolicy> Drop for StacklessPreOrderHeapIter<'a, UMP> { fn drop(&mut self) { UMP::invert_marker(self); if self.current == self.start { return; } while !self.backward() {} } } impl<'a> StacklessPreOrderHeapIter<'a, MarkerUMP> { pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self { heap[start].set_forwarding_bit(true); let next = heap[start].get_value(); Self { heap, start, current: start, next, iter_state: MarkerUMP {}, } } } impl<'a> StacklessPreOrderHeapIter<'a, IteratorUMP> { #[cfg(test)] pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self { heap[start].set_forwarding_bit(true); let next = heap[start].get_value(); Self { heap, start, current: start, next, iter_state: IteratorUMP { mark_phase: true }, } } } impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> { fn backward_and_return(&mut self) -> HeapCellValue { let mut current = self.heap[self.current]; current.set_value(self.next); if self.backward() { // set the f and m bits on the heap cell at start // so we invoke backward() and return None next call. self.heap[self.current].set_forwarding_bit(true); self.heap[self.current].set_mark_bit(self.iter_state.mark_phase()); } current } fn forward_var(&mut self) -> Option { if self.heap[self.next as usize].get_forwarding_bit() { return Some(self.backward_and_return()); } let temp = self.heap[self.next as usize].get_value(); self.heap[self.next as usize].set_value(self.current as u64); self.current = self.next as usize; self.next = temp; None } fn forward(&mut self) -> Option { loop { if self.heap[self.current].get_mark_bit() != self.iter_state.mark_phase() { self.heap[self.current].set_mark_bit(self.iter_state.mark_phase()); UMP::record_focus(self); match self.heap[self.current].get_tag() { HeapCellValueTag::AttrVar => { let next = self.next as usize; if let Some(cell) = UMP::forward_attr_var(self) { return Some(cell); } if self.next < self.heap.len() as u64 && UMP::report_var_link(self) { let tag = HeapCellValueTag::AttrVar; return Some(HeapCellValue::build_with(tag, next as u64)); } } HeapCellValueTag::Var => { let next = self.next as usize; if let Some(cell) = self.forward_var() { return Some(cell); } if self.next < self.heap.len() as u64 && UMP::report_var_link(self) { let tag = HeapCellValueTag::Var; return Some(HeapCellValue::build_with(tag, next as u64)); } } HeapCellValueTag::Str => { if self.heap[self.next as usize + 1].get_forwarding_bit() { return Some(self.backward_and_return()); } let h = self.next as usize; let cell = self.heap[h]; let arity = cell_as_atom_cell!(self.heap[h]).get_arity(); for cell in &mut self.heap[h + 1..h + arity + 1] { cell.set_forwarding_bit(true); } let last_cell_loc = h + arity; self.next = self.heap[last_cell_loc].get_value(); self.heap[last_cell_loc].set_value(self.current as u64); self.current = last_cell_loc; return Some(cell); } HeapCellValueTag::Lis => { let last_cell_loc = self.next as usize + 1; if self.heap[last_cell_loc].get_forwarding_bit() { return Some(self.backward_and_return()); } self.next = self.heap[last_cell_loc].get_value(); self.heap[last_cell_loc].set_value(self.current as u64); self.current = last_cell_loc; self.heap[last_cell_loc].set_forwarding_bit(true); return Some(list_loc_as_cell!(last_cell_loc - 1)); } HeapCellValueTag::PStrLoc => { let h = self.next as usize; if self.heap[h + 1].get_forwarding_bit() { return Some(self.backward_and_return()); } let cell = self.heap[h]; let last_cell_loc = h + 1; self.next = self.heap[last_cell_loc].get_value(); self.heap[last_cell_loc].set_value(self.current as u64); self.current = last_cell_loc; self.heap[last_cell_loc].set_forwarding_bit(true); return Some(cell); } HeapCellValueTag::PStrOffset => { let h = self.next as usize; let cell = self.heap[h]; let last_cell_loc = h + 1; if self.heap[last_cell_loc].get_forwarding_bit() { return Some(self.backward_and_return()); } if self.heap[h].get_tag() == HeapCellValueTag::PStr { self.heap[last_cell_loc].set_forwarding_bit(true); self.next = self.heap[last_cell_loc].get_value(); self.heap[last_cell_loc].set_value(self.current as u64); self.current = last_cell_loc; } else { debug_assert!(self.heap[h].get_tag() == HeapCellValueTag::CStr); self.next = self.heap[h].get_value(); self.heap[h].set_value(self.current as u64); self.current = h; } return Some(cell); } tag @ HeapCellValueTag::Atom => { let cell = HeapCellValue::build_with(tag, self.next); let arity = AtomCell::from_bytes(cell.into_bytes()).get_arity(); if arity == 0 { return Some(self.backward_and_return()); } else if self.backward() { return None; } } HeapCellValueTag::PStr => { if self.backward() { return None; } } _ => { return Some(self.backward_and_return()); } } } else if self.backward() { return None; } } } fn backward(&mut self) -> bool { while !self.heap[self.current].get_forwarding_bit() { let temp = self.heap[self.current].get_value(); self.heap[self.current].set_value(self.next); self.next = self.current as u64; self.current = temp as usize; } self.heap[self.current].set_forwarding_bit(false); if self.current == self.start { return true; } self.current -= 1; let temp = self.heap[self.current + 1].get_value(); self.heap[self.current + 1].set_value(self.next); self.next = self.heap[self.current].get_value(); self.heap[self.current].set_value(temp); false } } impl<'a, UMP: UnmarkPolicy> Iterator for StacklessPreOrderHeapIter<'a, UMP> { type Item = HeapCellValue; #[inline] fn next(&mut self) -> Option { self.forward() } } pub fn mark_cells(heap: &mut Heap, start: usize) { let mut iter = StacklessPreOrderHeapIter::::new(heap, start); while iter.forward().is_some() {} } #[cfg(test)] mod tests { use super::*; use crate::machine::mock_wam::*; #[test] fn heap_marking_tests() { let mut wam = MockWAM::new(); let f_atom = atom!("f"); let a_atom = atom!("a"); let b_atom = atom!("b"); wam.machine_st.heap.push(str_loc_as_cell!(1)); wam.machine_st .heap .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)])); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), str_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), atom_as_cell!(f_atom, 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(b_atom) ); wam.machine_st.heap.clear(); wam.machine_st.heap.push(str_loc_as_cell!(1)); wam.machine_st.heap.extend(functor!( f_atom, [ atom(a_atom), atom(b_atom), atom(a_atom), cell(str_loc_as_cell!(1)) ] )); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), str_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), atom_as_cell!(f_atom, 4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(b_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), str_loc_as_cell!(1) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } // make the structure doubly cyclic. wam.machine_st.heap[2] = str_loc_as_cell!(1); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); wam.machine_st.heap.clear(); wam.machine_st.heap.push(str_loc_as_cell!(1)); wam.machine_st.heap.extend(functor!( f_atom, [ atom(a_atom), atom(b_atom), atom(a_atom), cell(str_loc_as_cell!(1)) ] )); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), str_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), atom_as_cell!(f_atom, 4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(b_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), str_loc_as_cell!(1) ); wam.machine_st.heap.clear(); wam.machine_st.heap.push(heap_loc_as_cell!(0)); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), heap_loc_as_cell!(0) ); wam.machine_st.heap.clear(); // term is: [a, b] wam.machine_st.heap.push(list_loc_as_cell!(1)); wam.machine_st.heap.push(atom_as_cell!(a_atom)); wam.machine_st.heap.push(list_loc_as_cell!(3)); wam.machine_st.heap.push(atom_as_cell!(b_atom)); wam.machine_st.heap.push(empty_list_as_cell!()); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), list_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(b_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), empty_list_as_cell!() ); wam.machine_st.heap.pop(); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } // now make the list cyclic. wam.machine_st.heap.push(heap_loc_as_cell!(0)); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), list_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(b_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), heap_loc_as_cell!(0) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } // make the list doubly cyclic. wam.machine_st.heap[3] = heap_loc_as_cell!(0); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); wam.machine_st.heap.clear(); // term is: [a, ] let stream = Stream::from_static_string("test", &mut wam.machine_st.arena); let stream_cell = HeapCellValue::from(ConsPtr::build_with(stream.as_ptr(), ConsPtrMaskTag::Cons)); wam.machine_st.heap.push(list_loc_as_cell!(1)); wam.machine_st.heap.push(atom_as_cell!(a_atom)); wam.machine_st.heap.push(list_loc_as_cell!(3)); wam.machine_st.heap.push(stream_cell); wam.machine_st.heap.push(empty_list_as_cell!()); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), list_loc_as_cell!(3) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), stream_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), empty_list_as_cell!() ); wam.machine_st.heap.clear(); // now a cycle of variables. wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(heap_loc_as_cell!(3)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), heap_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), heap_loc_as_cell!(0) ); wam.machine_st.heap.clear(); // first a 'dangling' partial string, later modified to be a // two-part complete string, then a three-part cyclic string // involving an uncompacted list of chars. wam.machine_st.heap.push(pstr_loc_as_cell!(1)); let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), pstr_loc_as_cell!(1) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(2) ); wam.machine_st.heap.pop(); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap.push(pstr_loc_as_cell!(3)); let pstr_second_var_cell = put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl); let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(3) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), heap_loc_as_cell!(4) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap.pop(); wam.machine_st.heap.push(pstr_loc_as_cell!(5)); wam.machine_st.heap.push(pstr_offset_as_cell!(1)); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(2))); wam.machine_st.heap.push(pstr_loc_as_cell!(5)); mark_cells(&mut wam.machine_st.heap, 7); all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(3) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), pstr_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), fixnum_as_cell!(Fixnum::build_with(2)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), pstr_loc_as_cell!(5) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap[7] = heap_loc_as_cell!(2); mark_cells(&mut wam.machine_st.heap, 7); all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(3) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), pstr_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), fixnum_as_cell!(Fixnum::build_with(2)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), heap_loc_as_cell!(2) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap[7] = pstr_loc_as_cell!(1); mark_cells(&mut wam.machine_st.heap, 7); all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(3) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), pstr_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), fixnum_as_cell!(Fixnum::build_with(2)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), pstr_loc_as_cell!(1) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap[7] = heap_loc_as_cell!(0); mark_cells(&mut wam.machine_st.heap, 7); all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(3) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), pstr_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), fixnum_as_cell!(Fixnum::build_with(2)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), heap_loc_as_cell!(0) ); wam.machine_st.heap.truncate(4); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st .heap .push(atom_as_cell!(atom!("irrelevant stuff"))); wam.machine_st.heap.push(pstr_offset_as_cell!(1)); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(2))); // this is at index 7 wam.machine_st.heap.push(pstr_loc_as_cell!(5)); mark_cells(&mut wam.machine_st.heap, 7); assert!(!wam.machine_st.heap[0].get_mark_bit()); assert!(wam.machine_st.heap[1].get_mark_bit()); assert!(wam.machine_st.heap[2].get_mark_bit()); assert!(wam.machine_st.heap[3].get_mark_bit()); assert!(wam.machine_st.heap[4].get_mark_bit()); assert!(wam.machine_st.heap[5].get_mark_bit()); assert!(wam.machine_st.heap[6].get_mark_bit()); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(3) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), fixnum_as_cell!(Fixnum::build_with(2)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), pstr_loc_as_cell!(5) ); wam.machine_st.heap.clear(); wam.machine_st .heap .push(atom_as_cell!(atom!("irrelevant stuff"))); wam.machine_st.heap.push(pstr_cell); wam.machine_st.heap.push(pstr_loc_as_cell!(4)); wam.machine_st .heap .push(atom_as_cell!(atom!("irrelevant stuff"))); wam.machine_st.heap.push(pstr_second_cell); wam.machine_st.heap.push(pstr_loc_as_cell!(7)); wam.machine_st .heap .push(atom_as_cell!(atom!("irrelevant stuff"))); wam.machine_st.heap.push(pstr_offset_as_cell!(1)); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(2))); wam.machine_st.heap.push(pstr_loc_as_cell!(7)); mark_cells(&mut wam.machine_st.heap, 9); assert!(!wam.machine_st.heap[0].get_mark_bit()); assert!(wam.machine_st.heap[1].get_mark_bit()); assert!(wam.machine_st.heap[2].get_mark_bit()); assert!(!wam.machine_st.heap[3].get_mark_bit()); assert!(wam.machine_st.heap[4].get_mark_bit()); assert!(wam.machine_st.heap[5].get_mark_bit()); assert!(!wam.machine_st.heap[6].get_mark_bit()); assert!(wam.machine_st.heap[7].get_mark_bit()); assert!(wam.machine_st.heap[8].get_mark_bit()); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_loc_as_cell!(7) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), fixnum_as_cell!(Fixnum::build_with(2)) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap[9] = heap_loc_as_cell!(5); mark_cells(&mut wam.machine_st.heap, 9); assert!(!wam.machine_st.heap[0].get_mark_bit()); assert!(wam.machine_st.heap[1].get_mark_bit()); assert!(wam.machine_st.heap[2].get_mark_bit()); assert!(!wam.machine_st.heap[3].get_mark_bit()); assert!(wam.machine_st.heap[4].get_mark_bit()); assert!(wam.machine_st.heap[5].get_mark_bit()); assert!(!wam.machine_st.heap[6].get_mark_bit()); assert!(wam.machine_st.heap[7].get_mark_bit()); assert!(wam.machine_st.heap[8].get_mark_bit()); for cell in &wam.machine_st.heap { assert!(!cell.get_forwarding_bit()); } assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_loc_as_cell!(7) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), fixnum_as_cell!(Fixnum::build_with(2)) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap[9] = pstr_loc_as_cell!(4); mark_cells(&mut wam.machine_st.heap, 9); assert!(!wam.machine_st.heap[0].get_mark_bit()); assert!(wam.machine_st.heap[1].get_mark_bit()); assert!(wam.machine_st.heap[2].get_mark_bit()); assert!(!wam.machine_st.heap[3].get_mark_bit()); assert!(wam.machine_st.heap[4].get_mark_bit()); assert!(wam.machine_st.heap[5].get_mark_bit()); assert!(!wam.machine_st.heap[6].get_mark_bit()); assert!(wam.machine_st.heap[7].get_mark_bit()); assert!(wam.machine_st.heap[8].get_mark_bit()); for cell in &wam.machine_st.heap { assert!(!cell.get_forwarding_bit()); } assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_loc_as_cell!(7) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), fixnum_as_cell!(Fixnum::build_with(2)) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } mark_cells(&mut wam.machine_st.heap, 9); wam.machine_st.heap[9] = heap_loc_as_cell!(2); assert!(!wam.machine_st.heap[0].get_mark_bit()); assert!(wam.machine_st.heap[1].get_mark_bit()); assert!(wam.machine_st.heap[2].get_mark_bit()); assert!(!wam.machine_st.heap[3].get_mark_bit()); assert!(wam.machine_st.heap[4].get_mark_bit()); assert!(wam.machine_st.heap[5].get_mark_bit()); assert!(!wam.machine_st.heap[6].get_mark_bit()); assert!(wam.machine_st.heap[7].get_mark_bit()); assert!(wam.machine_st.heap[8].get_mark_bit()); for cell in &wam.machine_st.heap { assert!(!cell.get_forwarding_bit()); } assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_loc_as_cell!(7) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), fixnum_as_cell!(Fixnum::build_with(2)) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap[9] = pstr_loc_as_cell!(1); mark_cells(&mut wam.machine_st.heap, 9); assert!(!wam.machine_st.heap[0].get_mark_bit()); assert!(wam.machine_st.heap[1].get_mark_bit()); assert!(wam.machine_st.heap[2].get_mark_bit()); assert!(!wam.machine_st.heap[3].get_mark_bit()); assert!(wam.machine_st.heap[4].get_mark_bit()); assert!(wam.machine_st.heap[5].get_mark_bit()); assert!(!wam.machine_st.heap[6].get_mark_bit()); assert!(wam.machine_st.heap[7].get_mark_bit()); assert!(wam.machine_st.heap[8].get_mark_bit()); for cell in &wam.machine_st.heap { assert!(!cell.get_forwarding_bit()); } assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!(unmark_cell_bits!(wam.machine_st.heap[4]), pstr_second_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_loc_as_cell!(7) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(atom!("irrelevant stuff")) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), pstr_offset_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), fixnum_as_cell!(Fixnum::build_with(2)) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } wam.machine_st.heap.clear(); // embedded cyclic partial string. wam.machine_st.heap.push(pstr_cell); wam.machine_st.heap.push(pstr_loc_as_cell!(2)); wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(3))); wam.machine_st.heap.push(list_loc_as_cell!(5)); wam.machine_st.heap.push(pstr_loc_as_cell!(0)); wam.machine_st.heap.push(empty_list_as_cell!()); mark_cells(&mut wam.machine_st.heap, 4); all_cells_marked_and_unforwarded(&wam.machine_st.heap); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), pstr_loc_as_cell!(2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_offset_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), fixnum_as_cell!(Fixnum::build_with(3)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), list_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_loc_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), empty_list_as_cell!() ); wam.machine_st.heap.clear(); wam.machine_st.heap.push(pstr_cell); wam.machine_st.heap.push(pstr_loc_as_cell!(2)); wam.machine_st.heap.push(pstr_offset_as_cell!(0)); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(3))); wam.machine_st.heap.push(list_loc_as_cell!(5)); wam.machine_st.heap.push(pstr_loc_as_cell!(0)); wam.machine_st.heap.push(heap_loc_as_cell!(4)); mark_cells(&mut wam.machine_st.heap, 4); all_cells_marked_and_unforwarded(&wam.machine_st.heap); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); } assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), pstr_loc_as_cell!(2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), pstr_offset_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), fixnum_as_cell!(Fixnum::build_with(3)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), list_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), pstr_loc_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), heap_loc_as_cell!(4) ); wam.machine_st.heap.clear(); // a chain of variables, ending in a self-referential variable. wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(heap_loc_as_cell!(3)); wam.machine_st.heap.push(heap_loc_as_cell!(3)); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), heap_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), heap_loc_as_cell!(3) ); wam.machine_st.heap.clear(); // print L = [L|L]. wam.machine_st.heap.push(list_loc_as_cell!(1)); wam.machine_st.heap.push(list_loc_as_cell!(1)); wam.machine_st.heap.push(list_loc_as_cell!(1)); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), list_loc_as_cell!(1) ); wam.machine_st.heap.clear(); // term is [X,f(Y),Z]. // Z is an attributed variable, but has a variable attributes list. wam.machine_st.heap.push(list_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(3)); // 2 wam.machine_st.heap.push(list_loc_as_cell!(4)); // 3 wam.machine_st.heap.push(str_loc_as_cell!(6)); // 4 wam.machine_st.heap.push(heap_loc_as_cell!(8)); wam.machine_st.heap.push(atom_as_cell!(f_atom, 1)); // 6 wam.machine_st.heap.push(heap_loc_as_cell!(11)); // 7 wam.machine_st.heap.push(list_loc_as_cell!(9)); wam.machine_st.heap.push(heap_loc_as_cell!(9)); wam.machine_st.heap.push(empty_list_as_cell!()); wam.machine_st.heap.push(attr_var_as_cell!(11)); // linked from 7. wam.machine_st.heap.push(heap_loc_as_cell!(12)); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), list_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), str_loc_as_cell!(6) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), heap_loc_as_cell!(8) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(f_atom, 1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), heap_loc_as_cell!(11) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), list_loc_as_cell!(9) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[9]), heap_loc_as_cell!(9) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[10]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[11]), attr_var_as_cell!(11) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[12]), heap_loc_as_cell!(12) ); // now populate the attributes list. let clpz_atom = atom!("clpz"); let p_atom = atom!("p"); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); cell.set_forwarding_bit(false); } wam.machine_st.heap.pop(); wam.machine_st.heap.push(heap_loc_as_cell!(13)); // 12 wam.machine_st.heap.push(list_loc_as_cell!(14)); // 13 wam.machine_st.heap.push(str_loc_as_cell!(16)); // 14 wam.machine_st.heap.push(heap_loc_as_cell!(19)); // 15 wam.machine_st.heap.push(atom_as_cell!(clpz_atom, 2)); // 16 wam.machine_st.heap.push(atom_as_cell!(a_atom)); // 17 wam.machine_st.heap.push(atom_as_cell!(b_atom)); // 18 wam.machine_st.heap.push(list_loc_as_cell!(20)); // 19 wam.machine_st.heap.push(str_loc_as_cell!(22)); // 20 wam.machine_st.heap.push(empty_list_as_cell!()); // 21 wam.machine_st.heap.push(atom_as_cell!(p_atom, 1)); // 22 wam.machine_st.heap.push(heap_loc_as_cell!(23)); // 23 mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), list_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), str_loc_as_cell!(6) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), heap_loc_as_cell!(8) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(f_atom, 1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), heap_loc_as_cell!(11) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), list_loc_as_cell!(9) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[9]), heap_loc_as_cell!(9) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[10]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[11]), attr_var_as_cell!(11) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[12]), heap_loc_as_cell!(13) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[13]), list_loc_as_cell!(14) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[14]), str_loc_as_cell!(16) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[15]), heap_loc_as_cell!(19) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[16]), atom_as_cell!(clpz_atom, 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[17]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[18]), atom_as_cell!(b_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[19]), list_loc_as_cell!(20) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[20]), str_loc_as_cell!(22) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[21]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[22]), atom_as_cell!(p_atom, 1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[23]), heap_loc_as_cell!(23) ); for cell in &mut wam.machine_st.heap { cell.set_mark_bit(false); cell.set_forwarding_bit(false); } // push some unrelated nonsense cells to the heap and check that they // are unmarked after the marker has finished at 0. wam.machine_st.heap.push(heap_loc_as_cell!(5)); wam.machine_st.heap.push(heap_loc_as_cell!(5)); wam.machine_st.heap.push(list_loc_as_cell!(5)); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap[0..24]); for cell in &wam.machine_st.heap[24..] { assert!(!cell.get_mark_bit()); } assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), list_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), str_loc_as_cell!(6) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), heap_loc_as_cell!(8) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), atom_as_cell!(f_atom, 1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), heap_loc_as_cell!(11) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), list_loc_as_cell!(9) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[9]), heap_loc_as_cell!(9) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[10]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[11]), attr_var_as_cell!(11) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[12]), heap_loc_as_cell!(13) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[13]), list_loc_as_cell!(14) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[14]), str_loc_as_cell!(16) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[15]), heap_loc_as_cell!(19) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[16]), atom_as_cell!(clpz_atom, 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[17]), atom_as_cell!(a_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[18]), atom_as_cell!(b_atom) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[19]), list_loc_as_cell!(20) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[20]), str_loc_as_cell!(22) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[21]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[22]), atom_as_cell!(p_atom, 1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[23]), heap_loc_as_cell!(23) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[24]), heap_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[25]), heap_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[26]), list_loc_as_cell!(5) ); wam.machine_st.heap.clear(); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(0))); mark_cells(&mut wam.machine_st.heap, 0); assert_eq!(wam.machine_st.heap.len(), 1); all_cells_marked_and_unforwarded(&wam.machine_st.heap); wam.machine_st.heap.clear(); wam.machine_st.heap.push(str_loc_as_cell!(1)); wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(atom_as_cell!(atom!("y"))); wam.machine_st.heap.push(atom_as_cell!(atom!("="), 2)); wam.machine_st.heap.push(atom_as_cell!(atom!("X"))); wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(list_loc_as_cell!(8)); wam.machine_st.heap.push(str_loc_as_cell!(4)); wam.machine_st.heap.push(empty_list_as_cell!()); mark_cells(&mut wam.machine_st.heap, 7); assert_eq!(wam.machine_st.heap.len(), 10); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), str_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), atom_as_cell!(atom!("g"), 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), atom_as_cell!(atom!("y")) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), atom_as_cell!(atom!("="), 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), atom_as_cell!(atom!("X")) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), heap_loc_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), list_loc_as_cell!(8) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), str_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[9]), empty_list_as_cell!() ); wam.machine_st.heap.clear(); wam.machine_st.heap.push(atom_as_cell!(atom!("f"), 2)); wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(heap_loc_as_cell!(1)); wam.machine_st.heap.push(str_loc_as_cell!(0)); mark_cells(&mut wam.machine_st.heap, 3); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), atom_as_cell!(atom!("f"), 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), heap_loc_as_cell!(1) ); wam.machine_st.heap.clear(); // representation of one of the heap terms as in issue #1384. wam.machine_st.heap.push(list_loc_as_cell!(1)); wam.machine_st.heap.push(empty_list_as_cell!()); wam.machine_st.heap.push(list_loc_as_cell!(3)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(empty_list_as_cell!()); wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(list_loc_as_cell!(5)); mark_cells(&mut wam.machine_st.heap, 7); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), list_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), heap_loc_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), heap_loc_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), heap_loc_as_cell!(2) ); wam.machine_st.heap.clear(); // representation of one of the heap terms as in issue #1384. wam.machine_st.heap.push(list_loc_as_cell!(7)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); wam.machine_st.heap.push(list_loc_as_cell!(3)); // A = [B|[]]. wam.machine_st.heap.push(list_loc_as_cell!(5)); // B = [A|A]. wam.machine_st.heap.push(empty_list_as_cell!()); wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(heap_loc_as_cell!(2)); wam.machine_st.heap.push(empty_list_as_cell!()); // C = [[]|B]. wam.machine_st.heap.push(heap_loc_as_cell!(3)); wam.machine_st.heap.push(heap_loc_as_cell!(0)); mark_cells(&mut wam.machine_st.heap, 9); assert!(wam.machine_st.heap[0].get_mark_bit()); assert!(!wam.machine_st.heap[1].get_mark_bit()); all_cells_marked_and_unforwarded(&wam.machine_st.heap[2..]); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), list_loc_as_cell!(7) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), heap_loc_as_cell!(0) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), list_loc_as_cell!(3) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), list_loc_as_cell!(5) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), heap_loc_as_cell!(2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), heap_loc_as_cell!(2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), empty_list_as_cell!() ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), heap_loc_as_cell!(3) ); wam.machine_st.heap.clear(); wam.machine_st.heap.push(str_loc_as_cell!(1)); wam.machine_st.heap.push(atom_as_cell!(atom!("+"), 2)); wam.machine_st.heap.push(str_loc_as_cell!(4)); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(2))); wam.machine_st.heap.push(atom_as_cell!(atom!("-"), 2)); wam.machine_st.heap.push(str_loc_as_cell!(7)); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(1))); wam.machine_st.heap.push(atom_as_cell!(atom!("+"), 2)); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(3))); wam.machine_st .heap .push(fixnum_as_cell!(Fixnum::build_with(4))); mark_cells(&mut wam.machine_st.heap, 0); all_cells_marked_and_unforwarded(&wam.machine_st.heap); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[0]), str_loc_as_cell!(1) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[1]), atom_as_cell!(atom!("+"), 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[2]), str_loc_as_cell!(4) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[3]), fixnum_as_cell!(Fixnum::build_with(2)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[4]), atom_as_cell!(atom!("-"), 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[5]), str_loc_as_cell!(7) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[6]), fixnum_as_cell!(Fixnum::build_with(1)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[7]), atom_as_cell!(atom!("+"), 2) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[8]), fixnum_as_cell!(Fixnum::build_with(3)) ); assert_eq!( unmark_cell_bits!(wam.machine_st.heap[9]), fixnum_as_cell!(Fixnum::build_with(4)) ); } }