Merge branch 'master' into library-use-case
This commit is contained in:
504
src/heap_iter.rs
504
src/heap_iter.rs
@@ -1,5 +1,6 @@
|
||||
#[cfg(test)]
|
||||
pub(crate) use crate::machine::gc::{IteratorUMP, StacklessPreOrderHeapIter};
|
||||
pub(crate) use crate::machine::gc::{IteratorUMP};
|
||||
pub(crate) use crate::machine::gc::{CycleDetectorUMP, StacklessPreOrderHeapIter};
|
||||
|
||||
use crate::atom_table::*;
|
||||
use crate::machine::heap::*;
|
||||
@@ -12,6 +13,145 @@ use 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 let Some(_) = self.follow() {}
|
||||
}
|
||||
}
|
||||
|
||||
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 !(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;
|
||||
}
|
||||
|
||||
let value = self.heap[h+1];
|
||||
|
||||
self.heap[h].set_mark_bit(self.mark_phase);
|
||||
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 {
|
||||
@@ -198,11 +338,6 @@ impl<'a, ElideLists> StackfulPreOrderHeapIter<'a, ElideLists> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn stack_len(&self) -> usize {
|
||||
self.stack.len()
|
||||
}
|
||||
|
||||
fn push_if_unmarked(&mut self, loc: IterStackLoc) {
|
||||
let cell = self.read_cell_mut(loc);
|
||||
|
||||
@@ -236,17 +371,17 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
||||
let cell = self.read_cell(loc);
|
||||
|
||||
read_heap_cell!(cell,
|
||||
(HeapCellValueTag::Lis |
|
||||
HeapCellValueTag::Str |
|
||||
HeapCellValueTag::PStrLoc, vh) => {
|
||||
(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::AttrVar |
|
||||
HeapCellValueTag::Var, vh) => {
|
||||
(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);
|
||||
}
|
||||
@@ -374,11 +509,20 @@ impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a
|
||||
#[inline(always)]
|
||||
pub(crate) fn stackless_preorder_iter(
|
||||
heap: &mut Vec<HeapCellValue>,
|
||||
cell: HeapCellValue,
|
||||
start: usize,
|
||||
) -> StacklessPreOrderHeapIter<IteratorUMP> {
|
||||
StacklessPreOrderHeapIter::<IteratorUMP>::new(heap, cell)
|
||||
StacklessPreOrderHeapIter::<IteratorUMP>::new(heap, start)
|
||||
}
|
||||
|
||||
|
||||
pub(crate) fn cycle_detecting_stackless_preorder_iter(
|
||||
heap: &mut Heap,
|
||||
start: usize,
|
||||
) -> StacklessPreOrderHeapIter<CycleDetectorUMP> {
|
||||
StacklessPreOrderHeapIter::<CycleDetectorUMP>::new(heap, start)
|
||||
}
|
||||
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn stackful_preorder_iter<'a, ElideLists: ListElisionPolicy>(
|
||||
heap: &'a mut Vec<HeapCellValue>,
|
||||
@@ -529,9 +673,9 @@ pub(crate) type RightistPostOrderHeapIter<'a> =
|
||||
#[inline]
|
||||
pub(crate) fn stackless_post_order_iter<'a>(
|
||||
heap: &'a mut Heap,
|
||||
cell: HeapCellValue,
|
||||
start: usize,
|
||||
) -> RightistPostOrderHeapIter<'a> {
|
||||
PostOrderIterator::new(stackless_preorder_iter(heap, cell))
|
||||
PostOrderIterator::new(stackless_preorder_iter(heap, start))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -551,8 +695,10 @@ mod tests {
|
||||
.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, 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()),
|
||||
@@ -584,8 +730,10 @@ mod tests {
|
||||
]
|
||||
));
|
||||
|
||||
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, str_loc_as_cell!(0));
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 5);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -628,7 +776,7 @@ mod tests {
|
||||
));
|
||||
|
||||
for _ in 0..200000 {
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 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()),
|
||||
@@ -659,7 +807,7 @@ mod tests {
|
||||
{
|
||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 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()),
|
||||
@@ -680,7 +828,7 @@ mod tests {
|
||||
wam.machine_st.heap.push(empty_list_as_cell!());
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 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()),
|
||||
@@ -715,7 +863,7 @@ mod tests {
|
||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 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()),
|
||||
@@ -749,8 +897,10 @@ mod tests {
|
||||
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, 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!(
|
||||
@@ -764,8 +914,7 @@ mod tests {
|
||||
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.pop();
|
||||
wam.machine_st.heap.push(pstr_loc_as_cell!(2));
|
||||
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);
|
||||
@@ -773,36 +922,40 @@ mod tests {
|
||||
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, 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()), pstr_second_cell);
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
heap_loc_as_cell!(3),
|
||||
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!(2));
|
||||
assert_eq!(wam.machine_st.heap[2], pstr_second_cell);
|
||||
assert_eq!(wam.machine_st.heap[3], heap_loc_as_cell!(3));
|
||||
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!(4));
|
||||
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, pstr_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);
|
||||
|
||||
@@ -812,19 +965,19 @@ mod tests {
|
||||
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_second_cell);
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(wam.machine_st.heap[3]),
|
||||
pstr_loc_as_cell!(4)
|
||||
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_offset_as_cell!(0)
|
||||
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))
|
||||
);
|
||||
|
||||
@@ -840,31 +993,31 @@ mod tests {
|
||||
.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, 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_second_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.pop();
|
||||
wam.machine_st
|
||||
.heap
|
||||
.push(fixnum_as_cell!(Fixnum::build_with(1i64)));
|
||||
wam.machine_st.heap[5] = fixnum_as_cell!(Fixnum::build_with(1i64));
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
|
||||
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_second_cell);
|
||||
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_loc_as_cell!(4));
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -874,13 +1027,17 @@ mod tests {
|
||||
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!(iter.heap[4], pstr_offset_as_cell!(0));
|
||||
assert_eq!(iter.heap[5], fixnum_as_cell!(Fixnum::build_with(1i64)));
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -896,7 +1053,7 @@ mod tests {
|
||||
wam.machine_st.heap.extend(functor);
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 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()),
|
||||
@@ -933,26 +1090,13 @@ mod tests {
|
||||
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!(iter.next(), None);
|
||||
}
|
||||
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 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()),
|
||||
@@ -999,7 +1143,7 @@ mod tests {
|
||||
assert_eq!(wam.machine_st.heap[4], empty_list_as_cell!());
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 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()),
|
||||
@@ -1031,7 +1175,7 @@ mod tests {
|
||||
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 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()),
|
||||
@@ -1069,19 +1213,6 @@ mod tests {
|
||||
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!(iter.next(), None);
|
||||
}
|
||||
|
||||
@@ -1093,12 +1224,12 @@ mod tests {
|
||||
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, 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);
|
||||
}
|
||||
|
||||
@@ -1129,7 +1260,7 @@ mod tests {
|
||||
wam.machine_st.heap.push(list_loc_as_cell!(1));
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
||||
|
||||
assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
|
||||
assert_eq!(
|
||||
@@ -1137,10 +1268,6 @@ mod tests {
|
||||
list_loc_as_cell!(1)
|
||||
);
|
||||
|
||||
assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
|
||||
// this is what happens! this next line! We would like it not to happen though.
|
||||
assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
|
||||
|
||||
assert_eq!(iter.next(), None);
|
||||
}
|
||||
|
||||
@@ -1176,9 +1303,10 @@ mod tests {
|
||||
|
||||
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, 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));
|
||||
|
||||
@@ -1217,6 +1345,7 @@ mod tests {
|
||||
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
|
||||
@@ -1231,9 +1360,10 @@ mod tests {
|
||||
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, 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));
|
||||
|
||||
@@ -1368,10 +1498,9 @@ mod tests {
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(
|
||||
&mut wam.machine_st.heap,
|
||||
fixnum_as_cell!(Fixnum::build_with(0)),
|
||||
);
|
||||
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()),
|
||||
@@ -1383,8 +1512,6 @@ mod tests {
|
||||
|
||||
all_cells_unmarked(&wam.machine_st.heap);
|
||||
|
||||
assert_eq!(wam.machine_st.heap.len(), 0);
|
||||
|
||||
wam.machine_st.heap.clear();
|
||||
|
||||
wam.machine_st.heap.push(str_loc_as_cell!(1));
|
||||
@@ -1394,7 +1521,7 @@ mod tests {
|
||||
wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(1));
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -1406,7 +1533,7 @@ mod tests {
|
||||
atom_as_cell!(atom!("y"))
|
||||
);
|
||||
|
||||
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(1));
|
||||
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), heap_loc_as_cell!(0));
|
||||
|
||||
assert!(iter.next().is_none());
|
||||
}
|
||||
@@ -1418,9 +1545,10 @@ mod tests {
|
||||
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, 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()),
|
||||
@@ -1453,7 +1581,7 @@ mod tests {
|
||||
wam.machine_st.heap.push(empty_list_as_cell!());
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(7));
|
||||
let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 7);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -1511,9 +1639,10 @@ mod tests {
|
||||
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, 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()),
|
||||
@@ -1540,38 +1669,68 @@ mod tests {
|
||||
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));
|
||||
wam.machine_st.heap.push(list_loc_as_cell!(5));
|
||||
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!());
|
||||
wam.machine_st.heap.push(heap_loc_as_cell!(3));
|
||||
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
|
||||
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(
|
||||
&mut wam.machine_st.heap,
|
||||
heap_loc_as_cell!(0),
|
||||
);
|
||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
while let Some(_) = iter.next() {
|
||||
print_heap_terms(iter.heap.iter(), 0);
|
||||
println!("");
|
||||
}
|
||||
{
|
||||
let mut iter = stackless_preorder_iter(
|
||||
&mut wam.machine_st.heap,
|
||||
9,
|
||||
);
|
||||
|
||||
/*
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
atom_as_cell!(atom!("f"), 2)
|
||||
);
|
||||
/*
|
||||
while let Some(_) = iter.next() {
|
||||
print_heap_terms(iter.heap.iter(), 0);
|
||||
println!("");
|
||||
}
|
||||
*/
|
||||
|
||||
assert!(iter.next().is_none());
|
||||
*/
|
||||
}
|
||||
*/
|
||||
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]
|
||||
@@ -2663,8 +2822,10 @@ mod tests {
|
||||
.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, 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()),
|
||||
@@ -2694,8 +2855,10 @@ mod tests {
|
||||
]
|
||||
));
|
||||
|
||||
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, str_loc_as_cell!(0));
|
||||
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));
|
||||
|
||||
@@ -2726,7 +2889,7 @@ mod tests {
|
||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
let mut iter =
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -2742,8 +2905,7 @@ mod tests {
|
||||
wam.machine_st.heap.push(heap_loc_as_cell!(1));
|
||||
wam.machine_st.heap.push(heap_loc_as_cell!(0));
|
||||
|
||||
let mut iter =
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
|
||||
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -2769,7 +2931,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut iter =
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -2802,7 +2964,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut iter =
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
||||
|
||||
// the cycle will be iterated twice before being detected.
|
||||
assert_eq!(
|
||||
@@ -2831,7 +2993,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut iter =
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
|
||||
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
|
||||
@@ -2865,9 +3027,11 @@ mod tests {
|
||||
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, pstr_loc_as_cell!(0));
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, 2);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -2879,6 +3043,7 @@ mod tests {
|
||||
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));
|
||||
|
||||
@@ -2887,9 +3052,10 @@ mod tests {
|
||||
|
||||
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, 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()),
|
||||
@@ -2914,9 +3080,10 @@ mod tests {
|
||||
.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, 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);
|
||||
@@ -2924,11 +3091,7 @@ mod tests {
|
||||
// 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_offset_as_cell!(0)
|
||||
heap_loc_as_cell!(3)
|
||||
);
|
||||
|
||||
assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
|
||||
@@ -2939,28 +3102,27 @@ mod tests {
|
||||
|
||||
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, 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()),
|
||||
pstr_offset_as_cell!(0)
|
||||
heap_loc_as_cell!(3)
|
||||
);
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
pstr_offset_as_cell!(0)
|
||||
pstr_second_cell
|
||||
);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2976,9 +3138,10 @@ mod tests {
|
||||
|
||||
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, 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()),
|
||||
@@ -3008,18 +3171,6 @@ mod tests {
|
||||
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()),
|
||||
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)
|
||||
@@ -3038,8 +3189,7 @@ mod tests {
|
||||
wam.machine_st.heap[4] = list_loc_as_cell!(1);
|
||||
|
||||
{
|
||||
let mut iter =
|
||||
stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
|
||||
let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
|
||||
|
||||
assert_eq!(
|
||||
unmark_cell_bits!(iter.next().unwrap()),
|
||||
@@ -3059,25 +3209,15 @@ mod tests {
|
||||
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().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()),
|
||||
|
||||
@@ -328,6 +328,9 @@ staggered_sc(_, G) :- call(G).
|
||||
% to reason about the programs. Also restricts the ability to run the program with alternative execution strategies
|
||||
!.
|
||||
|
||||
:- non_counted_backtracking get_cp/1.
|
||||
get_cp(B) :- '$get_cp'(B).
|
||||
|
||||
:- non_counted_backtracking set_cp/1.
|
||||
|
||||
set_cp(B) :- '$set_cp'(B).
|
||||
@@ -359,24 +362,21 @@ cont_list_goal(Conts, '$call'(builtins:dispatch_call_list(Conts))).
|
||||
|
||||
:- non_counted_backtracking dispatch_prep/3.
|
||||
|
||||
dispatch_prep(Gs, B, [Cont|Conts]) :-
|
||||
dispatch_prep(Gs, B, Conts) :-
|
||||
( callable(Gs) ->
|
||||
strip_module(Gs, M, Gs0),
|
||||
( nonvar(Gs0),
|
||||
dispatch_prep_(Gs0, B, [Cont|Conts]) ->
|
||||
dispatch_prep_(Gs0, B, Conts) ->
|
||||
true
|
||||
; Gs0 == ! ->
|
||||
Cont = '$call'(builtins:set_cp(B)),
|
||||
Conts = []
|
||||
Conts = ['$call'(builtins:set_cp(B))]
|
||||
; nonvar(Gs0),
|
||||
\+ callable(Gs0) ->
|
||||
throw(dispatch_prep_error)
|
||||
; Cont = Gs,
|
||||
Conts = []
|
||||
; Conts = [Gs]
|
||||
)
|
||||
; var(Gs) ->
|
||||
Cont = Gs,
|
||||
Conts = []
|
||||
Conts = [Gs]
|
||||
; throw(dispatch_prep_error)
|
||||
).
|
||||
|
||||
@@ -387,20 +387,32 @@ dispatch_prep_((G1, G2), B, [Cont|Conts]) :-
|
||||
dispatch_prep(G1, B, IConts1),
|
||||
cont_list_goal(IConts1, Cont),
|
||||
dispatch_prep(G2, B, Conts).
|
||||
dispatch_prep_((G1 ; G2), B, [Cont|Conts]) :-
|
||||
dispatch_prep(G1, B, IConts0),
|
||||
dispatch_prep_((G1 ; G2), B, Conts) :-
|
||||
( nonvar(G1) ->
|
||||
( G1 = (G11 -> G12) ->
|
||||
dispatch_prep(G11, B, IConts2),
|
||||
dispatch_prep(G12, B, IConts3),
|
||||
cont_list_goal(IConts2, Cont2),
|
||||
cont_list_goal(IConts3, Cont3),
|
||||
Cont0 = '$call'(builtins:staggered_if_then(Cont2, Cont3))
|
||||
; dispatch_prep(G1, B, IConts0),
|
||||
dispatch_prep(G2, B, IConts1),
|
||||
cont_list_goal(IConts0, Cont0)
|
||||
)
|
||||
; dispatch_prep(G1, B1, IConts0),
|
||||
cont_list_goal(IConts0, Cont0)
|
||||
),
|
||||
dispatch_prep(G2, B, IConts1),
|
||||
cont_list_goal(IConts0, Cont0),
|
||||
cont_list_goal(IConts1, Cont1),
|
||||
Cont = '$call'(builtins:staggered_sc(Cont0, Cont1)),
|
||||
Conts = [].
|
||||
dispatch_prep_((G1 -> G2), B, [Cont|Conts]) :-
|
||||
dispatch_prep(G1, B, IConts1),
|
||||
Conts = ['$call'(builtins:staggered_sc(Cont0, Cont1))].
|
||||
dispatch_prep_((G1 -> G2), B, Conts) :-
|
||||
dispatch_prep(G1, B1, IConts1),
|
||||
dispatch_prep(G2, B, IConts2),
|
||||
cont_list_goal(IConts1, Cont1),
|
||||
cont_list_goal(IConts2, Cont2),
|
||||
Cont = '$call'(builtins:staggered_if_then(Cont1, Cont2)),
|
||||
Conts = [].
|
||||
Conts = ['$call'(builtins:get_cp(B1)),
|
||||
'$call'(builtins:staggered_if_then(Cont1, Cont2))].
|
||||
|
||||
|
||||
:- non_counted_backtracking dispatch_call_list/1.
|
||||
|
||||
214
src/lib/clpz.pl
214
src/lib/clpz.pl
@@ -1030,8 +1030,8 @@ term_expansion(Term0, Term) :-
|
||||
once(duodcg_body(Body0, Body, As0, As, Bs0, Bs)).
|
||||
|
||||
duodcg_body([], (As0=As,Bs0=Bs), As0, As, Bs0, Bs).
|
||||
duodcg_body(Xs+Ys, (phrase(list(Xs), As0, As),
|
||||
phrase(list(Ys), Bs0, Bs)), As0, As, Bs0, Bs).
|
||||
duodcg_body(Xs+Ys, (phrase(seq(Xs), As0, As),
|
||||
phrase(seq(Ys), Bs0, Bs)), As0, As, Bs0, Bs).
|
||||
duodcg_body({Goal}, call(Goal), As, As, Bs, Bs).
|
||||
duodcg_body((A0,B0), (A,B), As0, As, Bs0, Bs) :-
|
||||
duodcg_body(A0, A, As0, As1, Bs0, Bs1),
|
||||
@@ -1957,7 +1957,6 @@ choice_order_variable(step, Order, Var, Vars, Vars0, Selection, Consistency) :-
|
||||
( Var = Next,
|
||||
label(Vars, Selection, Order, step, Consistency)
|
||||
; neq_num(Var, Next),
|
||||
do_queue,
|
||||
label(Vars0, Selection, Order, step, Consistency)
|
||||
).
|
||||
choice_order_variable(enum, Order, Var, Vars, _, Selection, Consistency) :-
|
||||
@@ -2566,13 +2565,13 @@ parse_clpz(E, R,
|
||||
g(power_var_num(E, V, N)) => [p(pexp(V, N, R))],
|
||||
m(A*B) => [p(ptimes(A, B, R))],
|
||||
m(A-B) => [p(pplus(R,B,A))],
|
||||
m(-A) => [p(ptimes(-1,A,R))],
|
||||
m(-A) => [p(pplus(A,R,0))],
|
||||
m(max(A,B)) => [g(A #=< #R), g(B #=< R), p(pmax(A, B, R))],
|
||||
m(min(A,B)) => [g(A #>= #R), g(B #>= R), p(pmin(A, B, R))],
|
||||
m(A mod B) => [g(B #\= 0), p(pmod(A, B, R))],
|
||||
m(A rem B) => [g(B #\= 0), p(prem(A, B, R))],
|
||||
m(abs(A)) => [g(#R #>= 0), p(pabs(A, R))],
|
||||
m(A/B) => [g(B #\= 0), p(prdiv(A, B, R))],
|
||||
m(A/B) => [g(B #\= 0), p(ptimes(R, B, A))],
|
||||
m(A//B) => [g(B #\= 0), p(ptzdiv(A, B, R))],
|
||||
m(A div B) => [g(#R #= (A - (A mod B)) // B)],
|
||||
m(A^B) => [p(pexp(A, B, R))],
|
||||
@@ -2636,14 +2635,37 @@ parse_goals([]) --> [].
|
||||
parse_goals([G|Gs]) --> parse_goal(G), parse_goals(Gs).
|
||||
|
||||
parse_goal(g(Goal)) --> [Goal].
|
||||
parse_goal(p(Prop)) -->
|
||||
{ term_variables(Prop, Vs) },
|
||||
parse_goal(p(Prop0)) -->
|
||||
{ term_variables(Prop0, Vs),
|
||||
morphing_propagator(Prop0, Prop, _) },
|
||||
[make_propagator(Prop, P),
|
||||
new_queue(Q0),
|
||||
phrase(init_propagator_(Vs, P), [Q0], [Q]),
|
||||
variables_same_queue(Vs),
|
||||
trigger_once_(P, Q)].
|
||||
|
||||
morphing(pplus).
|
||||
morphing(ptimes).
|
||||
morphing(pexp).
|
||||
morphing(ptzdiv).
|
||||
|
||||
morphing_propagator(P0, P, Target) :-
|
||||
P0 =.. [F|Args0],
|
||||
( morphing(F) ->
|
||||
append(Args0, [Last], Args),
|
||||
Target = p(Last)
|
||||
; Args = Args0,
|
||||
Target = none
|
||||
),
|
||||
P =.. [F|Args].
|
||||
|
||||
morph_into_propagator(MState, Vs, P0, Morph) -->
|
||||
kill(MState),
|
||||
{ morphing_propagator(P0, P, _),
|
||||
make_propagator(P, Morph) },
|
||||
init_propagator_(Vs, Morph),
|
||||
trigger_prop(Morph).
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
?- use_module(library(lists)),
|
||||
use_module(library(format)),
|
||||
@@ -2734,14 +2756,12 @@ geq(A, B) :-
|
||||
)
|
||||
; ( AI cis_geq n(B) -> true
|
||||
; domain_remove_smaller_than(AD, B, AD1),
|
||||
fd_put(A, AD1, APs),
|
||||
do_queue
|
||||
fd_put(A, AD1, APs)
|
||||
)
|
||||
)
|
||||
; fd_get(B, BD, BPs) ->
|
||||
domain_remove_greater_than(BD, A, BD1),
|
||||
fd_put(B, BD1, BPs),
|
||||
do_queue
|
||||
fd_put(B, BD1, BPs)
|
||||
; A >= B
|
||||
).
|
||||
|
||||
@@ -2811,7 +2831,7 @@ matches([
|
||||
m(var(X) #= var(Y)+var(Z)) => [p(pplus(Y,Z,X))],
|
||||
m(var(X) #= var(Y)-var(Z)) => [p(pplus(X,Z,Y))],
|
||||
m(var(X) #= var(Y)*var(Z)) => [p(ptimes(Y,Z,X))],
|
||||
m(var(X) #= -var(Z)) => [p(ptimes(-1, Z, X))],
|
||||
m(var(X) #= -var(Y)) => [p(pplus(X,Y,0))],
|
||||
m_c(any(X) #= any(Y), left_right_linsum_const(X, Y, Cs, Vs, S)) =>
|
||||
[g(scalar_product_(#=, Cs, Vs, S))],
|
||||
m_c(var(X) #= abs(var(Y)) + any(V0), X == Y) => [d(V0,V),p(x_eq_abs_plus_v(X,V))],
|
||||
@@ -2907,8 +2927,9 @@ match_goals([G|Gs], F) --> match_goal(G, F), match_goals(Gs, F).
|
||||
match_goal(r(X,Y), F) --> { G =.. [F,X,Y] }, [G].
|
||||
match_goal(d(X,Y), _) --> [parse_clpz(X, Y)].
|
||||
match_goal(g(Goal), _) --> [Goal].
|
||||
match_goal(p(Prop), _) -->
|
||||
{ term_variables(Prop, Vs) },
|
||||
match_goal(p(Prop0), _) -->
|
||||
{ term_variables(Prop0, Vs),
|
||||
morphing_propagator(Prop0, Prop, _) },
|
||||
[make_propagator(Prop, P),
|
||||
new_queue(Q0),
|
||||
phrase(init_propagator_(Vs, P), [Q0], [Q]),
|
||||
@@ -3296,7 +3317,7 @@ integer_kroot_leq(L, U, N, K, R) :-
|
||||
% When reasoning over integers, replace (=\=)/2 by (#\=)/2 to obtain more
|
||||
% general relations.
|
||||
|
||||
X #\= Y :- clpz_neq(X, Y), do_queue.
|
||||
X #\= Y :- clpz_neq(X, Y).
|
||||
|
||||
% X #\= Y + Z
|
||||
|
||||
@@ -3359,7 +3380,7 @@ X #< Y :- Y #> X.
|
||||
% X in inf.. -4\/1..9\/81..sup.
|
||||
% ```
|
||||
|
||||
#\ Q :- reify(Q, 0), do_queue.
|
||||
#\ Q :- reify(Q, 0).
|
||||
|
||||
%% #<==>(?P, ?Q)
|
||||
%
|
||||
@@ -3397,7 +3418,7 @@ X #< Y :- Y #> X.
|
||||
% Z = 2.
|
||||
% ```
|
||||
|
||||
L #<==> R :- reify(L, B), reify(R, B), do_queue.
|
||||
L #<==> R :- reify(L, B), reify(R, B).
|
||||
|
||||
%% #==>(?P, ?Q)
|
||||
%
|
||||
@@ -3432,7 +3453,7 @@ L #<== R :- R #==> L.
|
||||
%
|
||||
% P and Q hold.
|
||||
|
||||
L #/\ R :- reify(L, 1), reify(R, 1), do_queue.
|
||||
L #/\ R :- reify(L, 1), reify(R, 1).
|
||||
|
||||
conjunctive_neqs_var_drep(Eqs, Var, Drep) :-
|
||||
conjunctive_neqs_var(Eqs, Var),
|
||||
@@ -3520,16 +3541,17 @@ L #\ R :- (L #\/ R) #/\ #\ (L #/\ R).
|
||||
d(D) that states D is 1 iff all subexpressions are defined. a(V)
|
||||
means that V is an auxiliary variable that was introduced while
|
||||
parsing a compound expression. a(X,V) means V is auxiliary unless
|
||||
it is ==/2 X, and a(X,Y,V) means V is auxiliary unless it is ==/2 X
|
||||
or Y. l(L) means the literal L occurs in the described list.
|
||||
it is (==)/2 X, and a(X,Y,V) means V is auxiliary unless it is
|
||||
(==)/2 X or Y. l(L) means the literal L occurs in the described
|
||||
list, and ls(Ls) means the literals Ls occur in the described list.
|
||||
|
||||
When a constraint becomes entailed or subexpressions become
|
||||
undefined, created auxiliary constraints are killed, and the
|
||||
"clpz" attribute is removed from auxiliary variables.
|
||||
|
||||
For mod/2, div/2, rem/2 etc. we create a skeleton propagator and
|
||||
remember it as an auxiliary constraint. The pskeleton propagator
|
||||
can use the skeleton when the constraint is defined.
|
||||
For (//)/2, (mod)/2 and (rem)/2, we create a skeleton propagator
|
||||
and remember it as an auxiliary constraint. The pskeleton
|
||||
propagator can use the skeleton when the constraint is defined.
|
||||
|
||||
We cannot use a skeleton propagator for (/)/2, since (/)/2 can
|
||||
fail in cases such as 0 #==> X #= 1/2, where we expect success.
|
||||
@@ -3545,27 +3567,32 @@ parse_reified(E, R, D,
|
||||
m(A+B) => [d(D), p(pplus(A,B,R)), a(A,B,R)],
|
||||
m(A*B) => [d(D), p(ptimes(A,B,R)), a(A,B,R)],
|
||||
m(A-B) => [d(D), p(pplus(R,B,A)), a(A,B,R)],
|
||||
m(-A) => [d(D), p(ptimes(-1,A,R)), a(R)],
|
||||
m(-A) => [d(D), p(pplus(A,R,0)), a(R)],
|
||||
m(max(A,B)) => [d(D), p(pgeq(R, A)), p(pgeq(R, B)), p(pmax(A,B,R)), a(A,B,R)],
|
||||
m(min(A,B)) => [d(D), p(pgeq(A, R)), p(pgeq(B, R)), p(pmin(A,B,R)), a(A,B,R)],
|
||||
m(abs(A)) => [g(#R#>=0), d(D), p(pabs(A, R)), a(A,R)],
|
||||
m(A/B) => [p(preified_slash(A,B,D,R)), a(A,B,R)],
|
||||
m(abs(A)) => [d(D), g(#R#>=0), p(pabs(A, R)), a(A,R)],
|
||||
m(A^B) => [d(D1), p(preified_exp(A,B,D2,R)),
|
||||
p(reified_and(D1,[],D2,[],D)),a(D2),a(A,B,R)],
|
||||
m(A/B) => [d(D1), p(preified_slash(A,B,D2,R)),
|
||||
p(reified_and(D1,[],D2,[],D)),a(D2),a(A,B,R)],
|
||||
m(A div B) => [d(D1),
|
||||
g(phrase(parse_reified_clpz(((A-(A mod B)) // B), R, D2), Ps)),
|
||||
ls(Ps),
|
||||
p(reified_and(D1,[],D2,[],D)),a(D2),a(A,B,R)],
|
||||
m(A//B) => [skeleton(A,B,D,R,ptzdiv)],
|
||||
m(A div B) => [skeleton(A,B,D,R,pdiv)],
|
||||
m(A mod B) => [skeleton(A,B,D,R,pmod)],
|
||||
m(A rem B) => [skeleton(A,B,D,R,prem)],
|
||||
m(A^B) => [d(D), p(pexp(A,B,R)), a(A,B,R)],
|
||||
% bitwise operations
|
||||
m(\A) => [function(D,\,A,R)],
|
||||
m(msb(A)) => [g(#A#>0) ,function(D,msb,A,R)],
|
||||
m(lsb(A)) => [g(#A#>0), function(D,lsb,A,R)],
|
||||
m(popcount(A)) => [function(D,popcount,A,R)],
|
||||
m(sign(A)) => [function(D,sign,A,R)],
|
||||
m(popcount(A)) => [d(D), p(ppopcount(A, R)), a(A,R)],
|
||||
m(sign(A)) => [d(D), p(psign(A, R)), a(A,R)],
|
||||
m(A<<B) => [function(D,<<,A,B,R)],
|
||||
m(A>>B) => [function(D,>>,A,B,R)],
|
||||
m(A/\B) => [function(D,/\,A,B,R)],
|
||||
m(A\/B) => [function(D,\/,A,B,R)],
|
||||
m(xor(A, B)) => [function(D,xor,A,B,R)],
|
||||
m(xor(A, B)) => [skeleton(A,B,D,R,pxor)],
|
||||
g(true) => [g(domain_error(clpz_expression, E))]]
|
||||
).
|
||||
|
||||
@@ -3621,10 +3648,13 @@ reified_goal(d(D), Ds) -->
|
||||
; { domain_error(one_or_two_element_list, Ds) }
|
||||
).
|
||||
reified_goal(g(Goal), _) --> [{Goal}].
|
||||
reified_goal(p(Vs, Prop), _) -->
|
||||
reified_goal(p(Vs, Prop0), _) -->
|
||||
{ morphing_propagator(Prop0, Prop, Target) },
|
||||
[{make_propagator(Prop, P)}],
|
||||
target_propagator(Target),
|
||||
parse_init_dcg(Vs, P),
|
||||
[{trigger_once(P)}],
|
||||
[{variables_same_queue(Vs),
|
||||
trigger_once(P)}],
|
||||
[( { propagator_state(P, S), S == dead } -> [] ; [p(P)])].
|
||||
reified_goal(p(Prop), Ds) -->
|
||||
{ term_variables(Prop, Vs) },
|
||||
@@ -3634,7 +3664,9 @@ reified_goal(function(D,Op,A,B,R), Ds) -->
|
||||
reified_goal(function(D,Op,A,R), Ds) -->
|
||||
reified_goals([d(D),p(pfunction(Op,A,R)),a(A,R)], Ds).
|
||||
reified_goal(skeleton(A,B,D,R,F), Ds) -->
|
||||
{ Prop =.. [F,X,Y,Z] },
|
||||
{ Prop0 =.. [F,X,Y,Z],
|
||||
morphing_propagator(Prop0, Prop, Target) },
|
||||
target_propagator(Target),
|
||||
reified_goals([d(D1),l(p(P)),g(make_propagator(Prop, P)),
|
||||
p([A,B,D2,R], pskeleton(A,B,D2,[X,Y,Z]-P,R,F)),
|
||||
p(reified_and(D1,[],D2,[],D)),a(D2),a(A,B,R)], Ds).
|
||||
@@ -3642,12 +3674,20 @@ reified_goal(a(V), _) --> [a(V)].
|
||||
reified_goal(a(X,V), _) --> [a(X,V)].
|
||||
reified_goal(a(X,Y,V), _) --> [a(X,Y,V)].
|
||||
reified_goal(l(L), _) --> [[L]].
|
||||
reified_goal(ls(Ls), _) --> [Ls].
|
||||
|
||||
target_propagator(p(Prop)) --> [[p(Prop)]].
|
||||
target_propagator(none) --> [].
|
||||
|
||||
parse_init_dcg([], _) --> [].
|
||||
parse_init_dcg([V|Vs], P) --> [{init_propagator(V, P)}], parse_init_dcg(Vs, P).
|
||||
|
||||
%?- set_prolog_flag(answer_write_options, [portray(true)]),
|
||||
% clpz:parse_reified_clauses(Cs), maplist(portray_clause, Cs).
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
?- use_module(library(lists)),
|
||||
use_module(library(format)),
|
||||
clpz:parse_reified_clauses(Cs),
|
||||
maplist(portray_clause, Cs).
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
reify(E, B) :- reify(E, B, _).
|
||||
|
||||
@@ -3692,7 +3732,7 @@ reify_(tuples_in(Tuples, Relation), B) -->
|
||||
#B #<==> And },
|
||||
propagator_init_trigger([B], tuples_not_in(Tuples, Relation, B)),
|
||||
kill_reified_tuples(Bs, Ps, Bs),
|
||||
list(Ps),
|
||||
seq(Ps),
|
||||
as([B|Bs]).
|
||||
reify_(finite_domain(V), B) -->
|
||||
propagator_init_trigger(reified_fd(V,B)),
|
||||
@@ -3724,20 +3764,17 @@ arithmetic(L, R, B, Functor) -->
|
||||
{ phrase((parse_reified_clpz(L, LR, LD),
|
||||
parse_reified_clpz(R, RR, RD)), Ps),
|
||||
Prop =.. [Functor,LD,LR,RD,RR,Ps,B] },
|
||||
list(Ps),
|
||||
seq(Ps),
|
||||
propagator_init_trigger([LD,LR,RD,RR,B], Prop),
|
||||
a(B).
|
||||
|
||||
boolean(L, R, B, Functor) -->
|
||||
{ reify(L, LR, Ps1), reify(R, RR, Ps2),
|
||||
Prop =.. [Functor,LR,Ps1,RR,Ps2,B] },
|
||||
list(Ps1), list(Ps2),
|
||||
seq(Ps1), seq(Ps2),
|
||||
propagator_init_trigger([LR,RR,B], Prop),
|
||||
a(LR, RR, B).
|
||||
|
||||
list([]) --> [].
|
||||
list([L|Ls]) --> [L], list(Ls).
|
||||
|
||||
a(X,Y,B) -->
|
||||
( nonvar(X) -> a(Y, B)
|
||||
; nonvar(Y) -> a(X, B)
|
||||
@@ -3872,7 +3909,6 @@ domain(V, Dom) :-
|
||||
domains_intersection(Dom, Dom0, Dom1),
|
||||
%format("intersected\n: ~w\n ~w\n==> ~w\n\n", [Dom,Dom0,Dom1]),
|
||||
fd_put(V, Dom1, VPs),
|
||||
do_queue,
|
||||
reinforce(V)
|
||||
; domain_contains(Dom, V)
|
||||
).
|
||||
@@ -4187,7 +4223,6 @@ activate_propagator(propagator(P,State)) -->
|
||||
|
||||
enable_queue :- true. % NOP
|
||||
disable_queue :- true. % NOP
|
||||
do_queue. % NOP
|
||||
|
||||
%do_queue --> print_queue, { false }.
|
||||
do_queue -->
|
||||
@@ -4769,7 +4804,7 @@ run_propagator(scalar_product_eq(Cs0,Vs0,P0), MState) -->
|
||||
) }.
|
||||
|
||||
% X + Y = Z
|
||||
run_propagator(pplus(X,Y,Z), MState) -->
|
||||
run_propagator(pplus(X,Y,Z,Morph), MState) -->
|
||||
( nonvar(X) ->
|
||||
( X =:= 0 -> kill(MState), Y = Z
|
||||
; Y == Z -> kill(MState), X =:= 0
|
||||
@@ -4788,7 +4823,7 @@ run_propagator(pplus(X,Y,Z), MState) -->
|
||||
; []
|
||||
)
|
||||
)
|
||||
; nonvar(Y) -> run_propagator(pplus(Y,X,Z), MState)
|
||||
; nonvar(Y) -> run_propagator(pplus(Y,X,Z,Morph), MState)
|
||||
; nonvar(Z) ->
|
||||
( X == Y -> kill(MState), { even(Z), X is Z // 2 }
|
||||
; { fd_get(X, XD, _),
|
||||
@@ -4805,7 +4840,8 @@ run_propagator(pplus(X,Y,Z), MState) -->
|
||||
; []
|
||||
)
|
||||
)
|
||||
; ( X == Y -> { kill(MState), 2*X #= Z }
|
||||
; ( X == Y ->
|
||||
morph_into_propagator(MState, [X,Z], ptimes(2,X,Z), Morph)
|
||||
; X == Z -> kill(MState), Y = 0
|
||||
; Y == Z -> kill(MState), X = 0
|
||||
; { fd_get(X, XD, XL, XU, XPs),
|
||||
@@ -4831,7 +4867,7 @@ run_propagator(pplus(X,Y,Z), MState) -->
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
run_propagator(ptimes(X,Y,Z), MState) -->
|
||||
run_propagator(ptimes(X,Y,Z,Morph), MState) -->
|
||||
( nonvar(X) ->
|
||||
( nonvar(Y) -> kill(MState), Z is X * Y
|
||||
; X =:= 0 -> kill(MState), Z = 0
|
||||
@@ -4851,7 +4887,7 @@ run_propagator(ptimes(X,Y,Z), MState) -->
|
||||
)
|
||||
)
|
||||
)
|
||||
; nonvar(Y) -> run_propagator(ptimes(Y,X,Z), MState)
|
||||
; nonvar(Y) -> run_propagator(ptimes(Y,X,Z,Morph), MState)
|
||||
; nonvar(Z) ->
|
||||
( X == Y ->
|
||||
kill(MState),
|
||||
@@ -4877,7 +4913,8 @@ run_propagator(ptimes(X,Y,Z), MState) -->
|
||||
; neq_num(X, 0), neq_num(Y, 0)
|
||||
)
|
||||
)
|
||||
; ( X == Y -> kill(MState), { X^2 #= Z }
|
||||
; ( X == Y ->
|
||||
morph_into_propagator(MState, [X,Z], pexp(X,2,Z), Morph)
|
||||
; { fd_get(X, XD, XL, XU, XPs),
|
||||
fd_get(Y, _, YL, YU, _),
|
||||
fd_get(Z, ZD, ZL, ZU, _) },
|
||||
@@ -4908,17 +4945,8 @@ run_propagator(ptimes(X,Y,Z), MState) -->
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% X div Y = Z
|
||||
run_propagator(pdiv(X,Y,Z), MState) -->
|
||||
{ kill(MState), Z #= (X-(X mod Y)) // Y }.
|
||||
|
||||
% X rdiv Y = Z
|
||||
run_propagator(prdiv(X,Y,Z), MState) -->
|
||||
{ kill(MState), Z*Y #= X }.
|
||||
|
||||
|
||||
% X // Y = Z (round towards zero)
|
||||
run_propagator(ptzdiv(X,Y,Z), MState) -->
|
||||
run_propagator(ptzdiv(X,Y,Z,Morph), MState) -->
|
||||
( nonvar(X) ->
|
||||
( nonvar(Y) -> kill(MState), Y =\= 0, Z is X // Y
|
||||
; { fd_get(Y, YD, YL, YU, YPs) },
|
||||
@@ -4962,7 +4990,8 @@ run_propagator(ptzdiv(X,Y,Z), MState) -->
|
||||
; nonvar(Y) ->
|
||||
Y =\= 0,
|
||||
( Y =:= 1 -> kill(MState), X = Z
|
||||
; Y =:= -1 -> kill(MState), { Z #= -X }
|
||||
; Y =:= -1 ->
|
||||
morph_into_propagator(MState, [X,Z], pplus(X,Z,0), Morph)
|
||||
; { fd_get(X, XD, XL, XU, XPs) },
|
||||
( nonvar(Z) ->
|
||||
kill(MState),
|
||||
@@ -5412,9 +5441,11 @@ run_propagator(pmin(X,Y,Z), MState) -->
|
||||
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%% % Z = X ^ Y
|
||||
|
||||
run_propagator(pexp(X,Y,Z), MState) -->
|
||||
run_propagator(pexp(X,Y,Z,Morph), MState) -->
|
||||
( X == 1 -> kill(MState), Z = 1
|
||||
; X == 0 -> kill(MState), queue_goal((Z in 0..1, Y #>= 0, Z #<==> Y #= 0))
|
||||
; X == 0 ->
|
||||
queue_goal((Z in 0..1, Y #>= 0)),
|
||||
morph_into_propagator(MState, [Y,Z], reified_eq(1,Y,1,0,[],Z), Morph)
|
||||
; Y == 0 -> kill(MState), Z = 1
|
||||
; Y == 1 -> kill(MState), Z = X
|
||||
; nonvar(X) ->
|
||||
@@ -5474,7 +5505,9 @@ run_propagator(pexp(X,Y,Z), MState) -->
|
||||
)
|
||||
; nonvar(Y), Y > 0 ->
|
||||
( { even(Y) } ->
|
||||
{ geq(Z, 0) }
|
||||
{ fd_get(Z, ZD0, ZPs0),
|
||||
domain_remove_smaller_than(ZD0, 0, ZDG0) },
|
||||
fd_put(Z, ZDG0, ZPs0)
|
||||
; true
|
||||
),
|
||||
( { fd_get(X, XD, XL, XU, _), fd_get(Z, ZD, ZL, ZU, ZPs) } ->
|
||||
@@ -5907,6 +5940,35 @@ run_propagator(preified_slash(X, Y, D, R), MState) -->
|
||||
; []
|
||||
).
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
run_propagator(preified_exp(X, Y, D, R), MState) -->
|
||||
( X == 1 ->
|
||||
kill(MState),
|
||||
D = 1,
|
||||
R = 1
|
||||
; Y == 0 ->
|
||||
kill(MState),
|
||||
D = 1,
|
||||
R = 1
|
||||
; Y == 1 ->
|
||||
kill(MState),
|
||||
D = 1,
|
||||
R = X
|
||||
; nonvar(X),
|
||||
nonvar(Y) ->
|
||||
kill(MState),
|
||||
( ( abs(X) =:= 1 ; Y >= 0 ) ->
|
||||
D = 1,
|
||||
R is X^Y
|
||||
; D = 0
|
||||
)
|
||||
; D == 1 ->
|
||||
kill(MState),
|
||||
queue_goal(X^Y #= R)
|
||||
; []
|
||||
).
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
@@ -6055,7 +6117,7 @@ domain_to_list(Domain, List) :- phrase(domain_to_list(Domain), List).
|
||||
domain_to_list(split(_, Left, Right)) -->
|
||||
domain_to_list(Left), domain_to_list(Right).
|
||||
domain_to_list(empty) --> [].
|
||||
domain_to_list(from_to(n(F),n(T))) --> { numlist(F, T, Ns) }, list(Ns).
|
||||
domain_to_list(from_to(n(F),n(T))) --> { numlist(F, T, Ns) }, seq(Ns).
|
||||
|
||||
difference_arcs([], []) --> [].
|
||||
difference_arcs([V|Vs], FL0) -->
|
||||
@@ -6415,8 +6477,7 @@ num_infinite(Var, N0, N) :-
|
||||
weak_arc_all_distinct(Ls) :-
|
||||
must_be(list, Ls),
|
||||
Orig = original_goal(_, weak_arc_all_distinct(Ls)),
|
||||
all_distinct(Ls, [], Orig),
|
||||
do_queue.
|
||||
all_distinct(Ls, [], Orig).
|
||||
|
||||
all_distinct([], _, _).
|
||||
all_distinct([X|Right], Left, Orig) :-
|
||||
@@ -6729,8 +6790,10 @@ gcc_pairs([Key-Num0|KNs], Vs, [Key-Num|Rest]) :-
|
||||
|
||||
gcc_global(Vs, KNs) :-
|
||||
gcc_check(KNs),
|
||||
% reach fix-point: all elements of clpz_gcc_vs must be variables
|
||||
do_queue,
|
||||
% previously: call do_queue/0 (now a NOP) here to reach a
|
||||
% fix-point: all elements of clpz_gcc_vs must be variables. We
|
||||
% must ensure this holds if gcc_check/1 is later rewritten to
|
||||
% actually disable the queue.
|
||||
with_local_attributes(Vs,
|
||||
(gcc_arcs(KNs, S, Vals),
|
||||
variables_with_num_occurrences(Vs, VNs),
|
||||
@@ -7753,7 +7816,7 @@ attributes_goals([propagator(P, State)|As]) -->
|
||||
; maplist(unwrap_with(=), Gs, Gs1)
|
||||
),
|
||||
maplist(with_clpz, Gs1, Gs2) },
|
||||
list(Gs2)
|
||||
seq(Gs2)
|
||||
; [P] % possibly user-defined constraint
|
||||
),
|
||||
attributes_goals(As).
|
||||
@@ -7771,17 +7834,15 @@ bare_integer(V0, V) :- ( integer(V0) -> V = V0 ; V = #V0 ).
|
||||
|
||||
attribute_goal_(presidual(Goal)) --> [Goal].
|
||||
attribute_goal_(pgeq(A,B)) --> [#A #>= #B].
|
||||
attribute_goal_(pplus(X,Y,Z)) --> [#X + #Y #= #Z].
|
||||
attribute_goal_(pplus(X,Y,Z,_)) --> [#X + #Y #= #Z].
|
||||
attribute_goal_(pneq(A,B)) --> [#A #\= #B].
|
||||
attribute_goal_(ptimes(X,Y,Z)) --> [#X * #Y #= #Z].
|
||||
attribute_goal_(ptimes(X,Y,Z,_)) --> [#X * #Y #= #Z].
|
||||
attribute_goal_(absdiff_neq(X,Y,C)) --> [abs(#X - #Y) #\= C].
|
||||
attribute_goal_(x_eq_abs_plus_v(X,V)) --> [#X #= abs(#X) + #V].
|
||||
attribute_goal_(x_neq_y_plus_z(X,Y,Z)) --> [#X #\= #Y + #Z].
|
||||
attribute_goal_(x_leq_y_plus_c(X,Y,C)) --> [#X #=< #Y + C].
|
||||
attribute_goal_(ptzdiv(X,Y,Z)) --> [#X // #Y #= #Z].
|
||||
attribute_goal_(pdiv(X,Y,Z)) --> [#X div #Y #= #Z].
|
||||
attribute_goal_(prdiv(X,Y,Z)) --> [#X / #Y #= #Z].
|
||||
attribute_goal_(pexp(X,Y,Z)) --> [#X ^ #Y #= #Z].
|
||||
attribute_goal_(ptzdiv(X,Y,Z,_)) --> [#X // #Y #= #Z].
|
||||
attribute_goal_(pexp(X,Y,Z,_)) --> [#X ^ #Y #= #Z].
|
||||
attribute_goal_(psign(X,Y)) --> [#Y #= sign(#X)].
|
||||
attribute_goal_(pabs(X,Y)) --> [#Y #= abs(#X)].
|
||||
attribute_goal_(pmod(X,M,K)) --> [#X mod #M #= #K].
|
||||
@@ -7841,6 +7902,7 @@ attribute_goal_(reified_and(X,_,Y,_,B)) --> [#X #/\ #Y #<==> #B].
|
||||
attribute_goal_(reified_or(X, _, Y, _, B)) --> [#X #\/ #Y #<==> #B].
|
||||
attribute_goal_(reified_not(X, Y)) --> [#\ #X #<==> #Y].
|
||||
attribute_goal_(preified_slash(X, Y, _, R)) --> [#X/ #Y #= R].
|
||||
attribute_goal_(preified_exp(X, Y, _, R)) --> [#X^ #Y #= R].
|
||||
attribute_goal_(pimpl(X, Y, _)) --> [#X #==> #Y].
|
||||
attribute_goal_(pfunction(Op, A, B, R)) -->
|
||||
{ Expr =.. [Op,#A,#B] },
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use dashu::base::Abs;
|
||||
use dashu::base::Gcd;
|
||||
use dashu::base::{Abs, Gcd, UnsignedAbs};
|
||||
use dashu::integer::IBig;
|
||||
use dashu::integer::fast_div::ConstDivisor;
|
||||
use divrem::*;
|
||||
use num_order::NumOrd;
|
||||
|
||||
@@ -854,7 +855,9 @@ pub(crate) fn modulus(x: Number, y: Number, arena: &mut Arena) -> Result<Number,
|
||||
} else if n1 < &Integer::ZERO && n2 > &Integer::ZERO {
|
||||
((n1 + Integer::ONE) / n2) - Integer::ONE
|
||||
} else {
|
||||
n1 / n2
|
||||
let ring = ConstDivisor::new(n2.unsigned_abs());
|
||||
let n1 = n1.clone();
|
||||
IBig::from(ring.reduce(n1).residue())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1131,27 +1131,29 @@ impl MachineState {
|
||||
|
||||
#[inline]
|
||||
pub fn is_cyclic_term(&mut self, value: HeapCellValue) -> bool {
|
||||
if value.is_constant() {
|
||||
let value = self.store(self.deref(value));
|
||||
|
||||
if value.is_constant() || value.is_stack_var() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut iter = stackful_preorder_iter::<NonListElider>
|
||||
(&mut self.heap, &mut self.stack, value);
|
||||
let h = self.heap.len();
|
||||
self.heap.push(value);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
if value.get_forwarding_bit() {
|
||||
let value = unmark_cell_bits!(heap_bound_store(
|
||||
iter.heap,
|
||||
heap_bound_deref(iter.heap, value),
|
||||
));
|
||||
let found_cycle = {
|
||||
let mut iter = cycle_detecting_stackless_preorder_iter(&mut self.heap, h);
|
||||
|
||||
if value.is_compound(iter.heap) {
|
||||
return true;
|
||||
while let Some(_) = iter.next() {
|
||||
if iter.found_cycle() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
iter.found_cycle()
|
||||
};
|
||||
|
||||
self.heap.pop();
|
||||
found_cycle
|
||||
}
|
||||
|
||||
// arg(+N, +Term, ?Arg)
|
||||
@@ -1621,56 +1623,12 @@ impl MachineState {
|
||||
|
||||
// returns true on failure.
|
||||
pub fn ground_test(&mut self) -> bool {
|
||||
use fxhash::FxBuildHasher;
|
||||
let iter = eager_stackful_preorder_iter(&mut self.heap, self.registers[1]);
|
||||
|
||||
if self.registers[1].is_constant() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let value = self.store(self.deref(self.registers[1]));
|
||||
|
||||
if value.is_stack_var() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut visited = IndexSet::with_hasher(FxBuildHasher::default());
|
||||
let mut iter = stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, value);
|
||||
let mut stack_len = 0;
|
||||
|
||||
let is_var = |heap: &Heap, value: HeapCellValue| -> bool {
|
||||
let value = unmark_cell_bits!(value);
|
||||
|
||||
if value.is_var() {
|
||||
let value = heap_bound_store(heap, heap_bound_deref(heap, value));
|
||||
|
||||
if value.is_var() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
};
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
if is_var(iter.heap, value) {
|
||||
for term in iter {
|
||||
if term.is_var() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if value.is_ref() {
|
||||
if visited.contains(&value) {
|
||||
while iter.stack_len() > stack_len {
|
||||
if let Some(value) = iter.pop_stack() {
|
||||
if is_var(iter.heap, value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
visited.insert(value);
|
||||
}
|
||||
}
|
||||
|
||||
stack_len = iter.stack_len();
|
||||
}
|
||||
|
||||
false
|
||||
|
||||
@@ -584,20 +584,11 @@ impl MachineState {
|
||||
seen_set: &mut IndexSet<HeapCellValue, S>,
|
||||
value: HeapCellValue,
|
||||
) {
|
||||
let mut iter = stackful_preorder_iter::<NonListElider>(&mut self.heap, &mut self.stack, value);
|
||||
let iter = eager_stackful_preorder_iter(&mut self.heap, value);
|
||||
|
||||
while let Some(value) = iter.next() {
|
||||
let value = unmark_cell_bits!(value);
|
||||
|
||||
if value.is_var() {
|
||||
let value = unmark_cell_bits!(heap_bound_store(
|
||||
iter.heap,
|
||||
heap_bound_deref(iter.heap, value)
|
||||
));
|
||||
|
||||
if value.is_var() {
|
||||
seen_set.insert(value);
|
||||
}
|
||||
for term in iter {
|
||||
if term.is_var() {
|
||||
seen_set.insert(term);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6891,6 +6882,17 @@ impl Machine {
|
||||
return;
|
||||
}
|
||||
|
||||
let stored_v = if stored_v.is_stack_var() {
|
||||
let h = self.machine_st.heap.len();
|
||||
|
||||
self.machine_st.heap.push(heap_loc_as_cell!(h));
|
||||
self.machine_st.bind(Ref::heap_cell(h), stored_v);
|
||||
|
||||
heap_loc_as_cell!(h)
|
||||
} else {
|
||||
stored_v
|
||||
};
|
||||
|
||||
let mut seen_set = IndexSet::with_hasher(FxBuildHasher::default());
|
||||
|
||||
self.machine_st.variable_set(&mut seen_set, stored_v);
|
||||
|
||||
@@ -691,6 +691,9 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
|
||||
(HeapCellValueTag::Cons, ptr_1) => {
|
||||
Self::unify_constant(self, ptr_1, d2);
|
||||
}
|
||||
(HeapCellValueTag::CutPoint, n1) => {
|
||||
Self::unify_fixnum(self, n1, d2);
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
233
src/tests/acyclic_term.pl
Normal file
233
src/tests/acyclic_term.pl
Normal file
@@ -0,0 +1,233 @@
|
||||
:- use_module(library(format)).
|
||||
|
||||
term1(A) :-
|
||||
B=[C|D],
|
||||
A=[D|C],
|
||||
B=[C|B].
|
||||
|
||||
term2(A) :-
|
||||
A=[B|C],
|
||||
D=[C|C],
|
||||
D=[B|D].
|
||||
|
||||
term3(A) :-
|
||||
A=[_B|C],
|
||||
D=[C|_E],
|
||||
A=[C|D].
|
||||
|
||||
term4(A) :-
|
||||
A=[B|C],
|
||||
C=[C|B].
|
||||
|
||||
term5(A) :-
|
||||
A=[_B|C],
|
||||
D=[_E|C],
|
||||
A=[C|D].
|
||||
|
||||
term6(A) :-
|
||||
A=[B|B],
|
||||
B=[C|C].
|
||||
|
||||
test("acyclic_term_1", (
|
||||
L = [_Y,[M,B],B|M], acyclic_term(L)
|
||||
)).
|
||||
|
||||
test("acyclic_term_2", (
|
||||
L = [_Y,[M,_B,L]|M], \+ acyclic_term(L)
|
||||
)).
|
||||
|
||||
test("acyclic_term_3", (
|
||||
L = [_Y,[M,B,L,B]|M], \+ acyclic_term(L)
|
||||
)).
|
||||
|
||||
test("acyclic_term_4", (
|
||||
L = [_Y,[L,_A,_B]|_M], \+ acyclic_term(L)
|
||||
)).
|
||||
|
||||
test("acyclic_term_5", (
|
||||
L = [_Y,[M,_A,_B]|M], acyclic_term(L)
|
||||
)).
|
||||
|
||||
test("acyclic_term_6", (
|
||||
L = [_Y,[L,_A,_B]|_M], \+ acyclic_term(L)
|
||||
)).
|
||||
|
||||
test("acyclic_term_7", (
|
||||
L = [A], A = [T], T = [_|X], X = Y, Y = L, \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_8", (
|
||||
L = [A], A = [T], T = [_|X], X = Y, Y = L, \+ acyclic_term(L)
|
||||
)).
|
||||
|
||||
test("acyclic_term_9", (
|
||||
L = [A], A = [T], T = [_|X], X = Y, Y = L, \+ acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term_10", (
|
||||
L = [A], A = [T], T = [_|X], X = Y, Y = L, \+ acyclic_term(Y)
|
||||
)).
|
||||
|
||||
test("acyclic_term_11", (
|
||||
L = [A], A = [T], T = [_|X], X = Y, Y = L, \+ acyclic_term(X)
|
||||
)).
|
||||
|
||||
test("acyclic_term_12", (
|
||||
A = [1|2], X = A, T=a(X, A), acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_13", (
|
||||
A = [A|2], X = A, T=a(X, A), \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_13", (
|
||||
A = [T|2], X = A, T=a(X, A), \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_14", (
|
||||
T = [_A|T], \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_15", (
|
||||
T = [T|_L], \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_16", (
|
||||
A = [1|A], X = A, T=a(X, A), \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_17", (
|
||||
T = [_A| [[[[L|T]|[]]]]], acyclic_term(L)
|
||||
)).
|
||||
|
||||
test("acyclic_term_18", (
|
||||
T = [A| [[[[_L|T]|[]]]]], acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term_19", (
|
||||
T = [_A| [[[[_L|T]|[]]]]], \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_20", (
|
||||
A = [_C|_B], X = A, T=a(t(X,A), A), acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_21", (
|
||||
X = [a | Rest], Rest = [_Y | Rest], \+ acyclic_term(X)
|
||||
)).
|
||||
|
||||
test("acyclic_term_22", (
|
||||
_X = [a | Rest], Rest = [_Y | Rest], \+ acyclic_term(Rest)
|
||||
)).
|
||||
|
||||
test("acyclic_term_23", (
|
||||
T = [[_A, T]], G = [1|T], \+ acyclic_term(G)
|
||||
)).
|
||||
|
||||
test("acyclic_term_24", (
|
||||
T = [[_A, T]], \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_25", (
|
||||
T = [[_, _], T], \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_26", (
|
||||
T = [[T, _], 1], \+ acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_27", (
|
||||
T = str(A,A), acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_28", (
|
||||
T = str(A,A,A), acyclic_term(T)
|
||||
)).
|
||||
|
||||
test("acyclic_term_29", (
|
||||
A = s(B, d(Y)), Y = B, acyclic_term(A),
|
||||
acyclic_term(B), acyclic_term(Y)
|
||||
)).
|
||||
|
||||
test("acyclic_term_30", (
|
||||
A=str(B,B,B), C=str(A,_D,B), acyclic_term(C),
|
||||
acyclic_term(A), acyclic_term(B)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2111_1", (
|
||||
term1(A), \+ acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2111_2", (
|
||||
term2(A), \+ acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2111_3", (
|
||||
term3(A), \+ acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2111_4", (
|
||||
term4(A), \+ acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2111_5", (
|
||||
term5(A), \+ acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2111_6", (
|
||||
term6(A), acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2113", (
|
||||
A=[]*B,B=[]*B, \+ acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2114", (
|
||||
A=B*B, acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2116", (
|
||||
A=B*B,B=[]*[], acyclic_term(A)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2117", (
|
||||
A=[]*A,B=[]*A, \+ acyclic_term(B)
|
||||
)).
|
||||
|
||||
test("acyclic_term#2121", (
|
||||
A=B*B, C=A*B, acyclic_term(C),
|
||||
acyclic_term(A), acyclic_term(B)
|
||||
)).
|
||||
|
||||
main :-
|
||||
findall(test(Name, Goal), test(Name, Goal), Tests),
|
||||
run_tests(Tests, Failed),
|
||||
show_failed(Failed),
|
||||
halt.
|
||||
|
||||
main_quiet :-
|
||||
findall(test(Name, Goal), test(Name, Goal), Tests),
|
||||
run_tests_quiet(Tests, Failed),
|
||||
( Failed = [] ->
|
||||
format("All tests passed", [])
|
||||
; format("Some tests failed", [])
|
||||
),
|
||||
halt.
|
||||
|
||||
run_tests([], []).
|
||||
run_tests([test(Name, Goal)|Tests], Failed) :-
|
||||
format("Running test \"~s\"~n", [Name]),
|
||||
( call(Goal) ->
|
||||
Failed = Failed1
|
||||
; format("Failed test \"~s\"~n", [Name]),
|
||||
Failed = [Name|Failed1]
|
||||
),
|
||||
run_tests(Tests, Failed1).
|
||||
|
||||
run_tests_quiet([], []).
|
||||
run_tests_quiet([test(Name, Goal)|Tests], Failed) :-
|
||||
( call(Goal) ->
|
||||
Failed = Failed1
|
||||
; Failed = [Name|Failed1]
|
||||
),
|
||||
run_tests_quiet(Tests, Failed1).
|
||||
83
src/tests/ground.pl
Normal file
83
src/tests/ground.pl
Normal file
@@ -0,0 +1,83 @@
|
||||
/**/
|
||||
|
||||
:- use_module(library(format)).
|
||||
:- use_module(library(dcgs)).
|
||||
:- use_module(library(lists)).
|
||||
:- use_module(library(debug)).
|
||||
:- use_module(library(atts)).
|
||||
|
||||
:- attribute a/1.
|
||||
|
||||
a(Var) :- put_atts(Var, +a(hello)).
|
||||
|
||||
test("ground#239", (
|
||||
% double negate to avoid residual goal being printed
|
||||
\+ \+ (a(X), var(X), \+ ground(X))
|
||||
)).
|
||||
|
||||
test("ground#1411",(
|
||||
G_0 = ( A=s(A) ), G_0,
|
||||
ground(A), ground(G_0)
|
||||
)).
|
||||
|
||||
test("ground#2065",(
|
||||
A = [B|_C], B = [A], \+ ground(B), \+ground([B])
|
||||
)).
|
||||
|
||||
test("ground#2073",(
|
||||
\+ ground(_-1+_-1),
|
||||
\+ ground(1-1-_)
|
||||
)).
|
||||
|
||||
test("ground#2075",(
|
||||
G_0 = (_,_,ground(_)),
|
||||
G_0 = (D=[D|_],_=D*[],ground(D)),
|
||||
\+ G_0,
|
||||
_=_B*_,_D=_B*_A,_B=_B*_D,\+ ground(_B),
|
||||
A=[A|B],B=A*B,ground(A)
|
||||
)).
|
||||
|
||||
main :-
|
||||
findall(test(Name, Goal), test(Name, Goal), Tests),
|
||||
run_tests(Tests, Failed),
|
||||
show_failed(Failed),
|
||||
halt.
|
||||
|
||||
main_quiet :-
|
||||
findall(test(Name, Goal), test(Name, Goal), Tests),
|
||||
run_tests_quiet(Tests, Failed),
|
||||
( Failed = [] ->
|
||||
format("All tests passed", [])
|
||||
; format("Some tests failed", [])
|
||||
),
|
||||
halt.
|
||||
|
||||
run_tests([], []).
|
||||
run_tests([test(Name, Goal)|Tests], Failed) :-
|
||||
format("Running test \"~s\"~n", [Name]),
|
||||
( call(Goal) ->
|
||||
Failed = Failed1
|
||||
; format("Failed test \"~s\"~n", [Name]),
|
||||
Failed = [Name|Failed1]
|
||||
),
|
||||
run_tests(Tests, Failed1).
|
||||
|
||||
run_tests_quiet([], []).
|
||||
run_tests_quiet([test(Name, Goal)|Tests], Failed) :-
|
||||
( call(Goal) ->
|
||||
Failed = Failed1
|
||||
; Failed = [Name|Failed1]
|
||||
),
|
||||
run_tests_quiet(Tests, Failed1).
|
||||
|
||||
portray_failed_([]) --> [].
|
||||
portray_failed_([F|Fs]) -->
|
||||
"\"", F, "\"", "\n", portray_failed_(Fs).
|
||||
|
||||
portray_failed([]) --> [].
|
||||
portray_failed([F|Fs]) -->
|
||||
"\n", "Failed tests:", "\n", portray_failed_([F|Fs]).
|
||||
|
||||
show_failed(Failed) :-
|
||||
phrase(portray_failed(Failed), F),
|
||||
format("~s", [F]).
|
||||
117
src/tests/term_variables.pl
Normal file
117
src/tests/term_variables.pl
Normal file
@@ -0,0 +1,117 @@
|
||||
/**/
|
||||
|
||||
:- use_module(library(format)).
|
||||
:- use_module(library(dcgs)).
|
||||
:- use_module(library(lists)).
|
||||
:- use_module(library(debug)).
|
||||
|
||||
test("term_variables#1400", (
|
||||
term_variables(A+B*C/B-D, Vars),
|
||||
term_variables(t(A,B,C,D), Vars),
|
||||
Vars = [A,B,C,D]
|
||||
)).
|
||||
|
||||
test("term_variables#1405", (
|
||||
\+ (B=[C|D],C=[_|D],C=[B|B], term_variables(B,_), false)
|
||||
)).
|
||||
|
||||
test("term_variables#1409", (
|
||||
G_0 = (A=[B|B],A=[C|C]), G_0, term_variables(G_0, Vars), Vars = [B]
|
||||
)).
|
||||
|
||||
test("term_variables#1410", (
|
||||
\+ \+ (G_0 = ( A=s(A) ), G_0, term_variables(G_0, Vars), Vars = []),
|
||||
E_0 = (_=[B|B]), G_0 = (E_0,\_=B), G_0, term_variables(G_0, Vars)
|
||||
)).
|
||||
|
||||
test("term_variables#1412", (
|
||||
G_0 = =([A|B],[A|B]), G_0, term_variables(G_0, Vars),
|
||||
Vars = [A,B]
|
||||
)).
|
||||
|
||||
test("term_variables#1414", (
|
||||
\+ (\B=A,C=[A|D],B=[a,b|E],C=[D|E], term_variables(\E,_), false)
|
||||
)).
|
||||
|
||||
test("term_variables#2063", (
|
||||
A=[B|C], B=[A], term_variables([B], Vars),
|
||||
Vars = [C]
|
||||
)).
|
||||
|
||||
test("term_variables#2097", (
|
||||
termt(T), term_variables(T,Vs),
|
||||
T = [[[A|B]|A]|A], Vs == [A,B]
|
||||
)).
|
||||
|
||||
test("term_variables#2100", (
|
||||
termt2(T), term_variables(T,Vs),
|
||||
T = [[T|A]|B], Vs == [A,B]
|
||||
)).
|
||||
|
||||
test("term_variables#2101", (
|
||||
termt3(T), term_variables(T,Vs),
|
||||
T = [[[[A|B]|A]|A]|A], Vs == [A, B]
|
||||
)).
|
||||
|
||||
termt(T) :-
|
||||
T = [T1|T2],
|
||||
T1 = [T3|A],
|
||||
T3 = [A|_],
|
||||
T2 = A.
|
||||
|
||||
termt2(T) :-
|
||||
T = [T1|_B],
|
||||
T1 = [T|_A].
|
||||
|
||||
termt3(T) :-
|
||||
T = [T1|T0],
|
||||
T1 = [T2|T3],
|
||||
T2 = [T4|A],
|
||||
T4 = [A|_],
|
||||
T3 = A,
|
||||
T0 = A.
|
||||
|
||||
main :-
|
||||
findall(test(Name, Goal), test(Name, Goal), Tests),
|
||||
run_tests(Tests, Failed),
|
||||
show_failed(Failed),
|
||||
halt.
|
||||
|
||||
main_quiet :-
|
||||
findall(test(Name, Goal), test(Name, Goal), Tests),
|
||||
run_tests_quiet(Tests, Failed),
|
||||
( Failed = [] ->
|
||||
format("All tests passed", [])
|
||||
; format("Some tests failed", [])
|
||||
),
|
||||
halt.
|
||||
|
||||
run_tests([], []).
|
||||
run_tests([test(Name, Goal)|Tests], Failed) :-
|
||||
format("Running test \"~s\"~n", [Name]),
|
||||
( call(Goal) ->
|
||||
Failed = Failed1
|
||||
; format("Failed test \"~s\"~n", [Name]),
|
||||
Failed = [Name|Failed1]
|
||||
),
|
||||
run_tests(Tests, Failed1).
|
||||
|
||||
run_tests_quiet([], []).
|
||||
run_tests_quiet([test(Name, Goal)|Tests], Failed) :-
|
||||
( call(Goal) ->
|
||||
Failed = Failed1
|
||||
; Failed = [Name|Failed1]
|
||||
),
|
||||
run_tests_quiet(Tests, Failed1).
|
||||
|
||||
portray_failed_([]) --> [].
|
||||
portray_failed_([F|Fs]) -->
|
||||
"\"", F, "\"", "\n", portray_failed_(Fs).
|
||||
|
||||
portray_failed([]) --> [].
|
||||
portray_failed([F|Fs]) -->
|
||||
"\n", "Failed tests:", "\n", portray_failed_([F|Fs]).
|
||||
|
||||
show_failed(Failed) :-
|
||||
phrase(portray_failed(Failed), F),
|
||||
format("~s", [F]).
|
||||
@@ -430,6 +430,7 @@ impl HeapCellValue {
|
||||
HeapCellValueTag::Cons
|
||||
| HeapCellValueTag::F64
|
||||
| HeapCellValueTag::Fixnum
|
||||
| HeapCellValueTag::CutPoint
|
||||
| HeapCellValueTag::Char
|
||||
| HeapCellValueTag::CStr => true,
|
||||
HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() == 0,
|
||||
|
||||
@@ -84,3 +84,30 @@ fn dif_tests() {
|
||||
"All tests passed",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ground_tests() {
|
||||
run_top_level_test_with_args(
|
||||
&["src/tests/ground.pl", "-f", "-g", "main_quiet"],
|
||||
"",
|
||||
"All tests passed",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn term_variables_tests() {
|
||||
run_top_level_test_with_args(
|
||||
&["src/tests/term_variables.pl", "-f", "-g", "main_quiet"],
|
||||
"",
|
||||
"All tests passed",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acyclic_term_tests() {
|
||||
run_top_level_test_with_args(
|
||||
&["src/tests/acyclic_term.pl", "-f", "-g", "main_quiet"],
|
||||
"",
|
||||
"All tests passed",
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user