diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 16f37bcb..7b8be1f8 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -643,11 +643,6 @@ enum SystemClauseType { UnattributedVar, #[strum_discriminants(strum(props(Arity = "4", Name = "$get_db_refs")))] GetDBRefs, - #[strum_discriminants(strum(props( - Arity = "2", - Name = "$keysort_with_constant_var_ordering" - )))] - KeySortWithConstantVarOrdering, #[strum_discriminants(strum(props(Arity = "0", Name = "$inference_limit_exceeded")))] InferenceLimitExceeded, #[strum_discriminants(strum(props(Arity = "1", Name = "$argv")))] diff --git a/src/codegen.rs b/src/codegen.rs index c5a0c857..19d056d6 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -639,7 +639,10 @@ impl CodeGenerator { } }, InlinedClauseType::IsRational(..) => match terms[0] { - Term::Literal(_, Literal::Rational(_)) => { + Term::Literal( + _, + Literal::Rational(_) | Literal::Fixnum(_) | Literal::Integer(_), + ) => { instr!("$succeed") } Term::Var(ref vr, ref name) => { @@ -679,10 +682,13 @@ impl CodeGenerator { } }, InlinedClauseType::IsNumber(..) => match terms[0] { - Term::Literal(_, Literal::F64(..)) - | Term::Literal(_, Literal::Rational(_)) - | Term::Literal(_, Literal::Integer(_)) - | Term::Literal(_, Literal::Fixnum(_)) => { + Term::Literal( + _, + Literal::F64(..) + | Literal::Rational(_) + | Literal::Integer(_) + | Literal::Fixnum(_), + ) => { instr!("$succeed") } Term::Var(ref vr, ref name) => { @@ -988,20 +994,27 @@ impl CodeGenerator { self.marker.in_tail_position = false; self.marker.reset_contents(); } - ClauseItem::FirstBranch(num_branches) => { + ClauseItem::FirstBranch { + branch_num, + num_branches, + } => { branch_code_stack.add_new_branch_stack(); branch_code_stack.add_new_branch(); - self.marker.branch_stack.add_branch_stack(num_branches); + self.marker + .branch_stack + .add_branch_stack(branch_num.clone(), num_branches); self.marker.add_branch(); } - ClauseItem::NextBranch => { + ClauseItem::NextBranch { branch_num } => { branch_code_stack.add_new_branch(); self.marker.add_branch(); - self.marker.branch_stack.incr_current_branch(); + self.marker + .branch_stack + .incr_current_branch(branch_num.clone()); } - ClauseItem::BranchEnd(depth) => { + ClauseItem::BranchEnd { depth } => { if !clause_iter.in_tail_position() { let subsumed_hits = branch_code_stack.push_missing_vars(depth, &mut self.marker); diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 7fe37259..30fae204 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -1,6 +1,6 @@ use crate::allocator::*; use crate::codegen::SubsumedBranchHits; -use crate::forms::{GenContext, Level}; +use crate::forms::{BranchNumber, GenContext, Level}; use crate::instructions::*; use crate::machine::disjuncts::VarData; use crate::parser::ast::*; @@ -24,24 +24,26 @@ pub struct BranchOccurrences { pub shallow_safety: BitSet, // unset means safe, set means unsafe (after the branch merge) pub deep_safety: BitSet, pub num_branches: usize, - pub current_branch: usize, + pub current_branch_idx: usize, + pub current_branch_num: BranchNumber, pub subsumed_hits: SubsumedBranchHits, } impl BranchOccurrences { - fn new(num_branches: usize) -> Self { + fn new(current_branch_num: BranchNumber, num_branches: usize) -> Self { Self { hits: BranchHits::with_hasher(FxBuildHasher::default()), shallow_safety: BitSet::default(), deep_safety: BitSet::default(), num_branches, - current_branch: 0, + current_branch_idx: 0, + current_branch_num, subsumed_hits: SubsumedBranchHits::with_hasher(FxBuildHasher::default()), } } pub(crate) fn add_branch_occurrence(&mut self, var_num: usize) { - debug_assert!(self.current_branch < self.num_branches); + debug_assert!(self.current_branch_idx < self.num_branches); let num_branches = self.num_branches; let entry = self @@ -49,7 +51,7 @@ impl BranchOccurrences { .entry(var_num) .or_insert_with(|| BitVec::repeat(false, num_branches)); - entry.set(self.current_branch, true); + entry.set(self.current_branch_idx, true); self.subsumed_hits.insert(var_num); } } @@ -76,19 +78,6 @@ impl DerefMut for BranchStack { } impl BranchStack { - fn branch_subsumes(&self, branch: &BranchDesignator, sub_branch: &BranchDesignator) -> bool { - if branch.branch_stack_num < sub_branch.branch_stack_num { - if branch.branch_stack_num == 0 { - true - } else { - let idx = branch.branch_stack_num - 1; - self[idx].current_branch == branch.branch_num - } - } else { - branch == sub_branch - } - } - fn safety_unneeded_in_branch( &self, safety: &VarSafetyStatus, @@ -96,9 +85,9 @@ impl BranchStack { ) -> bool { match safety { VarSafetyStatus::Needed => false, - VarSafetyStatus::LocallyUnneeded(planter_branch) => { - self.branch_subsumes(planter_branch, branch) - } + VarSafetyStatus::LocallyUnneeded(planter_branch) => planter_branch + .branch_num + .has_as_subbranch(&branch.branch_num), VarSafetyStatus::GloballyUnneeded => true, } } @@ -109,27 +98,24 @@ impl BranchStack { } } - pub(crate) fn add_branch_stack(&mut self, num_branches: usize) { - self.push(BranchOccurrences::new(num_branches)); + pub(crate) fn add_branch_stack(&mut self, branch_num: BranchNumber, num_branches: usize) { + self.push(BranchOccurrences::new(branch_num, num_branches)); } pub(crate) fn current_branch_designator(&self) -> BranchDesignator { - let branch_stack_num = self.len(); let branch_num = self .last() - .map(|occurrences| occurrences.current_branch) - .unwrap_or(0); + .map(|occurrences| occurrences.current_branch_num.clone()) + .unwrap_or_else(|| BranchNumber::default()); - BranchDesignator { - branch_stack_num, - branch_num, - } + BranchDesignator { branch_num } } #[inline] - pub(crate) fn incr_current_branch(&mut self) { + pub(crate) fn incr_current_branch(&mut self, branch_num: BranchNumber) { let branch_occurrences = self.last_mut().unwrap(); - branch_occurrences.current_branch += 1; + branch_occurrences.current_branch_idx += 1; + branch_occurrences.current_branch_num = branch_num; } #[inline] @@ -235,12 +221,12 @@ impl DebrayAllocator { VarAlloc::Perm(_, allocation) => { let shallow_safety = VarSafetyStatus::needed_if( shallow_safety.contains(var_num), - branch_designator, + &branch_designator, ); let deep_safety = VarSafetyStatus::needed_if( deep_safety.contains(var_num), - branch_designator, + &branch_designator, ); if running_count < num_occurrences { @@ -531,11 +517,11 @@ impl DebrayAllocator { .. }, ) => { - *deep_safety = VarSafetyStatus::unneeded(branch_designator); - *shallow_safety = VarSafetyStatus::unneeded(branch_designator); + *deep_safety = VarSafetyStatus::unneeded(&branch_designator); + *shallow_safety = VarSafetyStatus::unneeded(&branch_designator); } VarAlloc::Temp { safety, .. } => { - *safety = VarSafetyStatus::unneeded(branch_designator); + *safety = VarSafetyStatus::unneeded(&branch_designator); } _ => { unreachable!() @@ -557,8 +543,8 @@ impl DebrayAllocator { ) => { // GetVariable in head chunk is considered safe. if lvl == Level::Deep { - *deep_safety = VarSafetyStatus::unneeded(branch_designator); - *shallow_safety = VarSafetyStatus::unneeded(branch_designator); + *deep_safety = VarSafetyStatus::unneeded(&branch_designator); + *shallow_safety = VarSafetyStatus::unneeded(&branch_designator); } else if term_loc == GenContext::Head { *shallow_safety = VarSafetyStatus::GloballyUnneeded; } else if let Some(&temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c) { @@ -605,7 +591,7 @@ impl DebrayAllocator { { Target::argument_to_value(r, arg_c) } else { - *shallow_safety = VarSafetyStatus::unneeded(branch_designator); + *shallow_safety = VarSafetyStatus::unneeded(&branch_designator); Target::unsafe_argument_to_value(r, arg_c) } } @@ -640,7 +626,7 @@ impl DebrayAllocator { { Target::subterm_to_value(r) } else { - *deep_safety = VarSafetyStatus::unneeded(branch_designator); + *deep_safety = VarSafetyStatus::unneeded(&branch_designator); Target::unsafe_subterm_to_value(r) } } @@ -651,7 +637,7 @@ impl DebrayAllocator { { Target::subterm_to_value(r) } else { - *safety = VarSafetyStatus::unneeded(branch_designator); + *safety = VarSafetyStatus::unneeded(&branch_designator); Target::unsafe_subterm_to_value(r) } } diff --git a/src/forms.rs b/src/forms.rs index ae9b829d..310228e4 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -18,9 +18,11 @@ use indexmap::{IndexMap, IndexSet}; use ordered_float::OrderedFloat; use std::cell::Cell; +use std::cmp::Ordering; use std::collections::VecDeque; use std::convert::TryFrom; use std::fmt; +use std::hash::{Hash, Hasher}; use std::ops::{AddAssign, Deref, DerefMut}; use std::path::PathBuf; @@ -42,12 +44,6 @@ impl AppendOrPrepend { } } -#[derive(Debug, Clone, Copy)] -pub enum VarComparison { - Indistinct, - Distinct, -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Level { Deep, @@ -128,10 +124,82 @@ impl ChunkType { } } +#[derive(Debug, Clone)] //, PartialOrd, PartialEq, Eq, Hash)] +pub(crate) struct BranchNumber { + pub(crate) branch_num: Rational, + pub(crate) delta: Rational, +} + +impl Default for BranchNumber { + fn default() -> Self { + Self { + branch_num: Rational::from(0), + delta: Rational::from(1u64 << 31), + } + } +} + +impl PartialEq for BranchNumber { + #[inline] + fn eq(&self, rhs: &BranchNumber) -> bool { + self.branch_num == rhs.branch_num + } +} + +impl Eq for BranchNumber {} + +impl Hash for BranchNumber { + #[inline(always)] + fn hash(&self, hasher: &mut H) { + self.branch_num.hash(hasher) + } +} + +impl PartialOrd for BranchNumber { + #[inline] + fn partial_cmp(&self, rhs: &BranchNumber) -> Option { + self.branch_num.partial_cmp(&rhs.branch_num) + } +} + +impl BranchNumber { + pub(crate) fn has_as_subbranch(&self, other: &Self) -> bool { + other.delta <= self.delta + && other.branch_num >= self.branch_num + && other.branch_num < &self.branch_num + &self.delta + } + + pub(crate) fn split(&self) -> BranchNumber { + BranchNumber { + branch_num: self.branch_num.clone() + &self.delta / Rational::from(2), + delta: &self.delta / Rational::from(4), + } + } + + pub(crate) fn incr_by_delta(&self) -> BranchNumber { + BranchNumber { + branch_num: self.branch_num.clone() + &self.delta, + delta: self.delta.clone(), + } + } + + pub(crate) fn halve_delta(&self) -> BranchNumber { + BranchNumber { + branch_num: self.branch_num.clone(), + delta: &self.delta / Rational::from(2), + } + } +} + #[derive(Debug)] pub enum ChunkedTerms { - Branch(Vec>), - Chunk { terms: VecDeque }, + Branch { + branch_nums: Vec, + arms: Vec>, + }, + Chunk { + terms: VecDeque, + }, } #[derive(Debug)] @@ -165,21 +233,22 @@ impl ChunkedTermVec { } pub fn reserve_branch(&mut self, capacity: usize) { - self.chunk_vec - .push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity))); + self.chunk_vec.push_back(ChunkedTerms::Branch { + branch_nums: Vec::with_capacity(capacity), + arms: Vec::with_capacity(capacity), + }); } #[inline] pub fn add_chunk(&mut self) { - let chunk = ChunkedTerms::Chunk { + self.chunk_vec.push_back(ChunkedTerms::Chunk { terms: VecDeque::from(vec![]), - }; - self.chunk_vec.push_back(chunk); + }); } pub fn push_chunk_term(&mut self, term: QueryTerm) { match self.chunk_vec.back_mut() { - Some(ChunkedTerms::Branch(_)) => { + Some(ChunkedTerms::Branch { .. }) => { let chunk = ChunkedTerms::Chunk { terms: VecDeque::from(vec![term]), }; diff --git a/src/heap_iter.rs b/src/heap_iter.rs index 70314082..903fcbc2 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -1,21 +1,375 @@ #![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 +use crate::arena::Arena; +use crate::forms::Number; #[cfg(test)] pub(crate) use crate::machine::gc::StacklessPreOrderHeapIter; use crate::atom_table::*; use crate::machine::cycle_detection::*; use crate::machine::heap::*; +use crate::machine::machine_indices::TermOrderCategory; use crate::machine::stack::*; +use crate::parser::lexer::MachineState; use crate::types::*; use core::marker::PhantomData; +use fxhash::FxBuildHasher; +use indexmap::IndexSet; use scryer_modular_bitfield::prelude::*; +use std::cmp::Ordering; use std::ops::Deref; 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, + 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)] +#[allow(dead_code)] +pub enum TermPair { + Vars(usize, usize), + Less(HeapCellValue, HeapCellValue), + Greater(HeapCellValue, HeapCellValue), + Unordered(HeapCellValue, HeapCellValue), +} + +impl ParallelHeapIter<'_> { + #[inline] + fn parallel_cmp( + &mut self, + v1: Cmp, + v2: Cmp, + h1: HeapCellValue, + h2: HeapCellValue, + ) -> Option { + 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 { + 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); + + 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)] pub fn eager_stackful_preorder_iter( heap: &mut Heap, @@ -35,7 +389,7 @@ pub struct EagerStackfulPreOrderHeapIter<'a> { start_value: HeapCellValue, iter_stack: Vec, mark_phase: bool, - heap: &'a mut Heap, + pub heap: &'a mut Heap, } impl<'a> Drop for EagerStackfulPreOrderHeapIter<'a> { diff --git a/src/instructions.rs b/src/instructions.rs index 076c2672..f029e463 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -726,7 +726,6 @@ impl Instruction { | &Instruction::CallDeleteAllAttributesFromVar | &Instruction::CallUnattributedVar | &Instruction::CallGetDBRefs - | &Instruction::CallKeySortWithConstantVarOrdering | &Instruction::CallInferenceLimitExceeded | &Instruction::CallFetchGlobalVar | &Instruction::CallFirstStream @@ -986,7 +985,6 @@ impl Instruction { | &Instruction::ExecuteDeleteAllAttributesFromVar | &Instruction::ExecuteUnattributedVar | &Instruction::ExecuteGetDBRefs - | &Instruction::ExecuteKeySortWithConstantVarOrdering | &Instruction::ExecuteInferenceLimitExceeded | &Instruction::ExecuteFetchGlobalVar | &Instruction::ExecuteFirstStream diff --git a/src/iterators.rs b/src/iterators.rs index e3a2ccbd..0aa7bd38 100644 --- a/src/iterators.rs +++ b/src/iterators.rs @@ -319,15 +319,28 @@ pub(crate) fn breadth_first_iter( #[derive(Debug, Copy, Clone)] enum ClauseIteratorState<'a> { RemainingChunks(&'a VecDeque, usize), - RemainingBranches(&'a Vec>, usize), + RemainingBranches( + &'a Vec, + &'a Vec>, + usize, + ), } #[derive(Debug, Clone)] pub(crate) enum ClauseItem<'a> { - FirstBranch(usize), - NextBranch, - BranchEnd(usize), - Chunk { terms: &'a VecDeque }, + FirstBranch { + branch_num: &'a BranchNumber, + num_branches: usize, + }, + NextBranch { + branch_num: &'a BranchNumber, + }, + BranchEnd { + depth: usize, + }, + Chunk { + terms: &'a VecDeque, + }, } #[derive(Debug)] @@ -338,8 +351,8 @@ pub(crate) struct ClauseIterator<'a> { fn state_from_chunked_terms(chunk_vec: &VecDeque) -> ClauseIteratorState<'_> { if chunk_vec.len() == 1 { - if let Some(ChunkedTerms::Branch(ref branches)) = chunk_vec.front() { - return ClauseIteratorState::RemainingBranches(branches, 0); + if let Some(ChunkedTerms::Branch { branch_nums, arms }) = chunk_vec.front() { + return ClauseIteratorState::RemainingBranches(branch_nums, arms, 0); } } @@ -370,7 +383,9 @@ impl<'a> ClauseIterator<'a> { while let Some(state) = self.state_stack.pop() { match state { - ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => { + ClauseIteratorState::RemainingBranches(_branch_nums, terms, focus) + if terms.len() == focus => + { depth += 1; } _ => { @@ -399,9 +414,9 @@ impl<'a> Iterator for ClauseIterator<'a> { } match &chunks[focus] { - ChunkedTerms::Branch(branches) => { + ChunkedTerms::Branch { branch_nums, arms } => { self.state_stack - .push(ClauseIteratorState::RemainingBranches(branches, 0)); + .push(ClauseIteratorState::RemainingBranches(branch_nums, arms, 0)); } ChunkedTerms::Chunk { ref terms } => { return Some(ClauseItem::Chunk { terms }); @@ -411,11 +426,15 @@ impl<'a> Iterator for ClauseIterator<'a> { ClauseIteratorState::RemainingChunks(chunks, focus) => { debug_assert_eq!(chunks.len(), focus); } - ClauseIteratorState::RemainingBranches(branches, focus) + ClauseIteratorState::RemainingBranches(branch_nums, branches, focus) if focus < branches.len() => { self.state_stack - .push(ClauseIteratorState::RemainingBranches(branches, focus + 1)); + .push(ClauseIteratorState::RemainingBranches( + branch_nums, + branches, + focus + 1, + )); let state = state_from_chunked_terms(&branches[focus]); if let ClauseIteratorState::RemainingChunks(..) = &state { @@ -425,14 +444,21 @@ impl<'a> Iterator for ClauseIterator<'a> { self.state_stack.push(state); return if focus == 0 { - Some(ClauseItem::FirstBranch(branches.len())) + Some(ClauseItem::FirstBranch { + branch_num: &branch_nums[0], + num_branches: branches.len(), + }) } else { - Some(ClauseItem::NextBranch) + Some(ClauseItem::NextBranch { + branch_num: &branch_nums[focus], + }) }; } - ClauseIteratorState::RemainingBranches(branches, focus) => { + ClauseIteratorState::RemainingBranches(_branch_nums, branches, focus) => { debug_assert_eq!(branches.len(), focus); - return Some(ClauseItem::BranchEnd(self.branch_end_depth())); + return Some(ClauseItem::BranchEnd { + depth: self.branch_end_depth(), + }); } } } diff --git a/src/lib/builtins.pl b/src/lib/builtins.pl index 76a53420..65c829a5 100644 --- a/src/lib/builtins.pl +++ b/src/lib/builtins.pl @@ -944,65 +944,6 @@ findall(Template, Goal, Solutions0, Solutions1) :- builtins:findall_cleanup(LhLength, Error) ). -:- non_counted_backtracking set_difference/3. - -set_difference([X|Xs], [Y|Ys], Zs) :- - X == Y, !, set_difference(Xs, [Y|Ys], Zs). -set_difference([X|Xs], [Y|Ys], [X|Zs]) :- - X @< Y, !, set_difference(Xs, [Y|Ys], Zs). -set_difference([X|Xs], [Y|Ys], Zs) :- - X @> Y, !, set_difference([X|Xs], Ys, Zs). -set_difference([], _, []) :- !. -set_difference(Xs, [], Xs). - - -% variant/2 checks whether X is a variant of Y per the definition in -% 7.1.6.1 of the ISO standard. - -:- non_counted_backtracking variant/4. - -variant(X,Y,VPs,VPs0) :- - ( var(X) -> - var(Y), - VPs = [X-Y|VPs0] - ; var(Y) -> - false - ; X =.. [FX | XArgs], - Y =.. [FX | YArgs], - lists:foldl('$call'(builtins:variant), XArgs, YArgs, VPs, VPs0) - ). - -:- non_counted_backtracking variant/2. - -singleton([_]). - -variant(X, Y) :- - variant(X,Y, VPs, []), - keysort(VPs, SVPs), - pairs:group_pairs_by_key(SVPs, SVPKs), - pairs:pairs_values(SVPKs, Vals), - lists:maplist('$call'(builtins:term_variables), Vals, Vs), - lists:maplist('$call'(builtins:singleton), Vs), - term_variables(Vs, YVars), - lists:length(SVPKs, N), - lists:length(YVars, N). - - -:- non_counted_backtracking group_by_variant/4. - -group_by_variant([V2-S2 | Pairs], V1-S1, [S2 | Solutions], Pairs0) :- - variant(V1, V2), - !, - V1 = V2, - group_by_variant(Pairs, V2-S2, Solutions, Pairs0). -group_by_variant(Pairs, _, [], Pairs). - -:- non_counted_backtracking group_by_variants/2. - -group_by_variants([V-S|Pairs], [V-Solution|Solutions]) :- - group_by_variant([V-S|Pairs], V-S, Solution, Pairs0), - group_by_variants(Pairs0, Solutions). -group_by_variants([], []). :- non_counted_backtracking iterate_variants/3. @@ -1035,9 +976,7 @@ findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses) ( Goal1 = _ ^ _ ) -> rightmost_power(Goal1, Goal2, ExistentialVars0), term_variables(ExistentialVars0, ExistentialVars), - sort(Witnesses0, Witnesses1), - sort(ExistentialVars, ExistentialVars1), - set_difference(Witnesses1, ExistentialVars1, Witnesses), + lists:append(Witnesses0, Witnesses, ExistentialVars), expand_goal(M:Goal2, M, Goal3), findall(Witnesses-Template, Goal3, PairedSolutions) ; Witnesses = Witnesses0, @@ -1045,6 +984,34 @@ findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses) ). +:- non_counted_backtracking split_by_variant/4. + +:- non_counted_backtracking split_by_variant/3. + +:- non_counted_backtracking unify_variant_variables/2. + +split_by_variant([V2-S2 | Pairs], V1-S1, Solutions, Rest) :- + ( V1 == V2 -> + Solutions = [S2 | Solutions1], + split_by_variant(Pairs, V1-S1, Solutions1, Rest) + ; Solutions = [], + Rest = [V2-S2 | Pairs] + ). +split_by_variant([], _, [], []). + +split_by_variant([V-S|Pairs], Ws, Solutions) :- + split_by_variant(Pairs, V-S, Solutions0, Rest), + ( Rest == [] -> V = Ws, Solutions = [S|Solutions0] + ; V = Ws, Solutions = [S|Solutions0] + ; split_by_variant(Rest, Ws, Solutions) + ). + +unify_variant_variables([], _Dict). +unify_variant_variables([V-_S|Pairs], Dict) :- + term_variables(V, VVars), + lists:append(VVars, _, Dict), + unify_variant_variables(Pairs, Dict). + :- meta_predicate(bagof(?, 0, ?)). :- non_counted_backtracking bagof/3. @@ -1074,22 +1041,10 @@ bagof(Template, Goal, Solution) :- term_variables(Goal, GoalVars), term_variables(TemplateVars+GoalVars, TGVs), lists:append(TemplateVars, Witnesses0, TGVs), - findall_with_existential(Template, Goal, PairedSolutions0, Witnesses0, Witnesses), - keysort(PairedSolutions0, PairedSolutions), - group_by_variants(PairedSolutions, GroupedSolutions), - iterate_variants(GroupedSolutions, Witnesses, Solution). - -:- non_counted_backtracking iterate_variants_and_sort/3. - -iterate_variants_and_sort([V-Solution0|GroupSolutions], V, Solution) :- - sort(Solution0, Solution1), - Solution1 = Solution, - ( GroupSolutions == [] -> ! - ; true - ). -iterate_variants_and_sort([_|GroupSolutions], Ws, Solution) :- - iterate_variants_and_sort(GroupSolutions, Ws, Solution). - + findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses), + unify_variant_variables(PairedSolutions, _Dict), + keysort(PairedSolutions, PairedSolutions1), + split_by_variant(PairedSolutions1, Witnesses, Solution). :- meta_predicate(setof(?, 0, ?)). @@ -1112,10 +1067,10 @@ setof(Template, Goal, Solution) :- term_variables(Goal, GoalVars), term_variables(TemplateVars+GoalVars, TGVs), lists:append(TemplateVars, Witnesses0, TGVs), - findall_with_existential(Template, Goal, PairedSolutions0, Witnesses0, Witnesses), - '$keysort_with_constant_var_ordering'(PairedSolutions0, PairedSolutions), % see 7.2.1 - group_by_variants(PairedSolutions, GroupedSolutions), - iterate_variants_and_sort(GroupedSolutions, Witnesses, Solution). + findall_with_existential(Template, Goal, PairedSolutions, Witnesses0, Witnesses), + unify_variant_variables(PairedSolutions, _Dict), + sort(PairedSolutions, PairedSolutions1), + split_by_variant(PairedSolutions1, Witnesses, Solution). % Clause retrieval and information. diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index fdedabcc..6b822b95 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -103,9 +103,8 @@ impl MachineState { .collect() }; - attr_vars.sort_unstable_by(|a1, a2| { - compare_term_test!(self, *a1, *a2).unwrap_or(Ordering::Less) - }); + attr_vars + .sort_unstable_by(|a1, a2| self.compare_term_test(*a1, *a2).unwrap_or(Ordering::Less)); attr_vars.dedup(); attr_vars diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 4ecac7bc..09eec4a1 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -6,79 +6,16 @@ use crate::machine::loader::*; use crate::machine::machine_errors::CompilationError; use crate::machine::preprocessor::*; use crate::parser::ast::*; -use crate::parser::dashu::Rational; use crate::variable_records::*; use dashu::Integer; use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; -use std::cmp::Ordering; use std::collections::VecDeque; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::ops::{Deref, DerefMut}; -#[derive(Debug, Clone)] //, PartialOrd, PartialEq, Eq, Hash)] -pub struct BranchNumber { - branch_num: Rational, - delta: Rational, -} - -impl Default for BranchNumber { - fn default() -> Self { - Self { - branch_num: Rational::from(1u64 << 63), - delta: Rational::from(1), - } - } -} - -impl PartialEq for BranchNumber { - #[inline] - fn eq(&self, rhs: &BranchNumber) -> bool { - self.branch_num == rhs.branch_num - } -} - -impl Eq for BranchNumber {} - -impl Hash for BranchNumber { - #[inline(always)] - fn hash(&self, hasher: &mut H) { - self.branch_num.hash(hasher) - } -} - -impl PartialOrd for BranchNumber { - #[inline] - fn partial_cmp(&self, rhs: &BranchNumber) -> Option { - self.branch_num.partial_cmp(&rhs.branch_num) - } -} - -impl BranchNumber { - fn split(&self) -> BranchNumber { - BranchNumber { - branch_num: self.branch_num.clone() + &self.delta / Rational::from(2), - delta: &self.delta / Rational::from(4), - } - } - - fn incr_by_delta(&self) -> BranchNumber { - BranchNumber { - branch_num: self.branch_num.clone() + &self.delta, - delta: self.delta.clone(), - } - } - - fn halve_delta(&self) -> BranchNumber { - BranchNumber { - branch_num: self.branch_num.clone(), - delta: &self.delta / Rational::from(2), - } - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct VarInfo { var_ptr: VarPtr, @@ -140,12 +77,13 @@ pub struct ClassifyInfo { } enum TraversalState { - // construct a QueryTerm::Branch with number of disjuncts, reset - // the chunk type to that of the chunk preceding the disjunct and the chunk_num. + // pop the latest branch number from the root set and use it to construct a QueryTerm::Branch + // with number of disjuncts, reset the chunk type to that of the chunk preceding the disjunct + // and the chunk_num. BuildDisjunct(usize), + BuildFinalDisjunct(usize), // add the last disjunct to a QueryTerm::Branch, continuing from // where it leaves off. - BuildFinalDisjunct(usize), Fail, GetCutPoint { var_num: usize, prev_b: bool }, Cut { var_num: usize, is_global: bool }, @@ -154,7 +92,6 @@ enum TraversalState { Term(Term), OverrideGlobalCutVar(usize), ResetGlobalCutVarOverride(Option), - RemoveBranchNum, // pop the current_branch_num and from the root set. AddBranchNum(BranchNumber), // set current_branch_num, add it to the root set RepBranchNum(BranchNumber), // replace current_branch_num and the latest in the root set } @@ -199,7 +136,7 @@ impl VarData { VarAlloc::Perm(0, PermVarAllocation::Pending); match build_stack.front_mut() { - Some(ChunkedTerms::Branch(_)) => { + Some(ChunkedTerms::Branch { .. }) => { build_stack.push_front(ChunkedTerms::Chunk { terms: VecDeque::from(vec![term]), }); @@ -232,11 +169,16 @@ fn merge_branch_seq(branches: impl Iterator) -> BranchInfo { branch_info } -fn flatten_into_disjunct(build_stack: &mut ChunkedTermVec, preceding_len: usize) { +fn flatten_into_disjunct( + build_stack: &mut ChunkedTermVec, + branch_num: BranchNumber, + preceding_len: usize, +) { let branch_vec = build_stack.drain(preceding_len + 1..).collect(); - if let ChunkedTerms::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] { - disjuncts.push(branch_vec); + if let ChunkedTerms::Branch { branch_nums, arms } = &mut build_stack[preceding_len] { + branch_nums.push(branch_num); + arms.push(branch_vec); } else { unreachable!(); } @@ -477,9 +419,6 @@ impl VariableClassifier { self.root_set.insert(branch_num.clone()); self.current_branch_num = branch_num; } - TraversalState::RemoveBranchNum => { - self.root_set.pop(); - } TraversalState::RepBranchNum(branch_num) => { self.root_set.pop(); self.root_set.insert(branch_num.clone()); @@ -488,14 +427,10 @@ impl VariableClassifier { TraversalState::ResetCallPolicy(call_policy) => { self.call_policy = call_policy; } - TraversalState::BuildDisjunct(preceding_len) => { - flatten_into_disjunct(&mut build_stack, preceding_len); - - self.current_chunk_type = ChunkType::Mid; - self.current_chunk_num += 1; - } - TraversalState::BuildFinalDisjunct(preceding_len) => { - flatten_into_disjunct(&mut build_stack, preceding_len); + TraversalState::BuildDisjunct(preceding_len) + | TraversalState::BuildFinalDisjunct(preceding_len) => { + let branch_num = self.root_set.pop().unwrap(); + flatten_into_disjunct(&mut build_stack, branch_num, preceding_len); self.current_chunk_type = ChunkType::Mid; self.current_chunk_num += 1; @@ -636,7 +571,6 @@ impl VariableClassifier { for (term, branch_num) in iter.rev() { state_stack.push(TraversalState::BuildDisjunct(build_stack_len)); - state_stack.push(TraversalState::RemoveBranchNum); state_stack.push(TraversalState::Term(term)); state_stack.push(TraversalState::AddBranchNum(branch_num)); } @@ -655,23 +589,18 @@ impl VariableClassifier { let then_term = terms.pop().unwrap(); let if_term = terms.pop().unwrap(); - let prev_b = if matches!( - state_stack.last(), - Some(TraversalState::RemoveBranchNum) - ) { - // check if the second-to-last element - // is a regular BuildDisjunct, as we - // don't want to add GetPrevLevel in - // case of a TrustMe. - match state_stack.iter().rev().nth(1) { - Some(&TraversalState::BuildDisjunct(preceding_len)) => { - preceding_len + 1 == build_stack.len() - } - _ => false, - } - } else { - false - }; + let prev_b = + if let Some(&TraversalState::BuildDisjunct(preceding_len)) = + state_stack.last() + { + // check if the second-to-last element + // is a regular BuildDisjunct, as we + // don't want to add GetPrevLevel in + // case of a TrustMe. + preceding_len + 1 == build_stack.len() + } else { + false + }; state_stack.push(TraversalState::Term(then_term)); state_stack.push(TraversalState::Cut { @@ -690,14 +619,21 @@ impl VariableClassifier { let not_term = terms.pop().unwrap(); let build_stack_len = build_stack.len(); + let first_branch_num = self.current_branch_num.split(); + let second_branch_num = first_branch_num.incr_by_delta(); + build_stack.reserve_branch(2); + state_stack.push(TraversalState::RepBranchNum( + self.current_branch_num.halve_delta(), + )); state_stack.push(TraversalState::BuildFinalDisjunct(build_stack_len)); state_stack.push(TraversalState::Term(Term::Clause( Cell::default(), atom!("$succeed"), vec![], ))); + state_stack.push(TraversalState::AddBranchNum(second_branch_num)); state_stack.push(TraversalState::BuildDisjunct(build_stack_len)); state_stack.push(TraversalState::Fail); state_stack.push(TraversalState::CutPrev(self.var_num)); @@ -710,6 +646,7 @@ impl VariableClassifier { var_num: self.var_num, prev_b: false, }); + state_stack.push(TraversalState::AddBranchNum(first_branch_num)); self.current_chunk_type = ChunkType::Mid; self.current_chunk_num += 1; diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index f67b0df2..98a47309 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -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) => { atom!(">") } @@ -151,15 +151,12 @@ impl MachineState { let stub_gen = || functor_stub(atom!("sort"), 2); let mut list = self.try_from_list(self.registers[1], stub_gen)?; - list.sort_unstable_by(|v1, v2| { - compare_term_test!(self, *v1, *v2).unwrap_or(Ordering::Less) - }); - - list.dedup_by(|v1, v2| compare_term_test!(self, *v1, *v2) == Some(Ordering::Equal)); + list.sort_unstable_by(|v1, v2| self.compare_term_test(*v1, *v2).unwrap_or(Ordering::Less)); + list.dedup_by(|v1, v2| self.compare_term_test(*v1, *v2) == Some(Ordering::Equal)); let heap_addr = resource_error_call_result!( self, - sized_iter_to_heap_list(&mut self.heap, list.len(), list.into_iter(),) + sized_iter_to_heap_list(&mut self.heap, list.len(), list.into_iter()) ); let target_addr = self.registers[2]; @@ -167,7 +164,7 @@ impl MachineState { Ok(()) } - fn keysort(&mut self, var_comparison: VarComparison) -> CallResult { + fn keysort(&mut self) -> CallResult { self.check_keysort_errors()?; let stub_gen = || functor_stub(atom!("keysort"), 2); @@ -176,13 +173,11 @@ impl MachineState { let mut key_pairs = Vec::with_capacity(list.len()); for val in list { - let key = self.project_onto_key(val)?; + let (key, _) = self.key_val_pair(val)?; key_pairs.push((key, val)); } - key_pairs.sort_by(|a1, a2| { - compare_term_test!(self, a1.0, a2.0, var_comparison).unwrap_or(Ordering::Less) - }); + key_pairs.sort_by(|a1, a2| self.compare_term_test(a1.0, a2.0).unwrap_or(Ordering::Less)); let heap_addr = resource_error_call_result!( self, @@ -2034,8 +2029,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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; } else { self.machine_st.backtrack(); @@ -2045,8 +2039,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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; } else { self.machine_st.backtrack(); @@ -2056,7 +2049,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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; } else { self.machine_st.backtrack(); @@ -2066,7 +2059,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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; } else { self.machine_st.backtrack(); @@ -2076,7 +2069,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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) => { self.machine_st.p += 1; } @@ -2089,7 +2082,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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) => { self.machine_st.p = self.machine_st.cp; } @@ -2102,7 +2095,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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) => { self.machine_st.p += 1; } @@ -2115,7 +2108,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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) => { self.machine_st.p = self.machine_st.cp; } @@ -2188,7 +2181,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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(); } else { self.machine_st.p += 1; @@ -2198,7 +2191,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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(); } else { 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); } &Instruction::DefaultCallKeySort => { - try_or_throw!( - self.machine_st, - self.machine_st.keysort(VarComparison::Distinct), - continue - ); + try_or_throw!(self.machine_st, self.machine_st.keysort(), continue); step_or_fail!(self.machine_st, self.machine_st.p += 1); } &Instruction::DefaultExecuteKeySort => { - try_or_throw!( - self.machine_st, - self.machine_st.keysort(VarComparison::Distinct), - continue - ); + try_or_throw!(self.machine_st, self.machine_st.keysort(), continue); if self.machine_st.fail { self.machine_st.backtrack(); @@ -2323,8 +2308,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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); self.machine_st.p += 1; } else { @@ -2335,8 +2319,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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); self.machine_st.p = self.machine_st.cp; } else { @@ -2347,7 +2330,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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); self.machine_st.p += 1; } else { @@ -2358,7 +2341,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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); self.machine_st.p = self.machine_st.cp; } else { @@ -2369,7 +2352,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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) => { increment_call_count!(self.machine_st); self.machine_st.p += 1; @@ -2383,7 +2366,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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) => { increment_call_count!(self.machine_st); self.machine_st.p = self.machine_st.cp; @@ -2397,7 +2380,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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) => { increment_call_count!(self.machine_st); self.machine_st.p += 1; @@ -2411,7 +2394,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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) => { increment_call_count!(self.machine_st); self.machine_st.p = self.machine_st.cp; @@ -2503,7 +2486,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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(); } else { increment_call_count!(self.machine_st); @@ -2514,7 +2497,7 @@ impl Machine { let a1 = self.machine_st.registers[1]; 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(); } else { increment_call_count!(self.machine_st); @@ -2542,11 +2525,7 @@ impl Machine { } } &Instruction::CallKeySort => { - try_or_throw!( - self.machine_st, - self.machine_st.keysort(VarComparison::Distinct), - continue - ); + try_or_throw!(self.machine_st, self.machine_st.keysort(), continue); if self.machine_st.fail { self.machine_st.backtrack(); @@ -2556,39 +2535,7 @@ impl Machine { } } &Instruction::ExecuteKeySort => { - try_or_throw!( - self.machine_st, - self.machine_st.keysort(VarComparison::Distinct), - continue - ); - - if self.machine_st.fail { - self.machine_st.backtrack(); - } else { - increment_call_count!(self.machine_st); - self.machine_st.p = self.machine_st.cp; - } - } - &Instruction::CallKeySortWithConstantVarOrdering => { - try_or_throw!( - self.machine_st, - self.machine_st.keysort(VarComparison::Indistinct), - continue - ); - - if self.machine_st.fail { - self.machine_st.backtrack(); - } else { - increment_call_count!(self.machine_st); - self.machine_st.p += 1; - } - } - &Instruction::ExecuteKeySortWithConstantVarOrdering => { - try_or_throw!( - self.machine_st, - self.machine_st.keysort(VarComparison::Indistinct), - continue - ); + try_or_throw!(self.machine_st, self.machine_st.keysort(), continue); if self.machine_st.fail { self.machine_st.backtrack(); diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 7b777ae6..36a4772c 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -7,7 +7,6 @@ use crate::machine::copier::*; use crate::machine::heap::AllocError; use crate::machine::heap::*; use crate::machine::machine_errors::*; -use crate::machine::machine_indices::*; use crate::machine::machine_state::*; use crate::machine::partial_string::*; use crate::machine::stack::*; @@ -17,8 +16,6 @@ use crate::parser::ast::*; use crate::parser::dashu::{Integer, Rational}; use crate::types::*; -use indexmap::IndexSet; - use std::cmp::Ordering; use std::convert::TryFrom; @@ -380,347 +377,6 @@ impl MachineState { } } - pub fn compare_term_test(&mut self, var_comparison: VarComparison) -> Option { - 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( &mut self, goal: HeapCellValue, @@ -891,16 +547,32 @@ impl MachineState { } // 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 { return false; } - compare_term_test!(self, h1, h2) - .map(|o| o != Ordering::Equal) + self.compare_term_test(h1, h2) + .map(|o| !o.is_eq()) .unwrap_or(true) } + pub fn compare_term_test(&self, h1: HeapCellValue, h2: HeapCellValue) -> Option { + 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)] fn try_functor_compound_case(&mut self, name: Atom, arity: usize) { self.try_functor_unify_components(atom_as_cell!(name), arity); @@ -1262,7 +934,10 @@ impl MachineState { } // see 8.4.4.3 of Draft Technical Corrigendum 2 for an error guide. - pub fn project_onto_key(&mut self, value: HeapCellValue) -> Result { + pub fn key_val_pair( + &mut self, + value: HeapCellValue, + ) -> Result<(HeapCellValue, HeapCellValue), MachineStub> { let stub_gen = || functor_stub(atom!("keysort"), 2); let store_v = self.store(self.deref(value)); @@ -1276,7 +951,7 @@ impl MachineState { let (name, arity) = cell_as_atom_cell!(self.heap[s]).get_name_and_arity(); if name == atom!("-") && arity == 2 { - Ok(heap_loc_as_cell!(s + 1)) + Ok((heap_loc_as_cell!(s+1), heap_loc_as_cell!(s+2))) } else { let err = self.type_error(ValidType::Pair, self.heap[s]); Err(self.error_form(err, stub_gen())) diff --git a/src/machine/mock_wam.rs b/src/machine/mock_wam.rs index 7fcc5613..b871e0fc 100644 --- a/src/machine/mock_wam.rs +++ b/src/machine/mock_wam.rs @@ -581,56 +581,44 @@ mod tests { }); 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) ); 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) ); 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) ); 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) ); let cstr_cell = wam.heap.allocate_cstr("string").unwrap(); 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) ); assert_eq!( - compare_term_test!( - wam, - atom_as_cell!(atom!("atom")), - atom_as_cell!(atom!("atom")) - ), + wam.compare_term_test(atom_as_cell!(atom!("atom")), atom_as_cell!(atom!("atom"))), Some(Ordering::Equal) ); assert_eq!( - compare_term_test!( - wam, - atom_as_cell!(atom!("atom")), - atom_as_cell!(atom!("aaa")) - ), + wam.compare_term_test(atom_as_cell!(atom!("atom")), atom_as_cell!(atom!("aaa"))), Some(Ordering::Greater) ); assert_eq!( - compare_term_test!( - wam, - fixnum_as_cell!(Fixnum::build_with(6)), - heap_loc_as_cell!(1) - ), + wam.compare_term_test(fixnum_as_cell!(Fixnum::build_with(6)), heap_loc_as_cell!(1)), Some(Ordering::Greater) ); @@ -644,12 +632,12 @@ mod tests { }); assert_eq!( - compare_term_test!(wam, heap_loc_as_cell!(0), heap_loc_as_cell!(0)), + wam.compare_term_test(str_loc_as_cell!(0), str_loc_as_cell!(0)), Some(Ordering::Equal) ); assert_eq!( - compare_term_test!(wam, heap_loc_as_cell!(0), atom_as_cell!(atom!("a"))), + wam.compare_term_test(str_loc_as_cell!(0), atom_as_cell!(atom!("a"))), Some(Ordering::Greater) ); @@ -676,23 +664,22 @@ mod tests { }); 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) ); 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) ); 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) ); assert_eq!( - compare_term_test!( - wam, + wam.compare_term_test( empty_list_as_cell!(), fixnum_as_cell!(Fixnum::build_with(1)) ), @@ -702,29 +689,29 @@ mod tests { let cstr_cell = wam.heap.allocate_cstr("string").unwrap(); 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) ); 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) ); 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) ); let one_p_one = HeapCellValue::from(float_alloc!(1.1, &mut wam.arena)); 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) ); 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) ); } diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index d2db935e..edd08cb5 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -38,7 +38,7 @@ use rand::{Rng, SeedableRng}; use ordered_float::OrderedFloat; use fxhash::{FxBuildHasher, FxHasher}; -use indexmap::IndexSet; +use indexmap::*; use std::cell::Cell; use std::cmp::Ordering; @@ -925,7 +925,7 @@ impl MachineState { &mut self.lifted_heap, ); - let pstr_boundary = copy_term(copy_ball_term, copy_target, AttrVarPolicy::DeepCopy)?; + let pstr_boundary = copy_term(copy_ball_term, copy_target, AttrVarPolicy::StripAttributes)?; Ok(FindallCopyInfo { offset: threshold + lh_offset + 2, diff --git a/src/macros.rs b/src/macros.rs index 7e7853dc..8d60e959 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -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 { ($machine_st:expr, $val:expr) => {{ match $val { diff --git a/src/tests/builtins.pl b/src/tests/builtins.pl index a87fc22a..1a437413 100644 --- a/src/tests/builtins.pl +++ b/src/tests/builtins.pl @@ -46,7 +46,7 @@ test_queries_on_builtins :- \+ float([1,2,_]), \+ (X is 3 rdiv 4, float(X)), \+ \+ (X is 3 rdiv 4, rational(X)), - \+ rational(3), + rational(3), \+ rational(f(_)), \+ rational("sdfa"), \+ rational(atom), diff --git a/src/variable_records.rs b/src/variable_records.rs index c918067e..e8a867df 100644 --- a/src/variable_records.rs +++ b/src/variable_records.rs @@ -1,9 +1,11 @@ -use crate::forms::GenContext; +use crate::forms::{BranchNumber, GenContext}; use crate::parser::ast::*; use bit_set::*; use fxhash::FxBuildHasher; use indexmap::{IndexMap, IndexSet}; +use num_order::NumOrd; + use std::ops::{Deref, DerefMut}; #[derive(Debug, Clone)] @@ -13,20 +15,19 @@ pub struct TempVarData { pub(crate) conflict_set: BitSet, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct BranchDesignator { - pub branch_stack_num: usize, - pub branch_num: usize, + pub branch_num: BranchNumber, } impl BranchDesignator { #[inline] pub fn is_sub_branch(&self) -> bool { - self.branch_stack_num > 0 + self.branch_num.branch_num.num_gt(&0) } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub enum VarSafetyStatus { Needed, // which branch planted the last unsafe guarded instruction? It may still be needed. @@ -35,27 +36,27 @@ pub enum VarSafetyStatus { } impl VarSafetyStatus { - pub(crate) fn unneeded(current_branch: BranchDesignator) -> Self { + pub(crate) fn unneeded(current_branch: &BranchDesignator) -> Self { if current_branch.is_sub_branch() { - VarSafetyStatus::LocallyUnneeded(current_branch) + VarSafetyStatus::LocallyUnneeded(current_branch.clone()) } else { VarSafetyStatus::GloballyUnneeded } } #[inline] - pub(crate) fn needed_if(needed: bool, branch_designator: BranchDesignator) -> Self { + pub(crate) fn needed_if(needed: bool, branch_designator: &BranchDesignator) -> Self { if needed { VarSafetyStatus::Needed - } else if branch_designator.branch_stack_num == 0 { + } else if branch_designator.branch_num.branch_num.num_eq(&0) { VarSafetyStatus::GloballyUnneeded } else { - VarSafetyStatus::LocallyUnneeded(branch_designator) + VarSafetyStatus::LocallyUnneeded(branch_designator.clone()) } } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub enum PermVarAllocation { Done { shallow_safety: VarSafetyStatus,