use branch numbers to detect branch subsumption
This commit is contained in:
@@ -994,20 +994,27 @@ impl CodeGenerator {
|
|||||||
self.marker.in_tail_position = false;
|
self.marker.in_tail_position = false;
|
||||||
self.marker.reset_contents();
|
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_stack();
|
||||||
branch_code_stack.add_new_branch();
|
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();
|
self.marker.add_branch();
|
||||||
}
|
}
|
||||||
ClauseItem::NextBranch => {
|
ClauseItem::NextBranch { branch_num } => {
|
||||||
branch_code_stack.add_new_branch();
|
branch_code_stack.add_new_branch();
|
||||||
|
|
||||||
self.marker.add_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() {
|
if !clause_iter.in_tail_position() {
|
||||||
let subsumed_hits =
|
let subsumed_hits =
|
||||||
branch_code_stack.push_missing_vars(depth, &mut self.marker);
|
branch_code_stack.push_missing_vars(depth, &mut self.marker);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::allocator::*;
|
use crate::allocator::*;
|
||||||
use crate::codegen::SubsumedBranchHits;
|
use crate::codegen::SubsumedBranchHits;
|
||||||
use crate::forms::{GenContext, Level};
|
use crate::forms::{BranchNumber, GenContext, Level};
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine::disjuncts::VarData;
|
use crate::machine::disjuncts::VarData;
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
@@ -24,24 +24,26 @@ pub struct BranchOccurrences {
|
|||||||
pub shallow_safety: BitSet<usize>, // unset means safe, set means unsafe (after the branch merge)
|
pub shallow_safety: BitSet<usize>, // unset means safe, set means unsafe (after the branch merge)
|
||||||
pub deep_safety: BitSet<usize>,
|
pub deep_safety: BitSet<usize>,
|
||||||
pub num_branches: usize,
|
pub num_branches: usize,
|
||||||
pub current_branch: usize,
|
pub current_branch_idx: usize,
|
||||||
|
pub current_branch_num: BranchNumber,
|
||||||
pub subsumed_hits: SubsumedBranchHits,
|
pub subsumed_hits: SubsumedBranchHits,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BranchOccurrences {
|
impl BranchOccurrences {
|
||||||
fn new(num_branches: usize) -> Self {
|
fn new(current_branch_num: BranchNumber, num_branches: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
hits: BranchHits::with_hasher(FxBuildHasher::default()),
|
hits: BranchHits::with_hasher(FxBuildHasher::default()),
|
||||||
shallow_safety: BitSet::default(),
|
shallow_safety: BitSet::default(),
|
||||||
deep_safety: BitSet::default(),
|
deep_safety: BitSet::default(),
|
||||||
num_branches,
|
num_branches,
|
||||||
current_branch: 0,
|
current_branch_idx: 0,
|
||||||
|
current_branch_num,
|
||||||
subsumed_hits: SubsumedBranchHits::with_hasher(FxBuildHasher::default()),
|
subsumed_hits: SubsumedBranchHits::with_hasher(FxBuildHasher::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_branch_occurrence(&mut self, var_num: usize) {
|
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 num_branches = self.num_branches;
|
||||||
|
|
||||||
let entry = self
|
let entry = self
|
||||||
@@ -49,7 +51,7 @@ impl BranchOccurrences {
|
|||||||
.entry(var_num)
|
.entry(var_num)
|
||||||
.or_insert_with(|| BitVec::repeat(false, num_branches));
|
.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);
|
self.subsumed_hits.insert(var_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,19 +78,6 @@ impl DerefMut for BranchStack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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(
|
fn safety_unneeded_in_branch(
|
||||||
&self,
|
&self,
|
||||||
safety: &VarSafetyStatus,
|
safety: &VarSafetyStatus,
|
||||||
@@ -97,7 +86,7 @@ impl BranchStack {
|
|||||||
match safety {
|
match safety {
|
||||||
VarSafetyStatus::Needed => false,
|
VarSafetyStatus::Needed => false,
|
||||||
VarSafetyStatus::LocallyUnneeded(planter_branch) => {
|
VarSafetyStatus::LocallyUnneeded(planter_branch) => {
|
||||||
self.branch_subsumes(planter_branch, branch)
|
planter_branch.branch_num.has_as_subbranch(&branch.branch_num)
|
||||||
}
|
}
|
||||||
VarSafetyStatus::GloballyUnneeded => true,
|
VarSafetyStatus::GloballyUnneeded => true,
|
||||||
}
|
}
|
||||||
@@ -109,27 +98,26 @@ impl BranchStack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_branch_stack(&mut self, num_branches: usize) {
|
pub(crate) fn add_branch_stack(&mut self, branch_num: BranchNumber, num_branches: usize) {
|
||||||
self.push(BranchOccurrences::new(num_branches));
|
self.push(BranchOccurrences::new(branch_num, num_branches));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn current_branch_designator(&self) -> BranchDesignator {
|
pub(crate) fn current_branch_designator(&self) -> BranchDesignator {
|
||||||
let branch_stack_num = self.len();
|
|
||||||
let branch_num = self
|
let branch_num = self
|
||||||
.last()
|
.last()
|
||||||
.map(|occurrences| occurrences.current_branch)
|
.map(|occurrences| occurrences.current_branch_num.clone())
|
||||||
.unwrap_or(0);
|
.unwrap_or_else(|| BranchNumber::default());
|
||||||
|
|
||||||
BranchDesignator {
|
BranchDesignator {
|
||||||
branch_stack_num,
|
|
||||||
branch_num,
|
branch_num,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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();
|
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]
|
#[inline]
|
||||||
@@ -235,12 +223,12 @@ impl DebrayAllocator {
|
|||||||
VarAlloc::Perm(_, allocation) => {
|
VarAlloc::Perm(_, allocation) => {
|
||||||
let shallow_safety = VarSafetyStatus::needed_if(
|
let shallow_safety = VarSafetyStatus::needed_if(
|
||||||
shallow_safety.contains(var_num),
|
shallow_safety.contains(var_num),
|
||||||
branch_designator,
|
&branch_designator,
|
||||||
);
|
);
|
||||||
|
|
||||||
let deep_safety = VarSafetyStatus::needed_if(
|
let deep_safety = VarSafetyStatus::needed_if(
|
||||||
deep_safety.contains(var_num),
|
deep_safety.contains(var_num),
|
||||||
branch_designator,
|
&branch_designator,
|
||||||
);
|
);
|
||||||
|
|
||||||
if running_count < num_occurrences {
|
if running_count < num_occurrences {
|
||||||
@@ -531,11 +519,11 @@ impl DebrayAllocator {
|
|||||||
..
|
..
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
|
*deep_safety = VarSafetyStatus::unneeded(&branch_designator);
|
||||||
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
|
*shallow_safety = VarSafetyStatus::unneeded(&branch_designator);
|
||||||
}
|
}
|
||||||
VarAlloc::Temp { safety, .. } => {
|
VarAlloc::Temp { safety, .. } => {
|
||||||
*safety = VarSafetyStatus::unneeded(branch_designator);
|
*safety = VarSafetyStatus::unneeded(&branch_designator);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -557,8 +545,8 @@ impl DebrayAllocator {
|
|||||||
) => {
|
) => {
|
||||||
// GetVariable in head chunk is considered safe.
|
// GetVariable in head chunk is considered safe.
|
||||||
if lvl == Level::Deep {
|
if lvl == Level::Deep {
|
||||||
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
|
*deep_safety = VarSafetyStatus::unneeded(&branch_designator);
|
||||||
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
|
*shallow_safety = VarSafetyStatus::unneeded(&branch_designator);
|
||||||
} else if term_loc == GenContext::Head {
|
} else if term_loc == GenContext::Head {
|
||||||
*shallow_safety = VarSafetyStatus::GloballyUnneeded;
|
*shallow_safety = VarSafetyStatus::GloballyUnneeded;
|
||||||
} else if let Some(&temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c) {
|
} else if let Some(&temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c) {
|
||||||
@@ -605,7 +593,7 @@ impl DebrayAllocator {
|
|||||||
{
|
{
|
||||||
Target::argument_to_value(r, arg_c)
|
Target::argument_to_value(r, arg_c)
|
||||||
} else {
|
} else {
|
||||||
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
|
*shallow_safety = VarSafetyStatus::unneeded(&branch_designator);
|
||||||
Target::unsafe_argument_to_value(r, arg_c)
|
Target::unsafe_argument_to_value(r, arg_c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -640,7 +628,7 @@ impl DebrayAllocator {
|
|||||||
{
|
{
|
||||||
Target::subterm_to_value(r)
|
Target::subterm_to_value(r)
|
||||||
} else {
|
} else {
|
||||||
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
|
*deep_safety = VarSafetyStatus::unneeded(&branch_designator);
|
||||||
Target::unsafe_subterm_to_value(r)
|
Target::unsafe_subterm_to_value(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,7 +639,7 @@ impl DebrayAllocator {
|
|||||||
{
|
{
|
||||||
Target::subterm_to_value(r)
|
Target::subterm_to_value(r)
|
||||||
} else {
|
} else {
|
||||||
*safety = VarSafetyStatus::unneeded(branch_designator);
|
*safety = VarSafetyStatus::unneeded(&branch_designator);
|
||||||
Target::unsafe_subterm_to_value(r)
|
Target::unsafe_subterm_to_value(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
95
src/forms.rs
95
src/forms.rs
@@ -18,9 +18,11 @@ use indexmap::{IndexMap, IndexSet};
|
|||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::{AddAssign, Deref, DerefMut};
|
use std::ops::{AddAssign, Deref, DerefMut};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@@ -128,10 +130,86 @@ 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<BranchNumber> 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<H: Hasher>(&self, hasher: &mut H) {
|
||||||
|
self.branch_num.hash(hasher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd<BranchNumber> for BranchNumber {
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, rhs: &BranchNumber) -> Option<Ordering> {
|
||||||
|
self.branch_num.partial_cmp(&rhs.branch_num)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BranchNumber {
|
||||||
|
pub(crate) fn has_as_subbranch(&self, other: &Self) -> bool {
|
||||||
|
let delta_ratio = &self.delta / &other.delta;
|
||||||
|
|
||||||
|
if !delta_ratio.denominator().is_one() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)]
|
#[derive(Debug)]
|
||||||
pub enum ChunkedTerms {
|
pub enum ChunkedTerms {
|
||||||
Branch(Vec<VecDeque<ChunkedTerms>>),
|
Branch {
|
||||||
Chunk { terms: VecDeque<QueryTerm> },
|
branch_nums: Vec<BranchNumber>,
|
||||||
|
arms: Vec<VecDeque<ChunkedTerms>>,
|
||||||
|
},
|
||||||
|
Chunk {
|
||||||
|
terms: VecDeque<QueryTerm>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -165,21 +243,22 @@ impl ChunkedTermVec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_branch(&mut self, capacity: usize) {
|
pub fn reserve_branch(&mut self, capacity: usize) {
|
||||||
self.chunk_vec
|
self.chunk_vec.push_back(ChunkedTerms::Branch {
|
||||||
.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
|
branch_nums: Vec::with_capacity(capacity),
|
||||||
|
arms: Vec::with_capacity(capacity),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add_chunk(&mut self) {
|
pub fn add_chunk(&mut self) {
|
||||||
let chunk = ChunkedTerms::Chunk {
|
self.chunk_vec.push_back(ChunkedTerms::Chunk {
|
||||||
terms: VecDeque::from(vec![]),
|
terms: VecDeque::from(vec![]),
|
||||||
};
|
});
|
||||||
self.chunk_vec.push_back(chunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_chunk_term(&mut self, term: QueryTerm) {
|
pub fn push_chunk_term(&mut self, term: QueryTerm) {
|
||||||
match self.chunk_vec.back_mut() {
|
match self.chunk_vec.back_mut() {
|
||||||
Some(ChunkedTerms::Branch(_)) => {
|
Some(ChunkedTerms::Branch { .. }) => {
|
||||||
let chunk = ChunkedTerms::Chunk {
|
let chunk = ChunkedTerms::Chunk {
|
||||||
terms: VecDeque::from(vec![term]),
|
terms: VecDeque::from(vec![term]),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -319,15 +319,28 @@ pub(crate) fn breadth_first_iter(
|
|||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
enum ClauseIteratorState<'a> {
|
enum ClauseIteratorState<'a> {
|
||||||
RemainingChunks(&'a VecDeque<ChunkedTerms>, usize),
|
RemainingChunks(&'a VecDeque<ChunkedTerms>, usize),
|
||||||
RemainingBranches(&'a Vec<VecDeque<ChunkedTerms>>, usize),
|
RemainingBranches(
|
||||||
|
&'a Vec<BranchNumber>,
|
||||||
|
&'a Vec<VecDeque<ChunkedTerms>>,
|
||||||
|
usize,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) enum ClauseItem<'a> {
|
pub(crate) enum ClauseItem<'a> {
|
||||||
FirstBranch(usize),
|
FirstBranch {
|
||||||
NextBranch,
|
branch_num: &'a BranchNumber,
|
||||||
BranchEnd(usize),
|
num_branches: usize,
|
||||||
Chunk { terms: &'a VecDeque<QueryTerm> },
|
},
|
||||||
|
NextBranch {
|
||||||
|
branch_num: &'a BranchNumber,
|
||||||
|
},
|
||||||
|
BranchEnd {
|
||||||
|
depth: usize,
|
||||||
|
},
|
||||||
|
Chunk {
|
||||||
|
terms: &'a VecDeque<QueryTerm>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -338,8 +351,8 @@ pub(crate) struct ClauseIterator<'a> {
|
|||||||
|
|
||||||
fn state_from_chunked_terms(chunk_vec: &VecDeque<ChunkedTerms>) -> ClauseIteratorState<'_> {
|
fn state_from_chunked_terms(chunk_vec: &VecDeque<ChunkedTerms>) -> ClauseIteratorState<'_> {
|
||||||
if chunk_vec.len() == 1 {
|
if chunk_vec.len() == 1 {
|
||||||
if let Some(ChunkedTerms::Branch(ref branches)) = chunk_vec.front() {
|
if let Some(ChunkedTerms::Branch { branch_nums, arms }) = chunk_vec.front() {
|
||||||
return ClauseIteratorState::RemainingBranches(branches, 0);
|
return ClauseIteratorState::RemainingBranches(branch_nums, arms, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +383,9 @@ impl<'a> ClauseIterator<'a> {
|
|||||||
|
|
||||||
while let Some(state) = self.state_stack.pop() {
|
while let Some(state) = self.state_stack.pop() {
|
||||||
match state {
|
match state {
|
||||||
ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => {
|
ClauseIteratorState::RemainingBranches(_branch_nums, terms, focus)
|
||||||
|
if terms.len() == focus =>
|
||||||
|
{
|
||||||
depth += 1;
|
depth += 1;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -399,9 +414,9 @@ impl<'a> Iterator for ClauseIterator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match &chunks[focus] {
|
match &chunks[focus] {
|
||||||
ChunkedTerms::Branch(branches) => {
|
ChunkedTerms::Branch { branch_nums, arms } => {
|
||||||
self.state_stack
|
self.state_stack
|
||||||
.push(ClauseIteratorState::RemainingBranches(branches, 0));
|
.push(ClauseIteratorState::RemainingBranches(branch_nums, arms, 0));
|
||||||
}
|
}
|
||||||
ChunkedTerms::Chunk { ref terms } => {
|
ChunkedTerms::Chunk { ref terms } => {
|
||||||
return Some(ClauseItem::Chunk { terms });
|
return Some(ClauseItem::Chunk { terms });
|
||||||
@@ -411,11 +426,15 @@ impl<'a> Iterator for ClauseIterator<'a> {
|
|||||||
ClauseIteratorState::RemainingChunks(chunks, focus) => {
|
ClauseIteratorState::RemainingChunks(chunks, focus) => {
|
||||||
debug_assert_eq!(chunks.len(), focus);
|
debug_assert_eq!(chunks.len(), focus);
|
||||||
}
|
}
|
||||||
ClauseIteratorState::RemainingBranches(branches, focus)
|
ClauseIteratorState::RemainingBranches(branch_nums, branches, focus)
|
||||||
if focus < branches.len() =>
|
if focus < branches.len() =>
|
||||||
{
|
{
|
||||||
self.state_stack
|
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]);
|
let state = state_from_chunked_terms(&branches[focus]);
|
||||||
|
|
||||||
if let ClauseIteratorState::RemainingChunks(..) = &state {
|
if let ClauseIteratorState::RemainingChunks(..) = &state {
|
||||||
@@ -425,14 +444,21 @@ impl<'a> Iterator for ClauseIterator<'a> {
|
|||||||
self.state_stack.push(state);
|
self.state_stack.push(state);
|
||||||
|
|
||||||
return if focus == 0 {
|
return if focus == 0 {
|
||||||
Some(ClauseItem::FirstBranch(branches.len()))
|
Some(ClauseItem::FirstBranch {
|
||||||
|
branch_num: &branch_nums[0],
|
||||||
|
num_branches: branches.len(),
|
||||||
|
})
|
||||||
} else {
|
} 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);
|
debug_assert_eq!(branches.len(), focus);
|
||||||
return Some(ClauseItem::BranchEnd(self.branch_end_depth()));
|
return Some(ClauseItem::BranchEnd {
|
||||||
|
depth: self.branch_end_depth(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,79 +6,16 @@ use crate::machine::loader::*;
|
|||||||
use crate::machine::machine_errors::CompilationError;
|
use crate::machine::machine_errors::CompilationError;
|
||||||
use crate::machine::preprocessor::*;
|
use crate::machine::preprocessor::*;
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
use crate::parser::dashu::Rational;
|
|
||||||
use crate::variable_records::*;
|
use crate::variable_records::*;
|
||||||
|
|
||||||
use dashu::Integer;
|
use dashu::Integer;
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::Hash;
|
||||||
use std::ops::{Deref, DerefMut};
|
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<BranchNumber> 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<H: Hasher>(&self, hasher: &mut H) {
|
|
||||||
self.branch_num.hash(hasher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd<BranchNumber> for BranchNumber {
|
|
||||||
#[inline]
|
|
||||||
fn partial_cmp(&self, rhs: &BranchNumber) -> Option<Ordering> {
|
|
||||||
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)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct VarInfo {
|
pub struct VarInfo {
|
||||||
var_ptr: VarPtr,
|
var_ptr: VarPtr,
|
||||||
@@ -140,12 +77,13 @@ pub struct ClassifyInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum TraversalState {
|
enum TraversalState {
|
||||||
// construct a QueryTerm::Branch with number of disjuncts, reset
|
// pop the latest branch number from the root set and use it to construct a QueryTerm::Branch
|
||||||
// the chunk type to that of the chunk preceding the disjunct and the chunk_num.
|
// with number of disjuncts, reset the chunk type to that of the chunk preceding the disjunct
|
||||||
|
// and the chunk_num.
|
||||||
BuildDisjunct(usize),
|
BuildDisjunct(usize),
|
||||||
|
BuildFinalDisjunct(usize),
|
||||||
// add the last disjunct to a QueryTerm::Branch, continuing from
|
// add the last disjunct to a QueryTerm::Branch, continuing from
|
||||||
// where it leaves off.
|
// where it leaves off.
|
||||||
BuildFinalDisjunct(usize),
|
|
||||||
Fail,
|
Fail,
|
||||||
GetCutPoint { var_num: usize, prev_b: bool },
|
GetCutPoint { var_num: usize, prev_b: bool },
|
||||||
Cut { var_num: usize, is_global: bool },
|
Cut { var_num: usize, is_global: bool },
|
||||||
@@ -154,7 +92,6 @@ enum TraversalState {
|
|||||||
Term(Term),
|
Term(Term),
|
||||||
OverrideGlobalCutVar(usize),
|
OverrideGlobalCutVar(usize),
|
||||||
ResetGlobalCutVarOverride(Option<usize>),
|
ResetGlobalCutVarOverride(Option<usize>),
|
||||||
RemoveBranchNum, // pop the current_branch_num and from the root set.
|
|
||||||
AddBranchNum(BranchNumber), // set current_branch_num, add it to 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
|
RepBranchNum(BranchNumber), // replace current_branch_num and the latest in the root set
|
||||||
}
|
}
|
||||||
@@ -199,7 +136,7 @@ impl VarData {
|
|||||||
VarAlloc::Perm(0, PermVarAllocation::Pending);
|
VarAlloc::Perm(0, PermVarAllocation::Pending);
|
||||||
|
|
||||||
match build_stack.front_mut() {
|
match build_stack.front_mut() {
|
||||||
Some(ChunkedTerms::Branch(_)) => {
|
Some(ChunkedTerms::Branch { .. }) => {
|
||||||
build_stack.push_front(ChunkedTerms::Chunk {
|
build_stack.push_front(ChunkedTerms::Chunk {
|
||||||
terms: VecDeque::from(vec![term]),
|
terms: VecDeque::from(vec![term]),
|
||||||
});
|
});
|
||||||
@@ -232,11 +169,16 @@ fn merge_branch_seq(branches: impl Iterator<Item = BranchInfo>) -> BranchInfo {
|
|||||||
branch_info
|
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();
|
let branch_vec = build_stack.drain(preceding_len + 1..).collect();
|
||||||
|
|
||||||
if let ChunkedTerms::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] {
|
if let ChunkedTerms::Branch { branch_nums, arms } = &mut build_stack[preceding_len] {
|
||||||
disjuncts.push(branch_vec);
|
branch_nums.push(branch_num);
|
||||||
|
arms.push(branch_vec);
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
@@ -477,9 +419,6 @@ impl VariableClassifier {
|
|||||||
self.root_set.insert(branch_num.clone());
|
self.root_set.insert(branch_num.clone());
|
||||||
self.current_branch_num = branch_num;
|
self.current_branch_num = branch_num;
|
||||||
}
|
}
|
||||||
TraversalState::RemoveBranchNum => {
|
|
||||||
self.root_set.pop();
|
|
||||||
}
|
|
||||||
TraversalState::RepBranchNum(branch_num) => {
|
TraversalState::RepBranchNum(branch_num) => {
|
||||||
self.root_set.pop();
|
self.root_set.pop();
|
||||||
self.root_set.insert(branch_num.clone());
|
self.root_set.insert(branch_num.clone());
|
||||||
@@ -488,14 +427,9 @@ impl VariableClassifier {
|
|||||||
TraversalState::ResetCallPolicy(call_policy) => {
|
TraversalState::ResetCallPolicy(call_policy) => {
|
||||||
self.call_policy = call_policy;
|
self.call_policy = call_policy;
|
||||||
}
|
}
|
||||||
TraversalState::BuildDisjunct(preceding_len) => {
|
TraversalState::BuildDisjunct(preceding_len) | TraversalState::BuildFinalDisjunct(preceding_len) => {
|
||||||
flatten_into_disjunct(&mut build_stack, 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;
|
|
||||||
}
|
|
||||||
TraversalState::BuildFinalDisjunct(preceding_len) => {
|
|
||||||
flatten_into_disjunct(&mut build_stack, preceding_len);
|
|
||||||
|
|
||||||
self.current_chunk_type = ChunkType::Mid;
|
self.current_chunk_type = ChunkType::Mid;
|
||||||
self.current_chunk_num += 1;
|
self.current_chunk_num += 1;
|
||||||
@@ -632,11 +566,10 @@ impl VariableClassifier {
|
|||||||
));
|
));
|
||||||
|
|
||||||
let iter = branches.into_iter().zip(branch_numbers.into_iter());
|
let iter = branches.into_iter().zip(branch_numbers.into_iter());
|
||||||
let final_disjunct_loc = state_stack.len();
|
let final_disjunct_loc = state_stack.len();
|
||||||
|
|
||||||
for (term, branch_num) in iter.rev() {
|
for (term, branch_num) in iter.rev() {
|
||||||
state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
|
state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
|
||||||
state_stack.push(TraversalState::RemoveBranchNum);
|
|
||||||
state_stack.push(TraversalState::Term(term));
|
state_stack.push(TraversalState::Term(term));
|
||||||
state_stack.push(TraversalState::AddBranchNum(branch_num));
|
state_stack.push(TraversalState::AddBranchNum(branch_num));
|
||||||
}
|
}
|
||||||
@@ -655,23 +588,18 @@ impl VariableClassifier {
|
|||||||
let then_term = terms.pop().unwrap();
|
let then_term = terms.pop().unwrap();
|
||||||
let if_term = terms.pop().unwrap();
|
let if_term = terms.pop().unwrap();
|
||||||
|
|
||||||
let prev_b = if matches!(
|
let prev_b =
|
||||||
state_stack.last(),
|
if let Some(&TraversalState::BuildDisjunct(preceding_len)) =
|
||||||
Some(TraversalState::RemoveBranchNum)
|
state_stack.last()
|
||||||
) {
|
{
|
||||||
// check if the second-to-last element
|
// check if the second-to-last element
|
||||||
// is a regular BuildDisjunct, as we
|
// is a regular BuildDisjunct, as we
|
||||||
// don't want to add GetPrevLevel in
|
// don't want to add GetPrevLevel in
|
||||||
// case of a TrustMe.
|
// case of a TrustMe.
|
||||||
match state_stack.iter().rev().nth(1) {
|
preceding_len + 1 == build_stack.len()
|
||||||
Some(&TraversalState::BuildDisjunct(preceding_len)) => {
|
} else {
|
||||||
preceding_len + 1 == build_stack.len()
|
false
|
||||||
}
|
};
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
state_stack.push(TraversalState::Term(then_term));
|
state_stack.push(TraversalState::Term(then_term));
|
||||||
state_stack.push(TraversalState::Cut {
|
state_stack.push(TraversalState::Cut {
|
||||||
@@ -690,14 +618,21 @@ impl VariableClassifier {
|
|||||||
let not_term = terms.pop().unwrap();
|
let not_term = terms.pop().unwrap();
|
||||||
let build_stack_len = build_stack.len();
|
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);
|
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::BuildFinalDisjunct(build_stack_len));
|
||||||
state_stack.push(TraversalState::Term(Term::Clause(
|
state_stack.push(TraversalState::Term(Term::Clause(
|
||||||
Cell::default(),
|
Cell::default(),
|
||||||
atom!("$succeed"),
|
atom!("$succeed"),
|
||||||
vec![],
|
vec![],
|
||||||
)));
|
)));
|
||||||
|
state_stack.push(TraversalState::AddBranchNum(second_branch_num));
|
||||||
state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
|
state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
|
||||||
state_stack.push(TraversalState::Fail);
|
state_stack.push(TraversalState::Fail);
|
||||||
state_stack.push(TraversalState::CutPrev(self.var_num));
|
state_stack.push(TraversalState::CutPrev(self.var_num));
|
||||||
@@ -710,6 +645,7 @@ impl VariableClassifier {
|
|||||||
var_num: self.var_num,
|
var_num: self.var_num,
|
||||||
prev_b: false,
|
prev_b: false,
|
||||||
});
|
});
|
||||||
|
state_stack.push(TraversalState::AddBranchNum(first_branch_num));
|
||||||
|
|
||||||
self.current_chunk_type = ChunkType::Mid;
|
self.current_chunk_type = ChunkType::Mid;
|
||||||
self.current_chunk_num += 1;
|
self.current_chunk_num += 1;
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
use crate::forms::GenContext;
|
use crate::forms::{BranchNumber, GenContext};
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
|
||||||
use bit_set::*;
|
use bit_set::*;
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
|
use num_order::NumOrd;
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -13,20 +15,19 @@ pub struct TempVarData {
|
|||||||
pub(crate) conflict_set: BitSet<usize>,
|
pub(crate) conflict_set: BitSet<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct BranchDesignator {
|
pub struct BranchDesignator {
|
||||||
pub branch_stack_num: usize,
|
pub branch_num: BranchNumber,
|
||||||
pub branch_num: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BranchDesignator {
|
impl BranchDesignator {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_sub_branch(&self) -> bool {
|
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 {
|
pub enum VarSafetyStatus {
|
||||||
Needed,
|
Needed,
|
||||||
// which branch planted the last unsafe guarded instruction? It may still be needed.
|
// which branch planted the last unsafe guarded instruction? It may still be needed.
|
||||||
@@ -35,27 +36,27 @@ pub enum VarSafetyStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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() {
|
if current_branch.is_sub_branch() {
|
||||||
VarSafetyStatus::LocallyUnneeded(current_branch)
|
VarSafetyStatus::LocallyUnneeded(current_branch.clone())
|
||||||
} else {
|
} else {
|
||||||
VarSafetyStatus::GloballyUnneeded
|
VarSafetyStatus::GloballyUnneeded
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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 {
|
if needed {
|
||||||
VarSafetyStatus::Needed
|
VarSafetyStatus::Needed
|
||||||
} else if branch_designator.branch_stack_num == 0 {
|
} else if branch_designator.branch_num.branch_num.num_eq(&0) {
|
||||||
VarSafetyStatus::GloballyUnneeded
|
VarSafetyStatus::GloballyUnneeded
|
||||||
} else {
|
} else {
|
||||||
VarSafetyStatus::LocallyUnneeded(branch_designator)
|
VarSafetyStatus::LocallyUnneeded(branch_designator.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum PermVarAllocation {
|
pub enum PermVarAllocation {
|
||||||
Done {
|
Done {
|
||||||
shallow_safety: VarSafetyStatus,
|
shallow_safety: VarSafetyStatus,
|
||||||
|
|||||||
Reference in New Issue
Block a user