dependencies = [
"assert_cmd",
"base64",
+ "bit-set",
"blake2 0.8.1",
"chrono",
"cpu-time",
walkdir = "2"
[dependencies]
+bit-set = "0.5.3"
cpu-time = "1.0.0"
crossterm = "0.20.0"
dirs-next = "2.0.0"
// TODO: wha.. why?? grrr. it drains the VarStatus data from vs (which it owns!)
// into self.bindings and perm_vs after all is computed (i.e. vs.populate_restricting_sets()
// and vs.set_perm_vals(has_deep_cut) have both been called).
+ /*
fn drain_var_data<'a>(
&mut self,
- vs: VariableFixtures<'a>,
+ vs: VariableFixtures,
num_of_chunks: usize,
- ) -> VariableFixtures<'a> {
+ ) -> VariableFixtures {
let mut perm_vs = VariableFixtures::new();
- for (var, (var_status, cells)) in vs.into_iter() {
+ for (var, var_status) in vs.into_iter() {
match var_status {
VarStatus::Temp(chunk_num, tvd) => {
self.bindings_mut()
- .insert(var.clone(), VarData::Temp(chunk_num, 0, tvd));
-
- if chunk_num + 1 == num_of_chunks {
- perm_vs.insert_last_chunk_temp_var(var);
- }
+ .insert(var.clone(), VarAlloc::Temp(chunk_num, 0, tvd));
}
VarStatus::Perm(_) => {
- self.bindings_mut().insert(var.clone(), VarData::Perm(0));
- perm_vs.insert(var, (var_status, cells));
+ self.bindings_mut().insert(var.clone(), VarAlloc::Perm(0));
+ perm_vs.insert(var, var_status);
}
};
}
perm_vs
}
+ */
fn get(&self, var: Var) -> RegType {
self.bindings()
fn record_register(&mut self, var: Var, r: RegType) {
match self.bindings_mut().get_mut(&var).unwrap() {
- &mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
- &mut VarData::Perm(ref mut s) => *s = r.reg_num(),
+ &mut VarAlloc::Temp(_, ref mut s, _) => *s = r.reg_num(),
+ &mut VarAlloc::Perm(ref mut s) => *s = r.reg_num(),
}
}
}
use crate::atom_table::*;
use crate::parser::ast::*;
use crate::{perm_v, temp_v};
-
use crate::allocator::*;
use crate::arithmetic::*;
use crate::debray_allocator::*;
use std::collections::VecDeque;
#[derive(Debug)]
-pub(crate) struct ConjunctInfo<'a> {
- pub(crate) perm_vs: VariableFixtures<'a>,
+pub(crate) struct ConjunctInfo {
+ pub(crate) perm_vs: VariableFixtures,
pub(crate) num_of_chunks: usize,
pub(crate) has_deep_cut: bool,
}
-impl<'a> ConjunctInfo<'a> {
- fn new(perm_vs: VariableFixtures<'a>, num_of_chunks: usize, has_deep_cut: bool) -> Self {
+impl ConjunctInfo {
+ fn new(perm_vs: VariableFixtures, num_of_chunks: usize, has_deep_cut: bool) -> Self {
ConjunctInfo {
perm_vs,
num_of_chunks,
#[inline(always)]
pub(crate) fn get_binding(&self, name: &Var) -> Option<RegType> {
match self.bindings().get(name) {
- Some(&VarData::Temp(_, t, _)) if t != 0 => Some(RegType::Temp(t)),
- Some(&VarData::Perm(p)) if p != 0 => Some(RegType::Perm(p)),
+ Some(&VarAlloc::Temp(_, t, _)) if t != 0 => Some(RegType::Temp(t)),
+ Some(&VarAlloc::Perm(p)) if p != 0 => Some(RegType::Perm(p)),
_ => None,
}
}
fn compile_seq<'a>(
&mut self,
iter: ChunkedIterator<'a>,
- conjunct_info: &ConjunctInfo<'a>,
+ conjunct_info: &ConjunctInfo,
code: &mut Code,
) -> Result<(), CompilationError> {
for (chunk_num, _, terms) in iter.rule_body_iter() {
}
}
- fn compile_cleanup<'a>(
+ fn compile_cleanup(
&mut self,
code: &mut Code,
- conjunct_info: &ConjunctInfo<'a>,
- toc: &'a QueryTerm,
+ conjunct_info: &ConjunctInfo,
+ toc: &QueryTerm,
) {
// add a proceed to bookend any trailing cuts.
match toc {
code.push(instr!("proceed"));
}
_ => {}
- };
+ }
// perform lco.
let dealloc_index = Self::lco(code);
use crate::instructions::*;
use crate::iterators::*;
+use bit_set::*;
use indexmap::{IndexMap, IndexSet};
use std::cell::Cell;
use std::mem::swap;
use std::vec::Vec;
-// labeled with chunk numbers.
+pub(crate) type OccurrenceSet = IndexSet<(GenContext, usize)>;
+
#[derive(Debug)]
-pub(crate) enum VarStatus {
- Perm(usize),
- Temp(usize, TempVarData), // Perm(chunk_num) | Temp(chunk_num, _)
+pub(crate) struct TempVarData {
+ pub(crate) last_term_arity: usize,
+ pub(crate) use_set: OccurrenceSet,
+ pub(crate) no_use_set: BitSet<usize>,
+ pub(crate) conflict_set: BitSet<usize>,
}
-pub(crate) type OccurrenceSet = BTreeSet<(GenContext, usize)>;
+#[derive(Debug)]
+pub(crate) struct TempVarStatus {
+ chunk_num: usize,
+ temp_var_data: TempVarData,
+}
+// TODO: get ridda this! I think.
// Perm: 0 initially, a stack register once processed.
// Temp: labeled with chunk_num and temp offset (unassigned if 0).
#[derive(Debug)]
}
}
-#[derive(Debug)]
-pub(crate) struct TempVarData {
- pub(crate) last_term_arity: usize,
- pub(crate) use_set: OccurrenceSet,
- pub(crate) no_use_set: BTreeSet<usize>,
- pub(crate) conflict_set: BTreeSet<usize>,
-}
-
impl TempVarData {
pub(crate) fn new(last_term_arity: usize) -> Self {
TempVarData {
last_term_arity: last_term_arity,
- use_set: BTreeSet::new(),
- no_use_set: BTreeSet::new(),
- conflict_set: BTreeSet::new(),
+ use_set: BitSet::new(),
+ no_use_set: BitSet::new(),
+ conflict_set: BitSet::new(),
}
}
pub(crate) fn populate_conflict_set(&mut self) {
if self.last_term_arity > 0 {
let arity = self.last_term_arity;
- let mut conflict_set: BTreeSet<usize> = (1..arity).collect();
+ let mut conflict_set: BitSet<usize> = (1..arity).collect();
for &(_, reg) in self.use_set.iter() {
conflict_set.remove(®);
}
}
-type VariableFixture<'a> = (VarStatus, Vec<&'a Cell<VarReg>>);
-
#[derive(Debug)]
-pub(crate) struct VariableFixtures<'a> {
- perm_vars: IndexMap<Var, VariableFixture<'a>>,
- last_chunk_temp_vars: IndexSet<Var>, // TODO: has no use at all!
+pub(crate) struct VariableFixtures {
+ temp_vars: IndexMap<usize, TempVarStatus>,
+ last_chunk_temp_vars: IndexSet<usize>, // TODO: has no use at all! remove it.
}
impl<'a> VariableFixtures<'a> {
pub(crate) fn new() -> Self {
VariableFixtures {
- perm_vars: IndexMap::new(),
+ temp_vars: IndexMap::new(),
last_chunk_temp_vars: IndexSet::new(),
}
}
+ // TODO: get rid of this also.
pub(crate) fn insert(&mut self, var: Var, vs: VariableFixture<'a>) {
- self.perm_vars.insert(var, vs);
+ self.temp_vars.insert(var, vs);
}
+ // TODO: used?
pub(crate) fn insert_last_chunk_temp_var(&mut self, var: Var) {
self.last_chunk_temp_vars.insert(var);
}
// Compute the conflict set of u.
// 1.
- let mut use_sets: IndexMap<Var, OccurrenceSet> = IndexMap::new();
+ let mut use_sets: IndexMap<usize, OccurrenceSet> = IndexMap::new();
- for (var, &mut (ref mut var_status, _)) in self.iter_mut() {
- if let &mut VarStatus::Temp(_, ref mut var_data) = var_status {
- let mut use_set = OccurrenceSet::new();
+ for (var_gen_index, ref mut var_status) in self.temp_vars.iter_mut() {
+ let TempVarStatus { ref mut temp_var_data, .. } = var_status;
+ let mut use_set = OccurrenceSet::new();
- swap(&mut var_data.use_set, &mut use_set);
- use_sets.insert((*var).clone(), use_set);
- }
+ mem::swap(&mut temp_var_data.use_set, &mut use_set);
+ use_sets.insert(var_gen_index, use_set);
}
for (u, use_set) in use_sets.drain(..) {
// 2.
for &(term_loc, reg) in use_set.iter() {
if let GenContext::Last(cn_u) = term_loc {
- for (ref t, &mut (ref mut var_status, _)) in self.iter_mut() {
- if let &mut VarStatus::Temp(cn_t, ref mut t_data) = var_status {
- if cn_u == cn_t && u != **t {
- if !t_data.uses_reg(reg) {
- t_data.no_use_set.insert(reg);
- }
+ for (var_gen_index, ref mut var_status) in self.terms_vars.iter_mut() {
+ let TempVarStatus { chunk_num, ref mut temp_var_data } = var_status;
+
+ if cn_u == chunk_num && u != var_gen_index {
+ if !temp_var_data.uses_reg(reg) {
+ temp_var_data.no_use_set.insert(reg);
}
}
}
}
// 3.
- match self.get_mut(u).unwrap() {
- &mut (VarStatus::Temp(_, ref mut u_data), _) => {
- u_data.use_set = use_set;
- u_data.populate_conflict_set();
- }
- _ => {}
- };
- }
- }
-
- fn get_mut(&mut self, u: Var) -> Option<&mut VariableFixture<'a>> {
- self.perm_vars.get_mut(&u)
- }
+ let TempVarStatus { ref mut temp_var_data, ..} = self.temp_vars.get_mut(u).unwrap();
- fn iter_mut(&mut self) -> indexmap::map::IterMut<Var, VariableFixture<'a>> {
- self.perm_vars.iter_mut()
+ temp_var_data.use_set = use_set;
+ temp_var_data.populate_conflict_set();
+ }
}
fn record_temp_info(&mut self, tvd: &mut TempVarData, arg_c: usize, term_loc: GenContext) {
};
}
- pub(crate) fn vars_above_threshold(&self, index: usize) -> usize {
- let mut var_count = 0;
-
- for &(ref var_status, _) in self.values() {
- if let &VarStatus::Perm(i) = var_status {
- if i > index {
- var_count += 1;
- }
- }
- }
-
- var_count
- }
-
- pub(crate) fn mark_vars_in_chunk<I>(&mut self, iter: I, lt_arity: usize, term_loc: GenContext)
- where
- I: Iterator<Item = TermRef<'a>>,
- {
+ pub(crate) fn mark_temp_var(
+ &mut self,
+ generated_var_index: usize,
+ lvl: Level,
+ classify_info: &ClassifyInfo,
+ term_loc: GenContext,
+ ) {
let chunk_num = term_loc.chunk_num();
- let mut arg_c = 1;
-
- for term_ref in iter {
- if let &TermRef::Var(lvl, cell, ref var) = &term_ref {
- let mut status = self.perm_vars.swap_remove(var).unwrap_or((
- VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)),
- Vec::new(),
- ));
- status.1.push(cell);
-
- match status.0 {
- VarStatus::Temp(cn, ref mut tvd) if cn == chunk_num => {
- if let Level::Shallow = lvl {
- self.record_temp_info(tvd, arg_c, term_loc);
- }
- }
- _ => status.0 = VarStatus::Perm(chunk_num),
- };
-
- self.perm_vars.insert(var.clone(), status);
+ let mut status = self.temp_vars.swap_remove(generated_var_index).unwrap_or_else(|| {
+ TempVarStatus {
+ chunk_num,
+ temp_var_data: TempVarData::new(classify_info.arity),
}
+ });
- if let Level::Shallow = term_ref.level() {
- arg_c += 1;
- }
+ if let Level::Shallow = lvl {
+ self.record_temp_info(&mut status, classify_info.arg_c, term_loc);
}
- }
- pub(crate) fn into_iter(self) -> indexmap::map::IntoIter<Var, VariableFixture<'a>> {
- self.perm_vars.into_iter()
- }
-
- fn values(&self) -> indexmap::map::Values<Var, VariableFixture<'a>> {
- self.perm_vars.values()
- }
-
- pub(crate) fn size(&self) -> usize {
- self.perm_vars.len()
- }
-
- pub(crate) fn set_perm_vals(&self, has_deep_cuts: bool) {
- let mut values_vec: Vec<_> = self
- .values()
- .filter_map(|ref v| match &v.0 {
- &VarStatus::Perm(i) => Some((i, &v.1)),
- _ => None,
- })
- .collect();
-
- values_vec.sort_by_key(|ref v| v.0);
-
- let offset = has_deep_cuts as usize;
-
- for (i, (_, cells)) in values_vec.into_iter().rev().enumerate() {
- for cell in cells {
- cell.set(VarReg::Norm(RegType::Perm(i + 1 + offset)));
- }
- }
+ self.temp_vars.insert(Var::Generated(generated_var_index), status);
}
}
}
}
-
#[derive(Debug, Clone)]
pub(crate) enum TermRef<'a> {
AnonVar(Level),
*/
use crate::atom_table::*;
+use crate::fixtures::VariableFixtures;
use crate::forms::*;
use crate::instructions::*;
use crate::iterators::*;
impl Default for BranchNumber {
fn default() -> Self {
Self {
- branch_num: Rational::from(1 << 10),
+ branch_num: Rational::from(1 << 63),
delta: Rational::from(1),
}
}
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct VarInfo {
+ var_ptr: VarPtr,
+ classify_info: ClassifyInfo,
+ lvl: Level,
+}
+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ChunkInfo {
chunk_num: usize,
- vars: Vec<VarPtr>, // pointer to incidence
-}
-
-impl ChunkInfo {
- fn new(chunk_num: usize) -> Self {
- ChunkInfo { chunk_num, vars: vec![] }
- }
+ term_loc: GenContext,
+ // pointer to incidence, term occurrence arity.
+ vars: Vec<VarInfo>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Last,
}
+impl ChunkType {
+ #[inline(always)]
+ fn to_gen_context(self, chunk_num: usize) -> GenContext {
+ match self {
+ ChunkType::Head => GenContext::Head,
+ ChunkType::Mid => GenContext::Mid(chunk_num),
+ ChunkType::Last => GenContext::Last(chunk_num),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ClassifyInfo {
+ arg_c: usize,
+ arity: usize,
+}
+
enum TraversalState {
// construct a QueryTerm::Branch with number of disjuncts, reset
// the chunk type to that of the chunk preceding the disjunct.
pub num_occurrences: usize,
}
-pub type ClassifyFactResult = (Term, Vec<VarRecord>);
-pub type ClassifyRuleResult = (Term, Vec<QueryTerm>, Vec<VarRecord>);
+// TODO: already exists a VarData! although it may no longer exist??
+// Also, the name is too similar to VarInfo. Think of better names!
+pub struct VarData {
+ pub records: Vec<VarRecord>,
+ pub fixtures: VariableFixtures,
+}
+
+pub type ClassifyFactResult = (Term, VarData);
+pub type ClassifyRuleResult = (Term, Vec<QueryTerm>, VarData);
fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> BranchInfo {
let mut branch_info = BranchInfo::new(BranchNumber::default());
fn term_in_other_chunk(term: &Term) -> Option<bool> {
match term {
- Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(name, terms.len())),
+ Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(*name, terms.len())),
Term::Literal(_, Literal::Atom(atom!("!"))) |
Term::Literal(_, Literal::Char('!')) => Some(false),
- Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(name, 0)),
+ Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(*name, 0)),
Term::Var(..) => Some(true),
_ => None,
}
}
// returns true if the insertion of SetLastChunkType was the final push.
+// expects that iter iterates over a conjunct of Terms in reverse order.
fn insert_set_last_chunk_type(
state_stack: &mut Vec<TraversalState>,
- iter: impl Iterator<Item = TraversalState>,
+ mut iter: impl Iterator<Item = TraversalState>,
) -> bool {
let beg = state_stack.len();
let mut idx = beg;
if will_break {
state_stack.push(TraversalState::SetLastChunkType);
state_stack.push(traversal_st);
+
break;
} else {
state_stack.push(traversal_st);
}
fn probe_body_term(&mut self, term: &Term, term_loc: GenContext) {
+ let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() };
+
// second arg is true to iterate the root, which may be a variable
for term_ref in breadth_first_iter(term, true) {
- if let TermRef::Var(_, _, var_name) = term_ref {
- self.probe_body_var(Var::from(var_name), term_loc);
+ if let TermRef::Var(lvl, _, var_name) = term_ref {
+ let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), lvl, classify_info };
+ self.probe_body_var(var_name, term_loc, var_info);
+ }
+
+ if let Level::Shallow = term_ref.level() {
+ classify_info.arg_c += 1;
}
}
}
- fn probe_body_var(&mut self, var_name: Var, chunk_type: ChunkType) {
+ fn probe_body_var(&mut self, var_name: Var, term_loc: GenContext, var_info: VarInfo) {
let branch_info_v = self.branch_map.entry(var_name)
.or_insert_with(|| vec![]);
};
if needs_new_chunk {
- branch_info.chunks.push(ChunkInfo::new(self.current_chunk_num));
+ branch_info.chunks.push(ChunkInfo {
+ chunk_num: self.current_chunk_num,
+ term_loc,
+ vars: vec![],
+ });
}
let chunk_info = branch_info.chunks.last_mut().unwrap();
- chunk_info.vars.push(VarPtr::from(&var_name));
+ chunk_info.vars.push(var_info);
}
fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> {
_ => return Err(CompilationError::InvalidRuleHead),
}
+ let mut classify_info = ClassifyInfo {
+ arg_c: 0,
+ arity: term.arity(),
+ };
+
// false argument to breadth_first_iter because the root is not iterable.
for term_ref in breadth_first_iter(term, false) {
- if let TermRef::Var(_, _, var_name) = term_ref {
+ if let TermRef::Var(lvl, _, var_name) = term_ref {
// the body of the if let here is an inlined
// "probe_head_var". note the difference between it
// and "probe_body_var".
let needs_new_chunk = branch_info.chunks.is_empty();
if needs_new_chunk {
- branch_info.chunks.push(ChunkInfo::new(self.current_chunk_num));
+ branch_info.chunks.push(ChunkInfo {
+ chunk_num: self.current_chunk_num,
+ term_loc: GenContext::Head,
+ vars: vec![]
+ });
}
let chunk_info = branch_info.chunks.last_mut().unwrap();
- chunk_info.vars.push(VarPtr::from(&var_name));
+ let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), classify_info, lvl };
+
+ chunk_info.vars.push(var_info);
+ }
+
+ if let Level::Shallow = term_ref.level() {
+ classify_info.arg_c += 1;
}
}
}
}
Term::Clause(_, atom!(":"), mut terms) if terms.len() == 2 => {
+ let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
+
let predicate_name = terms.pop().unwrap();
let module_name = terms.pop().unwrap();
Term::Literal(_, Literal::Atom(module_name)),
Term::Literal(_, Literal::Atom(predicate_name)),
) => {
- if !ClauseType::is_inbuilt(name, 0) {
+ if !ClauseType::is_inbuilt(predicate_name, 0) {
state_stack.push(TraversalState::IncrChunkNum);
}
}
}
Term::Clause(cell, atom!("$call_with_inference_counting"), terms) if terms.len() == 1 => {
+ let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
+
for term in terms.iter() {
self.probe_body_term(term, term_loc);
}
state_stack.push(TraversalState::IncrChunkNum);
}
+ let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
+
for term in terms.iter() {
self.probe_body_term(term, term_loc);
}
),
);
}
+
_ => {
return Err(CompilationError::InadmissibleQueryTerm);
}
}
impl BranchMap {
- pub fn separate_and_classify_variables(&mut self) -> Vec<VarRecord> {
- let mut var_num = 0usize;
- let mut records = vec![];
+ pub fn separate_and_classify_variables(&mut self) -> VarData {
+ let mut var_num = 0usize;
+ let mut var_data = VarData {
+ records: vec![],
+ fixtures: VariableFixtures::new(),
+ };
for branches in self.values_mut() {
for branch in branches.iter_mut() {
let mut num_occurrences = 0;
let mut chunk_occurrences = vec![];
- for chunk in branch.chunks.iter_mut() {
- num_occurrences += chunk.vars.len();
-
- for var in chunk.vars.iter_mut() {
- var.set(Var::Generated(var_num));
- }
-
- chunk_occurrences.push(chunk.chunk_num);
- }
-
let classification = if branch.chunks.len() > 1 {
VarClassification::Perm
} else {
.unwrap_or(VarClassification::Void)
};
- records.push(VarRecord { classification, chunk_occurrences, num_occurrences });
+ for chunk in branch.chunks.iter_mut() {
+ num_occurrences += chunk.vars.len();
+
+ if let VarClassification::Temp = classification {
+ for var_info in chunk.vars.iter_mut() {
+ var_info.var_ptr.set(Var::Generated(var_num));
+ var_data.fixtures.mark_temp_var(
+ var_num,
+ var_info.lvl,
+ &var_info.classify_info,
+ chunk.term_loc,
+ );
+ }
+ } else {
+ for var_info in chunk.vars.iter_mut() {
+ var_info.var_ptr.set(Var::Generated(var_num));
+ }
+ }
+
+ chunk_occurrences.push(chunk.chunk_num);
+ }
+
+ let record = VarRecord { classification, chunk_occurrences, num_occurrences };
+ var_data.records.push(record);
+
var_num += 1;
}
}
- debug_assert_eq!(records.len(), var_num);
+ debug_assert_eq!(var_data.records.len(), var_num);
- records
+ var_data
}
}
};
}
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum GenContext {
Head,
Mid(usize),