3254 lines
100 KiB
Rust
3254 lines
100 KiB
Rust
#![allow(clippy::new_without_default)] // annotating structs annotated with #[bitfield] doesn't work
|
|
|
|
#[cfg(test)]
|
|
pub(crate) use crate::machine::gc::StacklessPreOrderHeapIter;
|
|
|
|
use crate::atom_table::*;
|
|
use crate::machine::cycle_detection::*;
|
|
use crate::machine::heap::*;
|
|
use crate::machine::stack::*;
|
|
use crate::types::*;
|
|
|
|
use core::marker::PhantomData;
|
|
use scryer_modular_bitfield::prelude::*;
|
|
|
|
use std::ops::Deref;
|
|
use std::vec::Vec;
|
|
|
|
#[inline(always)]
|
|
pub fn eager_stackful_preorder_iter(
|
|
heap: &mut Heap,
|
|
value: HeapCellValue,
|
|
) -> EagerStackfulPreOrderHeapIter {
|
|
EagerStackfulPreOrderHeapIter::new(heap, value)
|
|
}
|
|
|
|
/*
|
|
* Unlike StackfulPreOrderHeapIter, this iterator not only marks
|
|
* cyclic terms for the sake of skipping them at the second visit but
|
|
* leaves them marked until it is dropped. This makes for, e.g., more
|
|
* efficient ground/1 and term_variables/2 definitions.
|
|
*/
|
|
|
|
pub struct EagerStackfulPreOrderHeapIter<'a> {
|
|
start_value: HeapCellValue,
|
|
iter_stack: Vec<HeapCellValue>,
|
|
mark_phase: bool,
|
|
heap: &'a mut Heap,
|
|
}
|
|
|
|
impl<'a> Drop for EagerStackfulPreOrderHeapIter<'a> {
|
|
fn drop(&mut self) {
|
|
self.mark_phase = false;
|
|
|
|
self.iter_stack.clear();
|
|
self.start_value.set_mark_bit(true);
|
|
self.iter_stack.push(self.start_value);
|
|
|
|
while self.follow().is_some() {}
|
|
}
|
|
}
|
|
|
|
impl<'a> EagerStackfulPreOrderHeapIter<'a> {
|
|
pub fn new(heap: &'a mut Heap, value: HeapCellValue) -> Self {
|
|
Self {
|
|
start_value: value,
|
|
iter_stack: vec![value],
|
|
mark_phase: true,
|
|
heap,
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn is_self_ref_var(&self, value: HeapCellValue) -> bool {
|
|
if value.is_var() {
|
|
let h = value.get_value() as usize;
|
|
|
|
if self.heap[h].is_var() && self.heap[h].get_value() as usize == h {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
fn follow(&mut self) -> Option<HeapCellValue> {
|
|
while let Some(value) = self.iter_stack.pop() {
|
|
if value.get_mark_bit() == self.mark_phase {
|
|
// follow marked variables to their end. only marked
|
|
// non-variables are ignored.
|
|
if self.is_self_ref_var(value) {
|
|
return Some(unmark_cell_bits!(value));
|
|
} else if !value.is_var() {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
read_heap_cell!(value,
|
|
(HeapCellValueTag::Str, s) => {
|
|
let arity = cell_as_atom_cell!(self.heap[s]).get_arity();
|
|
|
|
for idx in (s + 1 .. s + arity + 1).rev() {
|
|
if self.heap[idx].get_mark_bit() != self.mark_phase {
|
|
self.iter_stack.push(self.heap[idx]);
|
|
self.heap[idx].set_mark_bit(self.mark_phase);
|
|
}
|
|
}
|
|
}
|
|
(HeapCellValueTag::Lis, l) => {
|
|
if self.heap[l+1].get_mark_bit() != self.mark_phase {
|
|
self.iter_stack.push(self.heap[l+1]);
|
|
self.heap[l+1].set_mark_bit(self.mark_phase);
|
|
}
|
|
|
|
if self.heap[l].get_mark_bit() != self.mark_phase {
|
|
self.iter_stack.push(self.heap[l]);
|
|
self.heap[l].set_mark_bit(self.mark_phase);
|
|
}
|
|
}
|
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
|
let var_value = self.heap[h];
|
|
self.heap[h].set_mark_bit(self.mark_phase);
|
|
|
|
if var_value.get_mark_bit() || !(self.heap[h].is_var() && self.heap[h].get_value() as usize == h) {
|
|
self.iter_stack.push(var_value);
|
|
continue;
|
|
}
|
|
}
|
|
(HeapCellValueTag::PStrLoc, h) => {
|
|
let h = if self.heap[h].get_tag() == HeapCellValueTag::PStr {
|
|
h
|
|
} else {
|
|
debug_assert_eq!(self.heap[h].get_tag(), HeapCellValueTag::PStrOffset);
|
|
self.heap[h].get_value() as usize
|
|
};
|
|
|
|
if self.heap[h].get_mark_bit() == self.mark_phase {
|
|
continue;
|
|
}
|
|
|
|
self.heap[h].set_mark_bit(self.mark_phase);
|
|
|
|
if self.heap[h].get_tag() == HeapCellValueTag::PStr {
|
|
let value = self.heap[h+1];
|
|
self.heap[h+1].set_mark_bit(self.mark_phase);
|
|
self.iter_stack.push(value);
|
|
}
|
|
}
|
|
_ => {
|
|
}
|
|
);
|
|
|
|
return Some(value);
|
|
}
|
|
|
|
None
|
|
}
|
|
}
|
|
|
|
impl<'a> Iterator for EagerStackfulPreOrderHeapIter<'a> {
|
|
type Item = HeapCellValue;
|
|
|
|
#[inline]
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
self.follow()
|
|
}
|
|
}
|
|
|
|
#[derive(BitfieldSpecifier, Clone, Copy, Debug, PartialEq, Eq)]
|
|
#[bits = 2]
|
|
enum IterStackLocTag {
|
|
Iterable,
|
|
Marked,
|
|
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 {
|
|
pub value: B61,
|
|
tag: IterStackLocTag,
|
|
heap_or_stack: HeapOrStackTag,
|
|
}
|
|
|
|
impl IterStackLoc {
|
|
#[inline]
|
|
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]
|
|
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]
|
|
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]
|
|
pub fn is_marked(self) -> bool {
|
|
self.tag() == IterStackLocTag::Marked
|
|
}
|
|
|
|
#[inline]
|
|
pub fn is_pending_mark(self) -> bool {
|
|
self.tag() == IterStackLocTag::PendingMark
|
|
}
|
|
|
|
#[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),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait ListElisionPolicy {
|
|
fn elide_lists() -> bool;
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ListElider {}
|
|
|
|
impl ListElisionPolicy for ListElider {
|
|
#[inline(always)]
|
|
fn elide_lists() -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct NonListElider {}
|
|
|
|
impl ListElisionPolicy for NonListElider {
|
|
#[inline(always)]
|
|
fn elide_lists() -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct StackfulPreOrderHeapIter<'a, ElideLists> {
|
|
pub heap: &'a mut Vec<HeapCellValue>,
|
|
pub machine_stack: &'a mut Stack,
|
|
stack: Vec<IterStackLoc>,
|
|
h: IterStackLoc,
|
|
_marker: PhantomData<ElideLists>,
|
|
}
|
|
|
|
impl<'a, ElideLists> Drop for StackfulPreOrderHeapIter<'a, ElideLists> {
|
|
fn drop(&mut self) {
|
|
while let Some(h) = self.stack.pop() {
|
|
let cell = self.read_cell_mut(h);
|
|
|
|
cell.set_forwarding_bit(false);
|
|
cell.set_mark_bit(false);
|
|
}
|
|
|
|
self.heap.pop();
|
|
}
|
|
}
|
|
|
|
pub trait FocusedHeapIter: Iterator<Item = HeapCellValue> {
|
|
fn focus(&self) -> IterStackLoc;
|
|
}
|
|
|
|
impl<'a, ElideLists: ListElisionPolicy> FocusedHeapIter
|
|
for StackfulPreOrderHeapIter<'a, ElideLists>
|
|
{
|
|
#[inline]
|
|
fn focus(&self) -> IterStackLoc {
|
|
self.h
|
|
}
|
|
}
|
|
|
|
impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
|
|
#[inline]
|
|
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 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 push_stack(&mut self, h: IterStackLoc) {
|
|
self.stack.push(h);
|
|
}
|
|
|
|
#[inline]
|
|
pub fn stack_last(&self) -> Option<IterStackLoc> {
|
|
for h in self.stack.iter().rev() {
|
|
let is_readable_marked = h.is_marked();
|
|
let cell = self.read_cell(*h);
|
|
|
|
if cell.get_forwarding_bit() {
|
|
return Some(*h);
|
|
} else if cell.get_mark_bit() && !is_readable_marked {
|
|
continue;
|
|
}
|
|
|
|
return Some(*h);
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
#[inline]
|
|
pub fn pop_stack(&mut self) -> Option<HeapCellValue> {
|
|
while let Some(h) = self.stack.pop() {
|
|
let is_readable_marked = h.is_marked();
|
|
|
|
self.h = h;
|
|
let cell = self.read_cell_mut(h);
|
|
|
|
if cell.get_forwarding_bit() {
|
|
cell.set_forwarding_bit(false);
|
|
} else if cell.get_mark_bit() && !is_readable_marked {
|
|
cell.set_mark_bit(false);
|
|
continue;
|
|
}
|
|
|
|
return Some(*cell);
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
fn push_if_unmarked(&mut self, loc: IterStackLoc) {
|
|
let cell = self.read_cell_mut(loc);
|
|
|
|
if !cell.get_mark_bit() {
|
|
cell.set_mark_bit(true);
|
|
self.stack.push(IterStackLoc::iterable_loc(
|
|
loc.value() as usize,
|
|
loc.heap_or_stack(),
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists> {
|
|
#[inline]
|
|
fn new(heap: &'a mut Vec<HeapCellValue>, stack: &'a mut Stack, cell: HeapCellValue) -> Self {
|
|
let h = IterStackLoc::iterable_loc(heap.len(), HeapOrStackTag::Heap);
|
|
heap.push(cell);
|
|
|
|
Self {
|
|
heap,
|
|
h,
|
|
machine_stack: stack,
|
|
stack: vec![h],
|
|
_marker: PhantomData,
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn forward_if_referent_marked(&mut self, loc: IterStackLoc) {
|
|
let cell = self.read_cell(loc);
|
|
|
|
read_heap_cell!(cell,
|
|
(HeapCellValueTag::Lis, vh) => {
|
|
let forward = if ElideLists::elide_lists() { true } else { cell.get_mark_bit() };
|
|
|
|
if forward && self.heap[vh].get_mark_bit() {
|
|
self.read_cell_mut(loc).set_forwarding_bit(true);
|
|
}
|
|
}
|
|
(HeapCellValueTag::Str |
|
|
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);
|
|
}
|
|
}
|
|
_ => {}
|
|
);
|
|
}
|
|
|
|
fn follow(&mut self) -> Option<HeapCellValue> {
|
|
while let Some(h) = self.stack.pop() {
|
|
if h.is_pending_mark() {
|
|
self.push_if_unmarked(h);
|
|
self.stack.push(IterStackLoc::mark_loc(
|
|
h.value() as usize,
|
|
h.heap_or_stack(),
|
|
));
|
|
|
|
self.forward_if_referent_marked(h);
|
|
continue;
|
|
}
|
|
|
|
self.h = h;
|
|
|
|
let is_readable_marked = h.is_marked();
|
|
let cell = self.read_cell_mut(h);
|
|
|
|
if cell.get_forwarding_bit() {
|
|
let copy = *cell;
|
|
cell.set_forwarding_bit(false);
|
|
return Some(copy);
|
|
} else if cell.get_mark_bit() && !is_readable_marked {
|
|
cell.set_mark_bit(false);
|
|
continue;
|
|
}
|
|
|
|
read_heap_cell!(*cell,
|
|
(HeapCellValueTag::Str | HeapCellValueTag::PStrLoc, 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) => {
|
|
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
|
|
|
self.forward_if_referent_marked(loc);
|
|
self.push_if_unmarked(loc);
|
|
|
|
self.stack.push(IterStackLoc::pending_mark_loc(vh + 1, HeapOrStackTag::Heap));
|
|
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
|
|
|
return Some(self.read_cell(h));
|
|
}
|
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, vh) => {
|
|
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
|
|
|
self.forward_if_referent_marked(loc);
|
|
self.push_if_unmarked(loc);
|
|
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
|
}
|
|
(HeapCellValueTag::StackVar, vs) => {
|
|
let loc = IterStackLoc::iterable_loc(vs, HeapOrStackTag::Stack);
|
|
|
|
self.forward_if_referent_marked(loc);
|
|
self.push_if_unmarked(loc);
|
|
self.stack.push(IterStackLoc::mark_loc(vs, HeapOrStackTag::Stack));
|
|
}
|
|
(HeapCellValueTag::PStrOffset, offset) => {
|
|
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.read_cell(h));
|
|
}
|
|
(HeapCellValueTag::PStr) => {
|
|
let tail_loc = IterStackLoc::iterable_loc((h.value()+1) as usize, HeapOrStackTag::Heap);
|
|
|
|
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.read_cell(h));
|
|
}
|
|
(HeapCellValueTag::Atom, (_name, arity)) => {
|
|
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 {
|
|
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.read_cell(h));
|
|
}
|
|
_ => {
|
|
return Some(*cell);
|
|
}
|
|
)
|
|
}
|
|
|
|
None
|
|
}
|
|
}
|
|
|
|
impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a, ElideLists> {
|
|
type Item = HeapCellValue;
|
|
|
|
#[inline]
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
self.follow()
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub(crate) fn cycle_detecting_stackless_preorder_iter(
|
|
heap: &'_ mut [HeapCellValue],
|
|
start: usize,
|
|
) -> CycleDetectingIter<'_, true> {
|
|
// const generics argument of true so that cycle discovery stops
|
|
// the iterator.
|
|
CycleDetectingIter::new(heap, start)
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub(crate) fn stackful_preorder_iter<'a, ElideLists: ListElisionPolicy>(
|
|
heap: &'a mut Vec<HeapCellValue>,
|
|
stack: &'a mut Stack,
|
|
cell: HeapCellValue,
|
|
) -> StackfulPreOrderHeapIter<'a, ElideLists> {
|
|
StackfulPreOrderHeapIter::new(heap, stack, cell)
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) struct PostOrderIterator<Iter: FocusedHeapIter> {
|
|
focus: IterStackLoc,
|
|
base_iter: Iter,
|
|
base_iter_valid: bool,
|
|
parent_stack: Vec<(usize, HeapCellValue, IterStackLoc)>, // number of children, parent node, focus.
|
|
}
|
|
|
|
impl<Iter: FocusedHeapIter> Deref for PostOrderIterator<Iter> {
|
|
type Target = Iter;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.base_iter
|
|
}
|
|
}
|
|
|
|
impl<Iter: FocusedHeapIter> PostOrderIterator<Iter> {
|
|
pub(crate) fn new(base_iter: Iter) -> Self {
|
|
PostOrderIterator {
|
|
focus: IterStackLoc::iterable_loc(0, HeapOrStackTag::Heap),
|
|
base_iter,
|
|
base_iter_valid: true,
|
|
parent_stack: vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<Iter: FocusedHeapIter> Iterator for PostOrderIterator<Iter> {
|
|
type Item = HeapCellValue;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
loop {
|
|
if let Some((child_count, node, focus)) = self.parent_stack.pop() {
|
|
if child_count == 0 {
|
|
self.focus = focus;
|
|
return Some(node);
|
|
}
|
|
|
|
self.parent_stack.push((child_count - 1, node, focus));
|
|
}
|
|
|
|
if self.base_iter_valid {
|
|
if let Some(item) = self.base_iter.next() {
|
|
let focus = self.base_iter.focus();
|
|
|
|
read_heap_cell!(item,
|
|
(HeapCellValueTag::Atom, (_name, arity)) => {
|
|
self.parent_stack.push((arity, item, focus));
|
|
}
|
|
(HeapCellValueTag::Lis) => {
|
|
self.parent_stack.push((2, item, focus));
|
|
}
|
|
(HeapCellValueTag::PStr | HeapCellValueTag::PStrOffset) => {
|
|
self.parent_stack.push((1, item, focus));
|
|
}
|
|
_ => {
|
|
self.focus = focus;
|
|
return Some(item);
|
|
}
|
|
);
|
|
|
|
continue;
|
|
} else {
|
|
self.base_iter_valid = false;
|
|
}
|
|
}
|
|
|
|
if self.parent_stack.is_empty() {
|
|
return None;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<Iter: FocusedHeapIter> FocusedHeapIter for PostOrderIterator<Iter> {
|
|
#[inline(always)]
|
|
fn focus(&self) -> IterStackLoc {
|
|
self.focus
|
|
}
|
|
}
|
|
|
|
impl<Iter: FocusedHeapIter> PostOrderIterator<Iter> {
|
|
/* return true if the term at heap offset idx_loc is a
|
|
* direct/inlined subterm of a structure at the focus of
|
|
* self.stack.last(). this function is used to determine, e.g.,
|
|
* ownership of inlined code indices.
|
|
*/
|
|
#[inline]
|
|
pub(crate) fn direct_subterm_of_str(&self, idx_loc: usize) -> bool {
|
|
if let Some((_child_count, item, focus)) = self.parent_stack.last() {
|
|
read_heap_cell!(item,
|
|
(HeapCellValueTag::Atom, (_name, arity)) => {
|
|
let focus = focus.value() as usize;
|
|
return focus + arity >= idx_loc && focus < idx_loc;
|
|
}
|
|
_ => {}
|
|
);
|
|
}
|
|
|
|
false
|
|
}
|
|
}
|
|
|
|
pub(crate) type LeftistPostOrderHeapIter<'a, ElideLists> =
|
|
PostOrderIterator<StackfulPreOrderHeapIter<'a, ElideLists>>;
|
|
|
|
impl<'a, ElideLists: ListElisionPolicy> LeftistPostOrderHeapIter<'a, ElideLists> {
|
|
#[inline]
|
|
pub fn pop_stack(&mut self) {
|
|
if let Some((child_count, ..)) = self.parent_stack.last() {
|
|
for _ in 0..*child_count {
|
|
self.base_iter.pop_stack();
|
|
}
|
|
|
|
self.parent_stack.pop();
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn parent_stack_len(&self) -> usize {
|
|
self.parent_stack.len()
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub(crate) fn stackful_post_order_iter<'a, ElideLists: ListElisionPolicy>(
|
|
heap: &'a mut Heap,
|
|
stack: &'a mut Stack,
|
|
cell: HeapCellValue,
|
|
) -> LeftistPostOrderHeapIter<'a, ElideLists> {
|
|
PostOrderIterator::new(StackfulPreOrderHeapIter::new(heap, stack, cell))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::machine::gc::IteratorUMP;
|
|
use crate::machine::mock_wam::*;
|
|
|
|
pub(crate) type RightistPostOrderHeapIter<'a> =
|
|
PostOrderIterator<StacklessPreOrderHeapIter<'a, IteratorUMP>>;
|
|
|
|
#[inline(always)]
|
|
pub(crate) fn stackless_preorder_iter(
|
|
heap: &mut [HeapCellValue],
|
|
start: usize,
|
|
) -> StacklessPreOrderHeapIter<IteratorUMP> {
|
|
StacklessPreOrderHeapIter::<IteratorUMP>::new(heap, start)
|
|
}
|
|
|
|
#[inline]
|
|
pub(crate) fn stackless_post_order_iter(
|
|
heap: &'_ mut Heap,
|
|
start: usize,
|
|
) -> RightistPostOrderHeapIter {
|
|
PostOrderIterator::new(stackless_preorder_iter(heap, start))
|
|
}
|
|
|
|
#[test]
|
|
#[cfg_attr(miri, ignore = "it takes too long to run")]
|
|
fn heap_stackless_iter_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
|
|
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
|
|
|
wam.machine_st.heap.push(str_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 2)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom, 0)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom, 0)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.extend(functor!(
|
|
f_atom,
|
|
[
|
|
atom(a_atom),
|
|
atom(b_atom),
|
|
atom(a_atom),
|
|
cell(str_loc_as_cell!(0))
|
|
]
|
|
));
|
|
|
|
wam.machine_st.heap.push(str_loc_as_cell!(0));
|
|
|
|
for _ in 0..20 {
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 5);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 4)
|
|
);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&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))
|
|
]
|
|
));
|
|
|
|
for _ in 0..200000 {
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 4)
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(1));
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
{
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
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!());
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.pop();
|
|
|
|
// now make the list cyclic.
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
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.
|
|
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];
|
|
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1),
|
|
);
|
|
|
|
assert!(iter.next().is_none());
|
|
}
|
|
|
|
assert_eq!(wam.machine_st.heap[0], pstr_cell);
|
|
assert_eq!(wam.machine_st.heap[1], heap_loc_as_cell!(1));
|
|
|
|
wam.machine_st.heap[1] = 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];
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(4),
|
|
);
|
|
|
|
assert!(iter.next().is_none());
|
|
}
|
|
|
|
assert_eq!(wam.machine_st.heap[0], pstr_cell);
|
|
assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(3));
|
|
assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(0));
|
|
assert_eq!(wam.machine_st.heap[3], pstr_second_cell);
|
|
assert_eq!(wam.machine_st.heap[4], heap_loc_as_cell!(4));
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(2)));
|
|
|
|
wam.machine_st.heap[2] = heap_loc_as_cell!(4);
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
|
|
|
|
let pstr_offset_cell = pstr_offset_as_cell!(0);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
fixnum_as_cell!(Fixnum::build_with(2))
|
|
);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
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!(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!(0)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(wam.machine_st.heap[6]),
|
|
fixnum_as_cell!(Fixnum::build_with(2))
|
|
);
|
|
|
|
wam.machine_st.heap.truncate(4);
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st
|
|
.heap
|
|
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
|
|
|
|
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
|
|
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 6);
|
|
let pstr_offset_cell = pstr_offset_as_cell!(0);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
pstr_loc_as_cell!(4)
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
fixnum_as_cell!(Fixnum::build_with(0))
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap[5] = fixnum_as_cell!(Fixnum::build_with(1i64));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 6);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
pstr_loc_as_cell!(4)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
pstr_offset_as_cell!(0)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
pstr_offset_as_cell!(0)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
fixnum_as_cell!(Fixnum::build_with(1))
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
assert_eq!(wam.machine_st.heap[4], pstr_offset_as_cell!(0));
|
|
assert_eq!(
|
|
wam.machine_st.heap[5],
|
|
fixnum_as_cell!(Fixnum::build_with(1i64))
|
|
);
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]);
|
|
|
|
wam.machine_st.heap.push(list_loc_as_cell!(1));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(list_loc_as_cell!(3));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
|
|
|
wam.machine_st.heap.extend(functor);
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
// drop the iterator before the iteration is complete to test
|
|
// that modified heap cells are restored to their
|
|
// pre-traversal state by the stackless iterator's Drop
|
|
// instance.
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
|
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
|
|
assert_eq!(wam.machine_st.heap[2], list_loc_as_cell!(3));
|
|
assert_eq!(wam.machine_st.heap[3], str_loc_as_cell!(5));
|
|
assert_eq!(wam.machine_st.heap[4], empty_list_as_cell!());
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
// drop the iterator before the iteration is complete to test
|
|
// that modified heap cells are restored to their
|
|
// pre-traversal state by the stackless iterator's Drop
|
|
// instance.
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
|
assert_eq!(wam.machine_st.heap[1], str_loc_as_cell!(5));
|
|
assert_eq!(wam.machine_st.heap[2], list_loc_as_cell!(3));
|
|
assert_eq!(wam.machine_st.heap[3], str_loc_as_cell!(5));
|
|
assert_eq!(wam.machine_st.heap[4], empty_list_as_cell!());
|
|
|
|
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
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));
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 4);
|
|
|
|
assert_eq!(iter.next().unwrap(), heap_loc_as_cell!(3));
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&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));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&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].
|
|
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));
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 13);
|
|
|
|
assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(4)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(9)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(9)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
attr_var_as_cell!(11)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
// now populate the attributes list. the iteration must not change.
|
|
let clpz_atom = atom!("clpz");
|
|
let p_atom = atom!("p");
|
|
|
|
wam.machine_st.heap.pop();
|
|
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
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 24);
|
|
|
|
assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(4)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(9)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(9)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
attr_var_as_cell!(11)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
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)
|
|
);
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
{
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(0)));
|
|
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
fixnum_as_cell!(Fixnum::build_with(0))
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&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")));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("g"), 2)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("y"))
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
|
|
assert!(iter.next().is_none());
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(0));
|
|
wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("g"), 2)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("y"))
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
|
|
|
|
assert!(iter.next().is_none());
|
|
}
|
|
|
|
all_cells_unmarked(&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!());
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 7);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(8)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("="), 2)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("g"), 2)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("y"))
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("X"))
|
|
);
|
|
|
|
assert!(iter.next().is_none());
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
assert_eq!(wam.machine_st.heap[0], str_loc_as_cell!(1));
|
|
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(atom!("g"), 2));
|
|
assert_eq!(wam.machine_st.heap[2], heap_loc_as_cell!(0));
|
|
assert_eq!(wam.machine_st.heap[3], atom_as_cell!(atom!("y")));
|
|
assert_eq!(wam.machine_st.heap[4], atom_as_cell!(atom!("="), 2));
|
|
assert_eq!(wam.machine_st.heap[5], atom_as_cell!(atom!("X")));
|
|
assert_eq!(wam.machine_st.heap[6], heap_loc_as_cell!(0));
|
|
assert_eq!(wam.machine_st.heap[7], list_loc_as_cell!(8));
|
|
assert_eq!(wam.machine_st.heap[8], str_loc_as_cell!(4));
|
|
assert_eq!(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));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("f"), 2)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1)
|
|
);
|
|
|
|
assert!(iter.next().is_none());
|
|
}
|
|
|
|
assert_eq!(wam.machine_st.heap[0], atom_as_cell!(atom!("f"), 2));
|
|
assert_eq!(wam.machine_st.heap[1], heap_loc_as_cell!(1));
|
|
assert_eq!(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!(7)); // 0
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0)); // 1
|
|
wam.machine_st.heap.push(list_loc_as_cell!(3)); // 2
|
|
wam.machine_st.heap.push(list_loc_as_cell!(5)); // 3
|
|
wam.machine_st.heap.push(empty_list_as_cell!()); // 4
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(2)); // 5
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(2)); // 6
|
|
wam.machine_st.heap.push(empty_list_as_cell!()); // 7
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(3)); // 8
|
|
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 9);
|
|
|
|
/*
|
|
while let Some(_) = iter.next() {
|
|
print_heap_terms(iter.heap.iter(), 0);
|
|
println!("");
|
|
}
|
|
*/
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(7)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(5)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(2)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(2)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn heap_stackful_iter_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
|
|
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
|
|
|
{
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
str_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 2)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.extend(functor!(
|
|
f_atom,
|
|
[
|
|
atom(a_atom),
|
|
atom(b_atom),
|
|
atom(a_atom),
|
|
cell(str_loc_as_cell!(0))
|
|
]
|
|
));
|
|
|
|
for _ in 0..20 {
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
str_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 4)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
{
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::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
|
|
// and marking bits set to true. it suffices to check only the
|
|
// forwarding bit to detect cycles of all kinds, including
|
|
// unbound/self-referencing variables.
|
|
|
|
var.set_forwarding_bit(true);
|
|
var.set_mark_bit(true);
|
|
|
|
assert_eq!(iter.next().unwrap(), var);
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
{
|
|
// mutually referencing variables.
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(1));
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
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!());
|
|
|
|
{
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.pop();
|
|
|
|
// now make the list cyclic.
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::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!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
{
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::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
|
|
// StackfulPreOrderHeapIter.
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
|
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
|
assert_eq!(wam.machine_st.heap[2], list_loc_as_cell!(3));
|
|
assert_eq!(wam.machine_st.heap[3], atom_as_cell!(b_atom));
|
|
assert_eq!(wam.machine_st.heap[4], 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.
|
|
|
|
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];
|
|
|
|
{
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::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!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1),
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
// here
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(2));
|
|
|
|
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];
|
|
|
|
{
|
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
|
&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);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(3),
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st
|
|
.heap
|
|
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
|
|
|
|
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
|
|
|
|
{
|
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
|
&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);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
|
|
assert_eq!(
|
|
iter.next().unwrap(),
|
|
fixnum_as_cell!(Fixnum::build_with(0i64))
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
/*
|
|
{
|
|
let mut iter = HeapPStrIter::new(&wam.machine_st.heap, 0);
|
|
let string: String = iter.chars().collect();
|
|
assert_eq!(string, "abc def");
|
|
}
|
|
*/
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
|
|
|
|
{
|
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
|
&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);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
|
|
assert_eq!(
|
|
iter.next().unwrap(),
|
|
fixnum_as_cell!(Fixnum::build_with(1i64))
|
|
);
|
|
|
|
let h = iter.focus();
|
|
|
|
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))
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]);
|
|
|
|
wam.machine_st.heap.push(list_loc_as_cell!(1));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(list_loc_as_cell!(3));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
|
|
|
wam.machine_st.heap.extend(functor);
|
|
|
|
{
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
|
|
|
{
|
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
let mut link_back = list_loc_as_cell!(1);
|
|
|
|
link_back.set_forwarding_bit(true);
|
|
link_back.set_mark_bit(true);
|
|
|
|
assert_eq!(iter.next().unwrap(), link_back);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
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));
|
|
|
|
{
|
|
let mut iter = StackfulPreOrderHeapIter::<NonListElider>::new(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
let mut cyclic_link = list_loc_as_cell!(1);
|
|
|
|
cyclic_link.set_forwarding_bit(true);
|
|
cyclic_link.set_mark_bit(true);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
assert_eq!(iter.next().unwrap(), cyclic_link);
|
|
assert_eq!(iter.next().unwrap(), cyclic_link);
|
|
assert_eq!(iter.next().unwrap(), cyclic_link);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.push(pstr_as_cell!(atom!("a string")));
|
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
|
|
|
{
|
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
pstr_as_cell!(atom!("a string"))
|
|
);
|
|
|
|
assert_eq!(iter.next().unwrap(), empty_list_as_cell!());
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&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!());
|
|
|
|
{
|
|
let mut iter = stackful_preorder_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("g"), 2)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(atom!("y"))
|
|
);
|
|
|
|
assert!(iter.next().is_none());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn heap_stackful_post_order_iter() {
|
|
let mut wam = MockWAM::new();
|
|
|
|
let f_atom = atom!("f");
|
|
let a_atom = atom!("a");
|
|
let b_atom = atom!("b");
|
|
|
|
wam.machine_st
|
|
.heap
|
|
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
str_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 2)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.extend(functor!(
|
|
f_atom,
|
|
[
|
|
atom(a_atom),
|
|
atom(b_atom),
|
|
atom(a_atom),
|
|
cell(str_loc_as_cell!(0))
|
|
]
|
|
));
|
|
|
|
for _ in 0..20 {
|
|
// 0000 {
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
str_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 4)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
{
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&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
|
|
// and marking bits set to true. it suffices to check only the
|
|
// forwarding bit to detect cycles of all kinds, including
|
|
// unbound/self-referencing variables.
|
|
|
|
var.set_forwarding_bit(true);
|
|
var.set_mark_bit(true);
|
|
|
|
assert_eq!(iter.next().unwrap(), var);
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
{
|
|
// mutually referencing variables.
|
|
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::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
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!());
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.pop();
|
|
|
|
// now make the list cyclic.
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&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!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&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
|
|
// StackfulPreOrderHeapIter.
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
|
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
|
assert_eq!(wam.machine_st.heap[2], list_loc_as_cell!(3));
|
|
assert_eq!(wam.machine_st.heap[3], atom_as_cell!(b_atom));
|
|
assert_eq!(wam.machine_st.heap[4], 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.
|
|
|
|
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];
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
pstr_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1),
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
|
|
|
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];
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
pstr_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(3),
|
|
);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st
|
|
.heap
|
|
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
|
|
|
|
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(0i64)));
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&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)
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&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)
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]);
|
|
|
|
wam.machine_st.heap.push(list_loc_as_cell!(1));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(list_loc_as_cell!(3));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
|
|
|
wam.machine_st.heap.extend(functor);
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
|
|
|
{
|
|
let mut iter = stackful_post_order_iter::<NonListElider>(
|
|
&mut wam.machine_st.heap,
|
|
&mut wam.machine_st.stack,
|
|
heap_loc_as_cell!(0),
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
let mut link_back = list_loc_as_cell!(1);
|
|
|
|
link_back.set_forwarding_bit(true);
|
|
link_back.set_mark_bit(true);
|
|
|
|
assert_eq!(iter.next().unwrap(), link_back);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
wam.machine_st.heap.clear();
|
|
}
|
|
|
|
#[test]
|
|
fn heap_stackless_post_order_iter() {
|
|
let mut wam = MockWAM::new();
|
|
|
|
let f_atom = atom!("f");
|
|
let a_atom = atom!("a");
|
|
let b_atom = atom!("b");
|
|
|
|
wam.machine_st
|
|
.heap
|
|
.extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
|
|
|
|
wam.machine_st.heap.push(str_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 3);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 2)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
wam.machine_st.heap.extend(functor!(
|
|
f_atom,
|
|
[
|
|
atom(a_atom),
|
|
atom(b_atom),
|
|
atom(a_atom),
|
|
cell(str_loc_as_cell!(0))
|
|
]
|
|
));
|
|
|
|
wam.machine_st.heap.push(str_loc_as_cell!(0));
|
|
|
|
for _ in 0..20 {
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 5);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 4)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
{
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
{
|
|
// mutually referencing variables.
|
|
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, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
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!());
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.pop();
|
|
|
|
// now make the list cyclic.
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
// the cycle will be iterated twice before being detected.
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
// cut the iteration short to check that all cells are
|
|
// unmarked and unforwarded by the Drop instance of
|
|
// StacklessPreOrderHeapIter.
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(0)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
assert_eq!(wam.machine_st.heap[0], list_loc_as_cell!(1));
|
|
assert_eq!(wam.machine_st.heap[1], atom_as_cell!(a_atom));
|
|
assert_eq!(wam.machine_st.heap[2], list_loc_as_cell!(3));
|
|
assert_eq!(wam.machine_st.heap[3], atom_as_cell!(b_atom));
|
|
assert_eq!(wam.machine_st.heap[4], 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.
|
|
|
|
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];
|
|
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 2);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(1),
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
|
|
|
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];
|
|
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 4);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(3),
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st
|
|
.heap
|
|
.push(pstr_loc_as_cell!(wam.machine_st.heap.len() + 1));
|
|
|
|
wam.machine_st.heap.push(pstr_offset_as_cell!(0));
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(0)));
|
|
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 7);
|
|
let mut pstr_loc_cell = pstr_loc_as_cell!(0);
|
|
|
|
pstr_loc_cell.set_forwarding_bit(true);
|
|
|
|
// assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64)));
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(3)
|
|
);
|
|
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st.heap.pop();
|
|
wam.machine_st
|
|
.heap
|
|
.push(fixnum_as_cell!(Fixnum::build_with(1)));
|
|
|
|
wam.machine_st.heap.push(pstr_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 7);
|
|
|
|
//assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1)));
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
heap_loc_as_cell!(3)
|
|
);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
|
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
wam.machine_st.heap.clear();
|
|
|
|
let functor = functor!(f_atom, [atom(a_atom), atom(b_atom), atom(b_atom)]);
|
|
|
|
wam.machine_st.heap.push(list_loc_as_cell!(1));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(list_loc_as_cell!(3));
|
|
wam.machine_st.heap.push(str_loc_as_cell!(5));
|
|
wam.machine_st.heap.push(empty_list_as_cell!());
|
|
|
|
wam.machine_st.heap.extend(functor);
|
|
|
|
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 9);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
empty_list_as_cell!()
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
|
|
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
|
|
|
{
|
|
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(b_atom)
|
|
);
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(a_atom)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
atom_as_cell!(f_atom, 3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(3)
|
|
);
|
|
|
|
assert_eq!(
|
|
unmark_cell_bits!(iter.next().unwrap()),
|
|
list_loc_as_cell!(1)
|
|
);
|
|
|
|
assert_eq!(iter.next(), None);
|
|
}
|
|
|
|
all_cells_unmarked(&wam.machine_st.heap);
|
|
}
|
|
}
|