replace compare_term_test with parallel iterator, add is_not_variant
This commit is contained in:
@@ -643,15 +643,12 @@ enum SystemClauseType {
|
|||||||
UnattributedVar,
|
UnattributedVar,
|
||||||
#[strum_discriminants(strum(props(Arity = "4", Name = "$get_db_refs")))]
|
#[strum_discriminants(strum(props(Arity = "4", Name = "$get_db_refs")))]
|
||||||
GetDBRefs,
|
GetDBRefs,
|
||||||
#[strum_discriminants(strum(props(
|
|
||||||
Arity = "2",
|
|
||||||
Name = "$keysort_with_constant_var_ordering"
|
|
||||||
)))]
|
|
||||||
KeySortWithConstantVarOrdering,
|
|
||||||
#[strum_discriminants(strum(props(Arity = "0", Name = "$inference_limit_exceeded")))]
|
#[strum_discriminants(strum(props(Arity = "0", Name = "$inference_limit_exceeded")))]
|
||||||
InferenceLimitExceeded,
|
InferenceLimitExceeded,
|
||||||
#[strum_discriminants(strum(props(Arity = "1", Name = "$argv")))]
|
#[strum_discriminants(strum(props(Arity = "1", Name = "$argv")))]
|
||||||
Argv,
|
Argv,
|
||||||
|
#[strum_discriminants(strum(props(Arity = "2", Name = "$variant")))]
|
||||||
|
IsVariant,
|
||||||
Repl(ReplCodePtr),
|
Repl(ReplCodePtr),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
src/forms.rs
10
src/forms.rs
@@ -170,13 +170,9 @@ impl PartialOrd<BranchNumber> for BranchNumber {
|
|||||||
|
|
||||||
impl BranchNumber {
|
impl BranchNumber {
|
||||||
pub(crate) fn has_as_subbranch(&self, other: &Self) -> bool {
|
pub(crate) fn has_as_subbranch(&self, other: &Self) -> bool {
|
||||||
let delta_ratio = &self.delta / &other.delta;
|
other.delta <= self.delta &&
|
||||||
|
other.branch_num >= self.branch_num &&
|
||||||
if !delta_ratio.denominator().is_one() {
|
other.branch_num < &self.branch_num + &self.delta
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
other.branch_num >= self.branch_num && other.branch_num < &self.branch_num + &self.delta
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn split(&self) -> BranchNumber {
|
pub(crate) fn split(&self) -> BranchNumber {
|
||||||
|
|||||||
357
src/heap_iter.rs
357
src/heap_iter.rs
@@ -1,21 +1,378 @@
|
|||||||
#![allow(clippy::new_without_default)] // annotating structs annotated with #[bitfield] doesn't work
|
#![allow(clippy::new_without_default)] // annotating structs annotated with #[bitfield] doesn't work
|
||||||
#![allow(unused_parens)] // see mthom/scryer-prolog#3092 and rust-lang/rust#147126
|
#![allow(unused_parens)] // see mthom/scryer-prolog#3092 and rust-lang/rust#147126
|
||||||
|
|
||||||
|
use crate::arena::Arena;
|
||||||
|
use crate::forms::Number;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) use crate::machine::gc::StacklessPreOrderHeapIter;
|
pub(crate) use crate::machine::gc::StacklessPreOrderHeapIter;
|
||||||
|
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::machine::cycle_detection::*;
|
use crate::machine::cycle_detection::*;
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
|
use crate::machine::machine_indices::TermOrderCategory;
|
||||||
use crate::machine::stack::*;
|
use crate::machine::stack::*;
|
||||||
|
use crate::parser::lexer::MachineState;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
use fxhash::FxBuildHasher;
|
||||||
|
use indexmap::IndexSet;
|
||||||
use scryer_modular_bitfield::prelude::*;
|
use scryer_modular_bitfield::prelude::*;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
|
// iterate through the subterms of a pair of terms
|
||||||
|
// for as long as they structurally agree, reporting
|
||||||
|
// the earliest (pre-order) difference before returning
|
||||||
|
// None's and pairs of variables as the Iterator Item.
|
||||||
|
|
||||||
|
pub struct ParallelHeapIter<'a> {
|
||||||
|
stack: Vec<HeapCellValue>,
|
||||||
|
heap: &'a Heap,
|
||||||
|
arena: &'a Arena,
|
||||||
|
tabu_list: IndexSet<(usize, usize), FxBuildHasher>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ParallelHeapIter<'a> {
|
||||||
|
pub fn from(machine_st: &'a MachineState, h1: HeapCellValue, h2: HeapCellValue) -> Self {
|
||||||
|
Self {
|
||||||
|
stack: vec![h2, h1],
|
||||||
|
heap: &machine_st.heap,
|
||||||
|
arena: &machine_st.arena,
|
||||||
|
tabu_list: IndexSet::with_hasher(FxBuildHasher::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TermPair {
|
||||||
|
Vars(usize, usize),
|
||||||
|
Less(HeapCellValue, HeapCellValue),
|
||||||
|
Greater(HeapCellValue, HeapCellValue),
|
||||||
|
Unordered(HeapCellValue, HeapCellValue),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParallelHeapIter<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn parallel_cmp<Cmp: Ord>(
|
||||||
|
&mut self,
|
||||||
|
v1: Cmp,
|
||||||
|
v2: Cmp,
|
||||||
|
h1: HeapCellValue,
|
||||||
|
h2: HeapCellValue,
|
||||||
|
) -> Option<TermPair> {
|
||||||
|
match v1.cmp(&v2) {
|
||||||
|
Ordering::Greater => {
|
||||||
|
self.stack.clear();
|
||||||
|
Some(TermPair::Greater(h1, h2))
|
||||||
|
}
|
||||||
|
Ordering::Less => {
|
||||||
|
self.stack.clear();
|
||||||
|
Some(TermPair::Less(h1, h2))
|
||||||
|
}
|
||||||
|
Ordering::Equal => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! some_or_return {
|
||||||
|
($e:expr) => {
|
||||||
|
if let Some(x) = $e {
|
||||||
|
return Some(x);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for ParallelHeapIter<'_> {
|
||||||
|
type Item = TermPair;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
use crate::offset_table::F64Offset;
|
||||||
|
|
||||||
|
while let Some(s1) = self.stack.pop() {
|
||||||
|
let s1 = heap_bound_deref(self.heap, s1);
|
||||||
|
|
||||||
|
let s2 = self.stack.pop().unwrap();
|
||||||
|
let s2 = heap_bound_deref(self.heap, s2);
|
||||||
|
|
||||||
|
if s1 == s2 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let v1 = heap_bound_store(self.heap, s1);
|
||||||
|
let v2 = heap_bound_store(self.heap, s2);
|
||||||
|
|
||||||
|
let order_cat_v1 = v1.order_category(self.heap);
|
||||||
|
let order_cat_v2 = v2.order_category(self.heap);
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp(order_cat_v1, order_cat_v2, v1, v2));
|
||||||
|
|
||||||
|
match order_cat_v1 {
|
||||||
|
Some(TermOrderCategory::Variable) => {
|
||||||
|
let v1 = v1.get_value() as usize;
|
||||||
|
let v2 = v2.get_value() as usize;
|
||||||
|
|
||||||
|
return Some(TermPair::Vars(v1, v2));
|
||||||
|
}
|
||||||
|
Some(TermOrderCategory::FloatingPoint) => {
|
||||||
|
let v1_offset = cell_as_f64_offset!(v1);
|
||||||
|
let v2_offset = cell_as_f64_offset!(v2);
|
||||||
|
|
||||||
|
let v1_f64 = self.arena.f64_tbl.get_entry(v1_offset);
|
||||||
|
let v2_f64 = self.arena.f64_tbl.get_entry(v2_offset);
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp(v1_f64, v2_f64, v1, v2));
|
||||||
|
}
|
||||||
|
Some(TermOrderCategory::Integer) => {
|
||||||
|
let v1_int = Number::try_from((v1, &self.arena.f64_tbl)).unwrap();
|
||||||
|
let v2_int = Number::try_from((v2, &self.arena.f64_tbl)).unwrap();
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp(v1_int, v2_int, v1, v2));
|
||||||
|
}
|
||||||
|
Some(TermOrderCategory::Atom) => {
|
||||||
|
read_heap_cell!(v1,
|
||||||
|
(HeapCellValueTag::Atom, (n1, _a1)) => {
|
||||||
|
read_heap_cell!(v2,
|
||||||
|
(HeapCellValueTag::Atom, (n2, _a2)) => {
|
||||||
|
some_or_return!(self.parallel_cmp(n1, n2, v1, v2));
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let n2 = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name();
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp(n1, n2, v1, v2));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let n1 = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name();
|
||||||
|
|
||||||
|
read_heap_cell!(v2,
|
||||||
|
(HeapCellValueTag::Atom, (n2, _a2)) => {
|
||||||
|
some_or_return!(self.parallel_cmp(n1, n2, v1, v2));
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s) => {
|
||||||
|
let n2 = cell_as_atom_cell!(self.heap[s])
|
||||||
|
.get_name();
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp(n1, n2, v1, v2));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Some(TermOrderCategory::Compound) => {
|
||||||
|
read_heap_cell!(v1,
|
||||||
|
(HeapCellValueTag::Lis, l1) => {
|
||||||
|
read_heap_cell!(v2,
|
||||||
|
(HeapCellValueTag::PStrLoc, l2) => {
|
||||||
|
if self.tabu_list.contains(&(l1, l2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tabu_list.insert((l1, l2));
|
||||||
|
|
||||||
|
// like the action of partial_string_to_stack here but the
|
||||||
|
// ordering of stack pushes is (crucially for comparison
|
||||||
|
// correctness) different.
|
||||||
|
let (c, succ_cell) = self.heap.last_str_char_and_tail(l2);
|
||||||
|
|
||||||
|
self.stack.push(succ_cell);
|
||||||
|
self.stack.push(heap_loc_as_cell!(l1 + 1));
|
||||||
|
|
||||||
|
self.stack.push(char_as_cell!(c));
|
||||||
|
self.stack.push(heap_loc_as_cell!(l1));
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Lis, l2) => {
|
||||||
|
if self.tabu_list.contains(&(l1, l2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tabu_list.insert((l1, l2));
|
||||||
|
|
||||||
|
self.stack.push(self.heap[l2 + 1]);
|
||||||
|
self.stack.push(self.heap[l1 + 1]);
|
||||||
|
|
||||||
|
self.stack.push(self.heap[l2]);
|
||||||
|
self.stack.push(self.heap[l1]);
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s2) => {
|
||||||
|
if self.tabu_list.contains(&(l1, s2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (n2, a2) = cell_as_atom_cell!(self.heap[s2])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp((2, atom!(".")), (a2, n2), v1, v2));
|
||||||
|
|
||||||
|
self.tabu_list.insert((l1, s2));
|
||||||
|
|
||||||
|
self.stack.push(self.heap[s2 + 2]);
|
||||||
|
self.stack.push(self.heap[l1 + 1]);
|
||||||
|
|
||||||
|
self.stack.push(self.heap[s2 + 1]);
|
||||||
|
self.stack.push(self.heap[l1]);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::PStrLoc, l1) => {
|
||||||
|
read_heap_cell!(v2,
|
||||||
|
(HeapCellValueTag::PStrLoc, l2) => {
|
||||||
|
if self.tabu_list.contains(&(l1, l2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.heap.compare_pstr_segments(l1, l2) {
|
||||||
|
PStrSegmentCmpResult::Continue(v1, v2) => {
|
||||||
|
self.tabu_list.insert((l1, l2));
|
||||||
|
|
||||||
|
self.stack.push(v1.offset_by(l1));
|
||||||
|
self.stack.push(v2.offset_by(l2));
|
||||||
|
}
|
||||||
|
PStrSegmentCmpResult::Less => {
|
||||||
|
self.stack.clear();
|
||||||
|
return Some(TermPair::Less(v1, v2));
|
||||||
|
}
|
||||||
|
PStrSegmentCmpResult::Greater => {
|
||||||
|
self.stack.clear();
|
||||||
|
return Some(TermPair::Greater(v1, v2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Lis, l2) => {
|
||||||
|
if self.tabu_list.contains(&(l1, l2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tabu_list.insert((l1, l2));
|
||||||
|
|
||||||
|
let (c, succ_cell) = self.heap.last_str_char_and_tail(l1);
|
||||||
|
|
||||||
|
self.stack.push(succ_cell);
|
||||||
|
self.stack.push(heap_loc_as_cell!(l2 + 1));
|
||||||
|
|
||||||
|
self.stack.push(char_as_cell!(c));
|
||||||
|
self.stack.push(heap_loc_as_cell!(l2));
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s2) => {
|
||||||
|
if self.tabu_list.contains(&(l1, s2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tabu_list.insert((l1, s2));
|
||||||
|
|
||||||
|
let (n2, a2) = cell_as_atom_cell!(self.heap[s2])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp((2, atom!(".")), (a2, n2), v1, v2));
|
||||||
|
|
||||||
|
let (c, succ_cell) = self.heap.last_str_char_and_tail(l1);
|
||||||
|
|
||||||
|
self.stack.push(heap_loc_as_cell!(s2+2));
|
||||||
|
self.stack.push(succ_cell);
|
||||||
|
|
||||||
|
self.stack.push(heap_loc_as_cell!(s2+1));
|
||||||
|
self.stack.push(char_as_cell!(c));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Str, s1) => {
|
||||||
|
read_heap_cell!(v2,
|
||||||
|
(HeapCellValueTag::Str, s2) => {
|
||||||
|
if self.tabu_list.contains(&(s1, s2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (n1, a1) = cell_as_atom_cell!(self.heap[s1])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
let (n2, a2) = cell_as_atom_cell!(self.heap[s2])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp((a1, n1), (a2, n2), v1, v2));
|
||||||
|
|
||||||
|
self.tabu_list.insert((s1, s2));
|
||||||
|
|
||||||
|
for idx in (1 .. a1+1).rev() {
|
||||||
|
self.stack.push(self.heap[s2+idx]);
|
||||||
|
self.stack.push(self.heap[s1+idx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Lis, l2) => {
|
||||||
|
if self.tabu_list.contains(&(s1, l2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (n1, a1) = cell_as_atom_cell!(self.heap[s1])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp((a1, n1), (2, atom!(".")), v1, v2));
|
||||||
|
|
||||||
|
self.stack.push(self.heap[l2]);
|
||||||
|
self.stack.push(self.heap[s1+1]);
|
||||||
|
|
||||||
|
self.stack.push(self.heap[l2+1]);
|
||||||
|
self.stack.push(self.heap[s1+2]);
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::PStrLoc, l2) => {
|
||||||
|
if self.tabu_list.contains(&(s1, l2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (n1, a1) = cell_as_atom_cell!(self.heap[s1])
|
||||||
|
.get_name_and_arity();
|
||||||
|
|
||||||
|
some_or_return!(self.parallel_cmp((a1, n1), (2, atom!(".")), v1, v2));
|
||||||
|
|
||||||
|
self.tabu_list.insert((s1, l2));
|
||||||
|
|
||||||
|
let (c, succ_cell) = self.heap.last_str_char_and_tail(l2);
|
||||||
|
|
||||||
|
self.stack.push(succ_cell);
|
||||||
|
self.stack.push(heap_loc_as_cell!(s1+2));
|
||||||
|
|
||||||
|
self.stack.push(char_as_cell!(c));
|
||||||
|
self.stack.push(heap_loc_as_cell!(s1+1));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Some(TermPair::Unordered(v1, v2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eager_stackful_preorder_iter(
|
pub fn eager_stackful_preorder_iter(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
|
|||||||
@@ -726,7 +726,6 @@ impl Instruction {
|
|||||||
| &Instruction::CallDeleteAllAttributesFromVar
|
| &Instruction::CallDeleteAllAttributesFromVar
|
||||||
| &Instruction::CallUnattributedVar
|
| &Instruction::CallUnattributedVar
|
||||||
| &Instruction::CallGetDBRefs
|
| &Instruction::CallGetDBRefs
|
||||||
| &Instruction::CallKeySortWithConstantVarOrdering
|
|
||||||
| &Instruction::CallInferenceLimitExceeded
|
| &Instruction::CallInferenceLimitExceeded
|
||||||
| &Instruction::CallFetchGlobalVar
|
| &Instruction::CallFetchGlobalVar
|
||||||
| &Instruction::CallFirstStream
|
| &Instruction::CallFirstStream
|
||||||
@@ -986,7 +985,6 @@ impl Instruction {
|
|||||||
| &Instruction::ExecuteDeleteAllAttributesFromVar
|
| &Instruction::ExecuteDeleteAllAttributesFromVar
|
||||||
| &Instruction::ExecuteUnattributedVar
|
| &Instruction::ExecuteUnattributedVar
|
||||||
| &Instruction::ExecuteGetDBRefs
|
| &Instruction::ExecuteGetDBRefs
|
||||||
| &Instruction::ExecuteKeySortWithConstantVarOrdering
|
|
||||||
| &Instruction::ExecuteInferenceLimitExceeded
|
| &Instruction::ExecuteInferenceLimitExceeded
|
||||||
| &Instruction::ExecuteFetchGlobalVar
|
| &Instruction::ExecuteFetchGlobalVar
|
||||||
| &Instruction::ExecuteFirstStream
|
| &Instruction::ExecuteFirstStream
|
||||||
|
|||||||
@@ -103,9 +103,8 @@ impl MachineState {
|
|||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
attr_vars.sort_unstable_by(|a1, a2| {
|
attr_vars
|
||||||
compare_term_test!(self, *a1, *a2).unwrap_or(Ordering::Less)
|
.sort_unstable_by(|a1, a2| self.compare_term_test(*a1, *a2).unwrap_or(Ordering::Less));
|
||||||
});
|
|
||||||
|
|
||||||
attr_vars.dedup();
|
attr_vars.dedup();
|
||||||
attr_vars
|
attr_vars
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let atom = match compare_term_test!(self, a2, a3) {
|
let atom = match self.compare_term_test(a2, a3) {
|
||||||
Some(Ordering::Greater) => {
|
Some(Ordering::Greater) => {
|
||||||
atom!(">")
|
atom!(">")
|
||||||
}
|
}
|
||||||
@@ -151,11 +151,8 @@ impl MachineState {
|
|||||||
let stub_gen = || functor_stub(atom!("sort"), 2);
|
let stub_gen = || functor_stub(atom!("sort"), 2);
|
||||||
let mut list = self.try_from_list(self.registers[1], stub_gen)?;
|
let mut list = self.try_from_list(self.registers[1], stub_gen)?;
|
||||||
|
|
||||||
list.sort_unstable_by(|v1, v2| {
|
list.sort_unstable_by(|v1, v2| self.compare_term_test(*v1, *v2).unwrap_or(Ordering::Less));
|
||||||
compare_term_test!(self, *v1, *v2).unwrap_or(Ordering::Less)
|
list.dedup_by(|v1, v2| self.compare_term_test(*v1, *v2) == Some(Ordering::Equal));
|
||||||
});
|
|
||||||
|
|
||||||
list.dedup_by(|v1, v2| compare_term_test!(self, *v1, *v2) == Some(Ordering::Equal));
|
|
||||||
|
|
||||||
let heap_addr = resource_error_call_result!(
|
let heap_addr = resource_error_call_result!(
|
||||||
self,
|
self,
|
||||||
@@ -167,7 +164,7 @@ impl MachineState {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn keysort(&mut self, var_comparison: VarComparison) -> CallResult {
|
fn keysort(&mut self) -> CallResult {
|
||||||
self.check_keysort_errors()?;
|
self.check_keysort_errors()?;
|
||||||
|
|
||||||
let stub_gen = || functor_stub(atom!("keysort"), 2);
|
let stub_gen = || functor_stub(atom!("keysort"), 2);
|
||||||
@@ -180,9 +177,7 @@ impl MachineState {
|
|||||||
key_pairs.push((key, val));
|
key_pairs.push((key, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
key_pairs.sort_by(|a1, a2| {
|
key_pairs.sort_by(|a1, a2| self.compare_term_test(a1.0, a2.0).unwrap_or(Ordering::Less));
|
||||||
compare_term_test!(self, a1.0, a2.0, var_comparison).unwrap_or(Ordering::Less)
|
|
||||||
});
|
|
||||||
|
|
||||||
let heap_addr = resource_error_call_result!(
|
let heap_addr = resource_error_call_result!(
|
||||||
self,
|
self,
|
||||||
@@ -2034,8 +2029,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
if let Some(Ordering::Greater) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
{
|
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -2045,8 +2039,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
if let Some(Ordering::Greater) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
{
|
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -2056,7 +2049,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Less) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -2066,7 +2059,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Less) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -2076,7 +2069,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match self.machine_st.compare_term_test(a1, a2) {
|
||||||
Some(Ordering::Greater | Ordering::Equal) => {
|
Some(Ordering::Greater | Ordering::Equal) => {
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
@@ -2089,7 +2082,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match self.machine_st.compare_term_test(a1, a2) {
|
||||||
Some(Ordering::Greater | Ordering::Equal) => {
|
Some(Ordering::Greater | Ordering::Equal) => {
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
@@ -2102,7 +2095,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match self.machine_st.compare_term_test(a1, a2) {
|
||||||
Some(Ordering::Less | Ordering::Equal) => {
|
Some(Ordering::Less | Ordering::Equal) => {
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
}
|
}
|
||||||
@@ -2115,7 +2108,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match self.machine_st.compare_term_test(a1, a2) {
|
||||||
Some(Ordering::Less | Ordering::Equal) => {
|
Some(Ordering::Less | Ordering::Equal) => {
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
}
|
}
|
||||||
@@ -2188,7 +2181,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Equal) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
@@ -2198,7 +2191,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Equal) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
@@ -2213,19 +2206,11 @@ impl Machine {
|
|||||||
step_or_fail!(self.machine_st, self.machine_st.p = self.machine_st.cp);
|
step_or_fail!(self.machine_st, self.machine_st.p = self.machine_st.cp);
|
||||||
}
|
}
|
||||||
&Instruction::DefaultCallKeySort => {
|
&Instruction::DefaultCallKeySort => {
|
||||||
try_or_throw!(
|
try_or_throw!(self.machine_st, self.machine_st.keysort(), continue);
|
||||||
self.machine_st,
|
|
||||||
self.machine_st.keysort(VarComparison::Distinct),
|
|
||||||
continue
|
|
||||||
);
|
|
||||||
step_or_fail!(self.machine_st, self.machine_st.p += 1);
|
step_or_fail!(self.machine_st, self.machine_st.p += 1);
|
||||||
}
|
}
|
||||||
&Instruction::DefaultExecuteKeySort => {
|
&Instruction::DefaultExecuteKeySort => {
|
||||||
try_or_throw!(
|
try_or_throw!(self.machine_st, self.machine_st.keysort(), continue);
|
||||||
self.machine_st,
|
|
||||||
self.machine_st.keysort(VarComparison::Distinct),
|
|
||||||
continue
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -2323,8 +2308,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
if let Some(Ordering::Greater) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
{
|
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -2335,8 +2319,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2)
|
if let Some(Ordering::Greater) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
{
|
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
} else {
|
} else {
|
||||||
@@ -2347,7 +2330,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Less) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -2358,7 +2341,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Less) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
} else {
|
} else {
|
||||||
@@ -2369,7 +2352,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match self.machine_st.compare_term_test(a1, a2) {
|
||||||
Some(Ordering::Greater | Ordering::Equal) => {
|
Some(Ordering::Greater | Ordering::Equal) => {
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
@@ -2383,7 +2366,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match self.machine_st.compare_term_test(a1, a2) {
|
||||||
Some(Ordering::Greater | Ordering::Equal) => {
|
Some(Ordering::Greater | Ordering::Equal) => {
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
@@ -2397,7 +2380,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match self.machine_st.compare_term_test(a1, a2) {
|
||||||
Some(Ordering::Less | Ordering::Equal) => {
|
Some(Ordering::Less | Ordering::Equal) => {
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st.p += 1;
|
self.machine_st.p += 1;
|
||||||
@@ -2411,7 +2394,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
match compare_term_test!(self.machine_st, a1, a2) {
|
match self.machine_st.compare_term_test(a1, a2) {
|
||||||
Some(Ordering::Less | Ordering::Equal) => {
|
Some(Ordering::Less | Ordering::Equal) => {
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
self.machine_st.p = self.machine_st.cp;
|
self.machine_st.p = self.machine_st.cp;
|
||||||
@@ -2503,7 +2486,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Equal) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
@@ -2514,7 +2497,7 @@ impl Machine {
|
|||||||
let a1 = self.machine_st.registers[1];
|
let a1 = self.machine_st.registers[1];
|
||||||
let a2 = self.machine_st.registers[2];
|
let a2 = self.machine_st.registers[2];
|
||||||
|
|
||||||
if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
|
if let Some(Ordering::Equal) = self.machine_st.compare_term_test(a1, a2) {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
} else {
|
} else {
|
||||||
increment_call_count!(self.machine_st);
|
increment_call_count!(self.machine_st);
|
||||||
@@ -2542,11 +2525,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::CallKeySort => {
|
&Instruction::CallKeySort => {
|
||||||
try_or_throw!(
|
try_or_throw!(self.machine_st, self.machine_st.keysort(), continue);
|
||||||
self.machine_st,
|
|
||||||
self.machine_st.keysort(VarComparison::Distinct),
|
|
||||||
continue
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -2556,11 +2535,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::ExecuteKeySort => {
|
&Instruction::ExecuteKeySort => {
|
||||||
try_or_throw!(
|
try_or_throw!(self.machine_st, self.machine_st.keysort(), continue);
|
||||||
self.machine_st,
|
|
||||||
self.machine_st.keysort(VarComparison::Distinct),
|
|
||||||
continue
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -2570,11 +2545,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::CallKeySortWithConstantVarOrdering => {
|
&Instruction::CallKeySortWithConstantVarOrdering => {
|
||||||
try_or_throw!(
|
try_or_throw!(self.machine_st, self.machine_st.keysort(), continue);
|
||||||
self.machine_st,
|
|
||||||
self.machine_st.keysort(VarComparison::Indistinct),
|
|
||||||
continue
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -2584,11 +2555,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::ExecuteKeySortWithConstantVarOrdering => {
|
&Instruction::ExecuteKeySortWithConstantVarOrdering => {
|
||||||
try_or_throw!(
|
try_or_throw!(self.machine_st, self.machine_st.keysort(), continue);
|
||||||
self.machine_st,
|
|
||||||
self.machine_st.keysort(VarComparison::Indistinct),
|
|
||||||
continue
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.machine_st.fail {
|
if self.machine_st.fail {
|
||||||
self.machine_st.backtrack();
|
self.machine_st.backtrack();
|
||||||
@@ -4813,6 +4780,14 @@ impl Machine {
|
|||||||
try_or_throw!(self.machine_st, self.argv(), continue);
|
try_or_throw!(self.machine_st, self.argv(), continue);
|
||||||
step_or_fail!(self.machine_st, self.machine_st.p = self.machine_st.cp);
|
step_or_fail!(self.machine_st, self.machine_st.p = self.machine_st.cp);
|
||||||
}
|
}
|
||||||
|
&Instruction::CallIsVariant => {
|
||||||
|
self.machine_st.fail = self.machine_st.is_not_variant();
|
||||||
|
step_or_fail!(self.machine_st, self.machine_st.p += 1);
|
||||||
|
}
|
||||||
|
&Instruction::ExecuteIsVariant => {
|
||||||
|
self.machine_st.fail = self.machine_st.is_not_variant();
|
||||||
|
step_or_fail!(self.machine_st, self.machine_st.p = self.machine_st.cp);
|
||||||
|
}
|
||||||
&Instruction::CallCurrentTime => {
|
&Instruction::CallCurrentTime => {
|
||||||
self.current_time();
|
self.current_time();
|
||||||
step_or_fail!(self.machine_st, self.machine_st.p += 1);
|
step_or_fail!(self.machine_st, self.machine_st.p += 1);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use crate::machine::copier::*;
|
|||||||
use crate::machine::heap::AllocError;
|
use crate::machine::heap::AllocError;
|
||||||
use crate::machine::heap::*;
|
use crate::machine::heap::*;
|
||||||
use crate::machine::machine_errors::*;
|
use crate::machine::machine_errors::*;
|
||||||
use crate::machine::machine_indices::*;
|
|
||||||
use crate::machine::machine_state::*;
|
use crate::machine::machine_state::*;
|
||||||
use crate::machine::partial_string::*;
|
use crate::machine::partial_string::*;
|
||||||
use crate::machine::stack::*;
|
use crate::machine::stack::*;
|
||||||
@@ -17,8 +16,6 @@ use crate::parser::ast::*;
|
|||||||
use crate::parser::dashu::{Integer, Rational};
|
use crate::parser::dashu::{Integer, Rational};
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
@@ -380,347 +377,6 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compare_term_test(&mut self, var_comparison: VarComparison) -> Option<Ordering> {
|
|
||||||
let mut tabu_list = IndexSet::new();
|
|
||||||
|
|
||||||
while let Some(s1) = self.pdl.pop() {
|
|
||||||
let s1 = self.deref(s1);
|
|
||||||
|
|
||||||
let s2 = self.pdl.pop().unwrap();
|
|
||||||
let s2 = self.deref(s2);
|
|
||||||
|
|
||||||
if s1 == s2 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let v1 = self.store(s1);
|
|
||||||
let v2 = self.store(s2);
|
|
||||||
|
|
||||||
let order_cat_v1 = v1.order_category(&self.heap);
|
|
||||||
let order_cat_v2 = v2.order_category(&self.heap);
|
|
||||||
|
|
||||||
if order_cat_v1 != order_cat_v2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(order_cat_v1.cmp(&order_cat_v2));
|
|
||||||
}
|
|
||||||
|
|
||||||
match order_cat_v1 {
|
|
||||||
Some(TermOrderCategory::Variable) => {
|
|
||||||
if let VarComparison::Distinct = var_comparison {
|
|
||||||
let v1 = v1.as_var().unwrap();
|
|
||||||
let v2 = v2.as_var().unwrap();
|
|
||||||
|
|
||||||
if v1 != v2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(v1.cmp(&v2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(TermOrderCategory::FloatingPoint) => {
|
|
||||||
let v1 = cell_as_f64_offset!(v1);
|
|
||||||
let v2 = cell_as_f64_offset!(v2);
|
|
||||||
|
|
||||||
let v1 = self.arena.f64_tbl.get_entry(v1);
|
|
||||||
let v2 = self.arena.f64_tbl.get_entry(v2);
|
|
||||||
|
|
||||||
if v1 != v2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(v1.cmp(&v2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(TermOrderCategory::Integer) => {
|
|
||||||
let v1 = Number::try_from((v1, &self.arena.f64_tbl)).unwrap();
|
|
||||||
let v2 = Number::try_from((v2, &self.arena.f64_tbl)).unwrap();
|
|
||||||
|
|
||||||
if v1 != v2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(v1.cmp(&v2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(TermOrderCategory::Atom) => {
|
|
||||||
read_heap_cell!(v1,
|
|
||||||
(HeapCellValueTag::Atom, (n1, _a1)) => {
|
|
||||||
read_heap_cell!(v2,
|
|
||||||
(HeapCellValueTag::Atom, (n2, _a2)) => {
|
|
||||||
if n1 != n2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(n1.cmp(&n2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Str, s) => {
|
|
||||||
let n2 = cell_as_atom_cell!(self.heap[s])
|
|
||||||
.get_name();
|
|
||||||
|
|
||||||
if n1 != n2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(n1.cmp(&n2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Str, s) => {
|
|
||||||
let n1 = cell_as_atom_cell!(self.heap[s])
|
|
||||||
.get_name();
|
|
||||||
|
|
||||||
read_heap_cell!(v2,
|
|
||||||
(HeapCellValueTag::Atom, (n2, _a2)) => {
|
|
||||||
if n1 != n2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(n1.cmp(&n2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Str, s) => {
|
|
||||||
let n2 = cell_as_atom_cell!(self.heap[s])
|
|
||||||
.get_name();
|
|
||||||
|
|
||||||
if n1 != n2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(n1.cmp(&n2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Some(TermOrderCategory::Compound) => {
|
|
||||||
read_heap_cell!(v1,
|
|
||||||
(HeapCellValueTag::Lis, l1) => {
|
|
||||||
read_heap_cell!(v2,
|
|
||||||
(HeapCellValueTag::PStrLoc, l2) => {
|
|
||||||
if tabu_list.contains(&(l1, l2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tabu_list.insert((l1, l2));
|
|
||||||
|
|
||||||
// like the action of
|
|
||||||
// partial_string_to_pdl here but
|
|
||||||
// the ordering of PDL pushes is
|
|
||||||
// (crucially for comparison
|
|
||||||
// correctness) different.
|
|
||||||
let (c, succ_cell) = self.heap.last_str_char_and_tail(l2);
|
|
||||||
|
|
||||||
self.pdl.push(succ_cell);
|
|
||||||
self.pdl.push(heap_loc_as_cell!(l1 + 1));
|
|
||||||
|
|
||||||
self.pdl.push(char_as_cell!(c));
|
|
||||||
self.pdl.push(heap_loc_as_cell!(l1));
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Lis, l2) => {
|
|
||||||
if tabu_list.contains(&(l1, l2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tabu_list.insert((l1, l2));
|
|
||||||
|
|
||||||
self.pdl.push(self.heap[l2 + 1]);
|
|
||||||
self.pdl.push(self.heap[l1 + 1]);
|
|
||||||
|
|
||||||
self.pdl.push(self.heap[l2]);
|
|
||||||
self.pdl.push(self.heap[l1]);
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Str, s2) => {
|
|
||||||
if tabu_list.contains(&(l1, s2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (name, arity) = cell_as_atom_cell!(self.heap[s2])
|
|
||||||
.get_name_and_arity();
|
|
||||||
|
|
||||||
match (2, atom!(".")).cmp(&(arity, name)) {
|
|
||||||
Ordering::Equal => {
|
|
||||||
tabu_list.insert((l1, s2));
|
|
||||||
|
|
||||||
self.pdl.push(self.heap[s2 + 2]);
|
|
||||||
self.pdl.push(self.heap[l1 + 1]);
|
|
||||||
|
|
||||||
self.pdl.push(self.heap[s2 + 1]);
|
|
||||||
self.pdl.push(self.heap[l1]);
|
|
||||||
}
|
|
||||||
ordering => {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(ordering);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::PStrLoc, l1) => {
|
|
||||||
read_heap_cell!(v2,
|
|
||||||
(HeapCellValueTag::PStrLoc, l2) => {
|
|
||||||
if tabu_list.contains(&(l1, l2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tabu_list.insert((l1, l2));
|
|
||||||
|
|
||||||
match self.heap.compare_pstr_segments(l1, l2) {
|
|
||||||
PStrSegmentCmpResult::Continue(v1, v2) => {
|
|
||||||
self.pdl.push(v1.offset_by(l1));
|
|
||||||
self.pdl.push(v2.offset_by(l2));
|
|
||||||
}
|
|
||||||
PStrSegmentCmpResult::Less => {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(Ordering::Less);
|
|
||||||
}
|
|
||||||
PStrSegmentCmpResult::Greater => {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(Ordering::Greater);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Lis, l2) => {
|
|
||||||
if tabu_list.contains(&(l1, l2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tabu_list.insert((l1, l2));
|
|
||||||
|
|
||||||
let (c, succ_cell) = self.heap.last_str_char_and_tail(l1);
|
|
||||||
|
|
||||||
self.pdl.push(succ_cell);
|
|
||||||
self.pdl.push(heap_loc_as_cell!(l2 + 1));
|
|
||||||
|
|
||||||
self.pdl.push(char_as_cell!(c));
|
|
||||||
self.pdl.push(heap_loc_as_cell!(l2));
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Str, s2) => {
|
|
||||||
if tabu_list.contains(&(l1, s2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tabu_list.insert((l1, s2));
|
|
||||||
|
|
||||||
let (n2, a2) = cell_as_atom_cell!(self.heap[s2])
|
|
||||||
.get_name_and_arity();
|
|
||||||
|
|
||||||
match (2, atom!(".")).cmp(&(a2,n2)) {
|
|
||||||
Ordering::Equal => {
|
|
||||||
let (c, succ_cell) = self.heap.last_str_char_and_tail(l1);
|
|
||||||
|
|
||||||
self.pdl.push(heap_loc_as_cell!(s2+2));
|
|
||||||
self.pdl.push(succ_cell);
|
|
||||||
|
|
||||||
self.pdl.push(heap_loc_as_cell!(s2+1));
|
|
||||||
self.pdl.push(char_as_cell!(c));
|
|
||||||
}
|
|
||||||
ordering => {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(ordering);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Str, s1) => {
|
|
||||||
read_heap_cell!(v2,
|
|
||||||
(HeapCellValueTag::Str, s2) => {
|
|
||||||
if tabu_list.contains(&(s1, s2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (n1, a1) = cell_as_atom_cell!(self.heap[s1])
|
|
||||||
.get_name_and_arity();
|
|
||||||
|
|
||||||
let (n2, a2) = cell_as_atom_cell!(self.heap[s2])
|
|
||||||
.get_name_and_arity();
|
|
||||||
|
|
||||||
match (a1,n1).cmp(&(a2, n2)) {
|
|
||||||
Ordering::Equal => {
|
|
||||||
tabu_list.insert((s1, s2));
|
|
||||||
|
|
||||||
for idx in (1 .. a1+1).rev() {
|
|
||||||
self.pdl.push(self.heap[s2+idx]);
|
|
||||||
self.pdl.push(self.heap[s1+idx]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ordering => {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(ordering);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Lis, l2) => {
|
|
||||||
if tabu_list.contains(&(s1, l2)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
tabu_list.insert((s1, l2));
|
|
||||||
|
|
||||||
let (n1, a1) = cell_as_atom_cell!(self.heap[s1])
|
|
||||||
.get_name_and_arity();
|
|
||||||
|
|
||||||
match (a1,n1).cmp(&(2, atom!("."))) {
|
|
||||||
Ordering::Equal => {
|
|
||||||
self.pdl.push(self.heap[l2]);
|
|
||||||
self.pdl.push(self.heap[s1+1]);
|
|
||||||
|
|
||||||
self.pdl.push(self.heap[l2+1]);
|
|
||||||
self.pdl.push(self.heap[s1+2]);
|
|
||||||
}
|
|
||||||
ordering => {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(ordering);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::PStrLoc, l2) => {
|
|
||||||
let (n1, a1) = cell_as_atom_cell!(self.heap[s1])
|
|
||||||
.get_name_and_arity();
|
|
||||||
|
|
||||||
match (a1,n1).cmp(&(2, atom!("."))) {
|
|
||||||
Ordering::Equal => {
|
|
||||||
let (c, succ_cell) = self.heap.last_str_char_and_tail(l2);
|
|
||||||
|
|
||||||
self.pdl.push(succ_cell);
|
|
||||||
self.pdl.push(heap_loc_as_cell!(s1+2));
|
|
||||||
|
|
||||||
self.pdl.push(char_as_cell!(c));
|
|
||||||
self.pdl.push(heap_loc_as_cell!(s1+1));
|
|
||||||
}
|
|
||||||
ordering => {
|
|
||||||
self.pdl.clear();
|
|
||||||
return Some(ordering);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
if v1 != v2 {
|
|
||||||
self.pdl.clear();
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Ordering::Equal)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn setup_call_n_init_goal_info(
|
pub(crate) fn setup_call_n_init_goal_info(
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: HeapCellValue,
|
goal: HeapCellValue,
|
||||||
@@ -891,16 +547,32 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true on failure, false on success.
|
// returns true on failure, false on success.
|
||||||
pub fn eq_test(&mut self, h1: HeapCellValue, h2: HeapCellValue) -> bool {
|
pub fn eq_test(&self, h1: HeapCellValue, h2: HeapCellValue) -> bool {
|
||||||
if h1 == h2 {
|
if h1 == h2 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
compare_term_test!(self, h1, h2)
|
self.compare_term_test(h1, h2)
|
||||||
.map(|o| o != Ordering::Equal)
|
.map(|o| o != Ordering::Equal)
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn compare_term_test(&self, h1: HeapCellValue, h2: HeapCellValue) -> Option<Ordering> {
|
||||||
|
for term_pair in ParallelHeapIter::from(self, h1, h2) {
|
||||||
|
match term_pair {
|
||||||
|
TermPair::Vars(v1_offset, v2_offset) if v1_offset != v2_offset => {
|
||||||
|
return Some(v1_offset.cmp(&v2_offset));
|
||||||
|
}
|
||||||
|
TermPair::Less(..) => return Some(Ordering::Less),
|
||||||
|
TermPair::Greater(..) => return Some(Ordering::Greater),
|
||||||
|
TermPair::Unordered(cell_1, cell_2) if cell_1 != cell_2 => return None,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Ordering::Equal)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn try_functor_compound_case(&mut self, name: Atom, arity: usize) {
|
fn try_functor_compound_case(&mut self, name: Atom, arity: usize) {
|
||||||
self.try_functor_unify_components(atom_as_cell!(name), arity);
|
self.try_functor_unify_components(atom_as_cell!(name), arity);
|
||||||
|
|||||||
@@ -581,56 +581,44 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, wam.heap[0], wam.heap[1]),
|
wam.compare_term_test(wam.heap[0], wam.heap[1]),
|
||||||
Some(Ordering::Less)
|
Some(Ordering::Less)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, wam.heap[1], wam.heap[0]),
|
wam.compare_term_test(wam.heap[1], wam.heap[0]),
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, wam.heap[0], wam.heap[0]),
|
wam.compare_term_test(wam.heap[0], wam.heap[0]),
|
||||||
Some(Ordering::Equal)
|
Some(Ordering::Equal)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, wam.heap[1], wam.heap[1]),
|
wam.compare_term_test(wam.heap[1], wam.heap[1]),
|
||||||
Some(Ordering::Equal)
|
Some(Ordering::Equal)
|
||||||
);
|
);
|
||||||
|
|
||||||
let cstr_cell = wam.heap.allocate_cstr("string").unwrap();
|
let cstr_cell = wam.heap.allocate_cstr("string").unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, atom_as_cell!(atom!("atom")), cstr_cell),
|
wam.compare_term_test(atom_as_cell!(atom!("atom")), cstr_cell),
|
||||||
Some(Ordering::Less)
|
Some(Ordering::Less)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(
|
wam.compare_term_test(atom_as_cell!(atom!("atom")), atom_as_cell!(atom!("atom"))),
|
||||||
wam,
|
|
||||||
atom_as_cell!(atom!("atom")),
|
|
||||||
atom_as_cell!(atom!("atom"))
|
|
||||||
),
|
|
||||||
Some(Ordering::Equal)
|
Some(Ordering::Equal)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(
|
wam.compare_term_test(atom_as_cell!(atom!("atom")), atom_as_cell!(atom!("aaa"))),
|
||||||
wam,
|
|
||||||
atom_as_cell!(atom!("atom")),
|
|
||||||
atom_as_cell!(atom!("aaa"))
|
|
||||||
),
|
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(
|
wam.compare_term_test(fixnum_as_cell!(Fixnum::build_with(6)), heap_loc_as_cell!(1)),
|
||||||
wam,
|
|
||||||
fixnum_as_cell!(Fixnum::build_with(6)),
|
|
||||||
heap_loc_as_cell!(1)
|
|
||||||
),
|
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -644,12 +632,12 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(0)),
|
wam.compare_term_test(heap_loc_as_cell!(0), heap_loc_as_cell!(0)),
|
||||||
Some(Ordering::Equal)
|
Some(Ordering::Equal)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, heap_loc_as_cell!(0), atom_as_cell!(atom!("a"))),
|
wam.compare_term_test(heap_loc_as_cell!(0), atom_as_cell!(atom!("a"))),
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -676,23 +664,22 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, heap_loc_as_cell!(7), heap_loc_as_cell!(7)),
|
wam.compare_term_test(heap_loc_as_cell!(7), heap_loc_as_cell!(7)),
|
||||||
Some(Ordering::Equal)
|
Some(Ordering::Equal)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(7)),
|
wam.compare_term_test(heap_loc_as_cell!(0), heap_loc_as_cell!(7)),
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, empty_list_as_cell!(), heap_loc_as_cell!(7)),
|
wam.compare_term_test(empty_list_as_cell!(), heap_loc_as_cell!(7)),
|
||||||
Some(Ordering::Less)
|
Some(Ordering::Less)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(
|
wam.compare_term_test(
|
||||||
wam,
|
|
||||||
empty_list_as_cell!(),
|
empty_list_as_cell!(),
|
||||||
fixnum_as_cell!(Fixnum::build_with(1))
|
fixnum_as_cell!(Fixnum::build_with(1))
|
||||||
),
|
),
|
||||||
@@ -702,29 +689,29 @@ mod tests {
|
|||||||
let cstr_cell = wam.heap.allocate_cstr("string").unwrap();
|
let cstr_cell = wam.heap.allocate_cstr("string").unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, empty_list_as_cell!(), cstr_cell),
|
wam.compare_term_test(empty_list_as_cell!(), cstr_cell),
|
||||||
Some(Ordering::Less)
|
Some(Ordering::Less)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, empty_list_as_cell!(), atom_as_cell!(atom!("atom"))),
|
wam.compare_term_test(empty_list_as_cell!(), atom_as_cell!(atom!("atom"))),
|
||||||
Some(Ordering::Less)
|
Some(Ordering::Less)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, atom_as_cell!(atom!("atom")), empty_list_as_cell!()),
|
wam.compare_term_test(atom_as_cell!(atom!("atom")), empty_list_as_cell!()),
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
);
|
);
|
||||||
|
|
||||||
let one_p_one = HeapCellValue::from(float_alloc!(1.1, &mut wam.arena));
|
let one_p_one = HeapCellValue::from(float_alloc!(1.1, &mut wam.arena));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, one_p_one, fixnum_as_cell!(Fixnum::build_with(1))),
|
wam.compare_term_test(one_p_one, fixnum_as_cell!(Fixnum::build_with(1))),
|
||||||
Some(Ordering::Less)
|
Some(Ordering::Less)
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compare_term_test!(wam, fixnum_as_cell!(Fixnum::build_with(1)), one_p_one),
|
wam.compare_term_test(fixnum_as_cell!(Fixnum::build_with(1)), one_p_one),
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ use rand::{Rng, SeedableRng};
|
|||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
use fxhash::{FxBuildHasher, FxHasher};
|
use fxhash::{FxBuildHasher, FxHasher};
|
||||||
use indexmap::IndexSet;
|
use indexmap::*;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@@ -574,6 +574,53 @@ pub(crate) struct FindallCopyInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MachineState {
|
impl MachineState {
|
||||||
|
// determine whether two terms are variants, i.e. if there exists
|
||||||
|
// a bijection between their variable sets such that applying it
|
||||||
|
// to h1 produces h2 (ISO Prolog standard section 7.1.6.1).
|
||||||
|
// return true on failure and false on success.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn is_not_variant(&self) -> bool {
|
||||||
|
let h1 = self.registers[1];
|
||||||
|
let h2 = self.registers[2];
|
||||||
|
|
||||||
|
let mut a_to_b = IndexMap::with_hasher(FxBuildHasher::default());
|
||||||
|
let mut b_to_a = IndexMap::with_hasher(FxBuildHasher::default());
|
||||||
|
|
||||||
|
for term_pair in ParallelHeapIter::from(self, h1, h2) {
|
||||||
|
match term_pair {
|
||||||
|
TermPair::Vars(v1_offset, v2_offset) => {
|
||||||
|
match a_to_b.entry(v1_offset) {
|
||||||
|
indexmap::map::Entry::Occupied(stored_v2_offset) => {
|
||||||
|
if v2_offset != *stored_v2_offset.get() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indexmap::map::Entry::Vacant(entry) => {
|
||||||
|
entry.insert_entry(v2_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match b_to_a.entry(v2_offset) {
|
||||||
|
indexmap::map::Entry::Occupied(stored_v1_offset) => {
|
||||||
|
if v1_offset != *stored_v1_offset.get() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indexmap::map::Entry::Vacant(entry) => {
|
||||||
|
entry.insert_entry(v1_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TermPair::Less(..) => return true,
|
||||||
|
TermPair::Greater(..) => return true,
|
||||||
|
TermPair::Unordered(cell_1, cell_2) if cell_1 != cell_2 => return true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn copy_lifted_heap_from_offset(&mut self, offset: usize, lh_offset: usize) {
|
fn copy_lifted_heap_from_offset(&mut self, offset: usize, lh_offset: usize) {
|
||||||
let reserve_size = self.lifted_heap.cell_len() - lh_offset;
|
let reserve_size = self.lifted_heap.cell_len() - lh_offset;
|
||||||
let mut writer = step_or_resource_error!(self, self.heap.reserve(reserve_size));
|
let mut writer = step_or_resource_error!(self, self.heap.reserve(reserve_size));
|
||||||
|
|||||||
@@ -426,21 +426,6 @@ macro_rules! unify_with_occurs_check {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! compare_term_test {
|
|
||||||
($machine_st:expr, $e1:expr, $e2:expr) => {{
|
|
||||||
$machine_st.pdl.push($e2);
|
|
||||||
$machine_st.pdl.push($e1);
|
|
||||||
|
|
||||||
$machine_st.compare_term_test(VarComparison::Distinct)
|
|
||||||
}};
|
|
||||||
($machine_st:expr, $e1:expr, $e2:expr, $var_comparison:expr) => {{
|
|
||||||
$machine_st.pdl.push($e2);
|
|
||||||
$machine_st.pdl.push($e1);
|
|
||||||
|
|
||||||
$machine_st.compare_term_test($var_comparison)
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! step_or_resource_error {
|
macro_rules! step_or_resource_error {
|
||||||
($machine_st:expr, $val:expr) => {{
|
($machine_st:expr, $val:expr) => {{
|
||||||
match $val {
|
match $val {
|
||||||
|
|||||||
Reference in New Issue
Block a user