functor!(atom!("intermediate"), [fixnum(i)])
}
ArithmeticTerm::Number(n) => {
- vec![HeapCellValue::from((n, arena))]
+ functor!(atom!("number"), [cell(HeapCellValue::from((n, arena)))])
}
}
}
lvl: Level,
context: GenContext,
code: &mut CodeDeque,
- );
+ ) -> RegType;
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
&mut self,
use crate::forms::*;
use crate::instructions::*;
use crate::iterators::*;
+use crate::machine::disjuncts::*;
use crate::machine::stack::Stack;
use crate::parser::ast::FocusedHeap;
use crate::targets::QueryInstruction;
Literal::Atom(name) if name == atom!("epsilon") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(f64::EPSILON)),
)),
- _ => return Err(ArithmeticError::NonEvaluableFunctor(c, 0)),
+ _ => return Err(ArithmeticError::NonEvaluableFunctor(HeapCellValue::from(c), 0)),
}
Ok(())
atom!("float_fractional_part") => Ok(Instruction::FloatFractionalPart(a1, t)),
atom!("sign") => Ok(Instruction::Sign(a1, t)),
atom!("\\") => Ok(Instruction::BitwiseComplement(a1, t)),
- _ => Err(ArithmeticError::NonEvaluableFunctor(Literal::Atom(name), 1)),
+ _ => Err(ArithmeticError::NonEvaluableFunctor(atom_as_cell!(name), 1)),
}
}
atom!("rem") => Ok(Instruction::Rem(a1, a2, t)),
atom!("gcd") => Ok(Instruction::Gcd(a1, a2, t)),
atom!("atan2") => Ok(Instruction::ATan2(a1, a2, t)),
- _ => Err(ArithmeticError::NonEvaluableFunctor(Literal::Atom(name), 2)),
+ _ => Err(ArithmeticError::NonEvaluableFunctor(atom_as_cell!(name), 2)),
}
}
self.get_binary_instr(name, a1, a2, ninterm)
}
_ => Err(ArithmeticError::NonEvaluableFunctor(
- Literal::Atom(name),
+ atom_as_cell!(name),
arity,
)),
}
let mut stack = Stack::uninitialized();
let mut iter = query_iterator::<false>(&mut src.heap, &mut stack, term_loc);
+ let chunk_num = context.chunk_num();
+
while let Some(term) = iter.next() {
read_heap_cell!(term,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
let lvl = iter.level();
- let var_ptr = src.var_locs.read_next_var_ptr_at_key(h).unwrap();
- let var_num = var_ptr.to_var_num().unwrap();
- let old_r = self.marker.get_var_binding(var_num);
-
- let r = if lvl == Level::Root {
- self.marker.mark_non_callable(var_num, arg, context, &mut code)
- } else if context.is_last() || old_r.reg_num() == 0 {
- let r = old_r;
-
- if r.reg_num() == 0 {
- self.marker.mark_var::<QueryInstruction>(
- var_num, lvl, context, &mut code,
- )
- } else {
- self.marker.increment_running_count(var_num);
- r
+
+ let r = match self.marker.var_data.var_locs_to_nums.get(VarPtrIndex { chunk_num, term_loc }) {
+ VarPtr::Numbered(var_num) => {
+ let old_r = self.marker.get_var_binding(var_num);
+
+ if lvl == Level::Root {
+ self.marker.mark_non_callable(var_num, arg, context, &mut code)
+ } else if context.is_last() || old_r.reg_num() == 0 {
+ let r = old_r;
+
+ if r.reg_num() == 0 {
+ self.marker.mark_var::<QueryInstruction>(
+ var_num, lvl, context, &mut code,
+ )
+ } else {
+ self.marker.increment_running_count(var_num);
+ r
+ }
+ } else {
+ self.marker.increment_running_count(var_num);
+ old_r
+ }
+ }
+ VarPtr::Anon => {
+ self.marker.mark_anon_var::<QueryInstruction>(lvl, context, &mut code)
}
- } else {
- self.marker.increment_running_count(var_num);
- old_r
};
self.interm.push(ArithmeticTerm::Reg(r));
_ => {
match Literal::try_from(term) {
Ok(lit) => push_literal(&mut self.interm, lit)?,
- _ => unreachable!()
+ _ => return Err(ArithmeticError::NonEvaluableFunctor(term, 0)),
}
}
);
}
}
+
impl PartialEq for Number {
fn eq(&self, rhs: &Self) -> bool {
match (self, rhs) {
}
}
+
impl Ord for Number {
fn cmp(&self, rhs: &Number) -> Ordering {
match (self, rhs) {
fn subterm_to_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
&mut self,
subterm: HeapCellValue,
- var_locs: &mut VarLocs,
heap_loc: usize,
context: GenContext,
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
target: &mut CodeDeque,
) -> Option<RegType> {
let subterm = unmark_cell_bits!(subterm);
+ let chunk_num = context.chunk_num();
read_heap_cell!(subterm,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = var_locs.read_next_var_ptr_at_key(h).unwrap();
-
- if var_ptr.is_anon() {
- Self::add_or_increment_void_instr::<Target>(target);
- } else {
- let var_num = var_ptr.to_var_num().unwrap();
-
- self.deep_var_instr::<Target>(
- var_num,
- context,
- target,
- );
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
+ match self.marker.var_data.var_locs_to_nums.get(VarPtrIndex { chunk_num, term_loc }) {
+ VarPtr::Numbered(var_num) => {
+ self.deep_var_instr::<Target>(
+ var_num,
+ context,
+ target,
+ );
+ }
+ VarPtr::Anon => {
+ Self::add_or_increment_void_instr::<Target>(target);
+ }
}
None
&mut self,
mut iter: Iter,
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
- var_locs: &mut VarLocs,
context: GenContext,
) -> CodeDeque
where
CodeGenerator<'b>: AddToFreeList<'a, Target>,
{
let mut target = CodeDeque::new();
+ let chunk_num = context.chunk_num();
while let Some(term) = iter.next() {
let lvl = iter.level();
let term = unmark_cell_bits!(term);
read_heap_cell!(term,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
if lvl == Level::Shallow {
- let var_ptr = var_locs.read_next_var_ptr_at_key(h).unwrap();
-
- if var_ptr.is_anon() {
- if let GenContext::Head = context {
- self.marker.advance_arg();
- } else {
- self.marker.mark_anon_var::<Target>(lvl, context, &mut target);
+ match self.marker.var_data.var_locs_to_nums.get(
+ VarPtrIndex { chunk_num, term_loc }
+ ) {
+ VarPtr::Numbered(var_num) => {
+ self.marker.mark_var::<Target>(
+ var_num,
+ lvl,
+ context,
+ &mut target,
+ );
+ }
+ VarPtr::Anon => {
+ if let GenContext::Head = context {
+ self.marker.advance_arg();
+ } else {
+ self.marker.mark_anon_var::<Target>(lvl, context, &mut target);
+ }
}
- } else {
- self.marker.mark_var::<Target>(
- var_ptr.to_var_num().unwrap(),
- lvl,
- context,
- &mut target,
- );
}
}
}
let (subterm_loc, subterm) = subterm_index(iter.deref(), subterm_loc);
self.subterm_to_instr::<Target>(
- subterm, var_locs, subterm_loc, context, index_ptrs, &mut target,
+ subterm, subterm_loc, context, index_ptrs, &mut target,
)
})
.collect();
let head_r_opt = self.subterm_to_instr::<Target>(
head,
- var_locs,
head_loc,
context,
index_ptrs,
let tail_r_opt = self.subterm_to_instr::<Target>(
tail,
- var_locs,
tail_loc,
context,
index_ptrs,
let (tail_loc, tail) = subterm_index(iter.deref(), heap_loc + 1);
self.subterm_to_instr::<Target>(
- tail, var_locs, tail_loc, context, index_ptrs, &mut target,
+ tail, tail_loc, context, index_ptrs, &mut target,
);
}
(HeapCellValueTag::PStrOffset, l) => {
target.push_back(Target::to_pstr(lvl, pstr_offset_atom, r, true));
self.subterm_to_instr::<Target>(
- tail, var_locs, tail_loc, context, index_ptrs, &mut target,
+ tail, tail_loc, context, index_ptrs, &mut target,
);
}
_ if lvl == Level::Shallow => {
context: GenContext,
code: &mut CodeDeque,
) -> Result<(), CompilationError> {
- let term = terms.heap[terms.nth_arg(term_loc, 1).unwrap()];
+ let first_arg_loc = terms.nth_arg(term_loc, 1).unwrap();
+ let first_arg = terms.deref_loc(first_arg_loc);
+
+ let chunk_num = context.chunk_num();
+ let mut variable_marker = |marker: &mut DebrayAllocator| {
+ read_heap_cell!(first_arg,
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, first_arg_loc) => {
+ match marker.var_data.var_locs_to_nums.get(
+ VarPtrIndex { chunk_num, term_loc: first_arg_loc },
+ ) {
+ VarPtr::Numbered(var_num) => {
+ Some(marker.mark_non_callable(
+ var_num,
+ 1,
+ context,
+ code,
+ ))
+ }
+ VarPtr::Anon => {
+ Some(marker.mark_anon_var::<QueryInstruction>(
+ Level::Shallow,
+ context,
+ code,
+ ))
+ }
+ }
+ }
+ _ => {
+ marker.advance_arg();
+ None
+ }
+ )
+ };
let call_instr = match ct {
&InlinedClauseType::CompareNumber(mut cmp) => {
self.marker.reset_arg(2);
let (mut lcode, at_1) =
- self.compile_arith_expr(terms, term_loc + 1, 1, context, 1)?;
-
- if !terms.deref_loc(term_loc + 1).is_var() {
- self.marker.advance_arg();
- }
+ if let Some(r) = variable_marker(&mut self.marker) {
+ (CodeDeque::default(), Some(ArithmeticTerm::Reg(r)))
+ } else {
+ self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)?
+ };
let (mut rcode, at_2) =
- self.compile_arith_expr(terms, term_loc + 2, 2, context, 2)?;
+ self.compile_arith_expr(terms, first_arg_loc + 1, 2, context, 2)?;
code.append(&mut lcode);
code.append(&mut rcode);
compare_number_instr!(cmp, at_1, at_2)
}
- InlinedClauseType::IsAtom(..) => read_heap_cell!(term,
- (HeapCellValueTag::Atom, (_name, arity)) => {
- if arity == 0 {
- instr!("$succeed")
- } else {
- instr!("$fail")
- }
- }
- (HeapCellValueTag::Char) => {
- instr!("$succeed")
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- self.marker.reset_arg(1);
-
- if var_ptr.is_anon() {
- instr!("$fail")
- } else {
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
-
- instr!("atom", r)
- }
- }
- _ => {
- instr!("$fail")
- }
- ),
- InlinedClauseType::IsAtomic(..) => read_heap_cell!(term,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
-
- if var_ptr.is_anon() {
- instr!("$fail")
- } else {
- self.marker.reset_arg(1);
-
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
+ InlinedClauseType::IsAtom(..) => {
+ self.marker.reset_arg(1);
- instr!("atomic", r)
- }
- }
- (HeapCellValueTag::Fixnum |
- HeapCellValueTag::Char |
- HeapCellValueTag::F64) => {
- instr!("$succeed")
- }
- (HeapCellValueTag::Cons, cons_ptr) => {
- match cons_ptr.get_tag() {
- ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("atom", r)
+ } else {
+ read_heap_cell!(first_arg,
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ if arity == 0 {
+ instr!("$succeed")
+ } else {
+ instr!("$fail")
+ }
+ }
+ (HeapCellValueTag::Char) => {
instr!("$succeed")
}
_ => {
instr!("$fail")
}
- }
+ )
}
- (HeapCellValueTag::Atom, (_name, arity)) => {
- if arity == 0 {
- instr!("$succeed")
- } else {
- instr!("$fail")
- }
- }
- (HeapCellValueTag::Lis
- | HeapCellValueTag::Str
- | HeapCellValueTag::PStrLoc
- | HeapCellValueTag::CStr) => {
- instr!("$fail")
- }
- _ => {
- if Literal::try_from(term).is_ok() {
- instr!("$succeed")
- } else {
- instr!("$fail")
- }
+ }
+ InlinedClauseType::IsAtomic(..) => {
+ self.marker.reset_arg(1);
+
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("atomic", r)
+ } else {
+ read_heap_cell!(first_arg,
+ (HeapCellValueTag::Fixnum |
+ HeapCellValueTag::Char |
+ HeapCellValueTag::F64) => {
+ instr!("$succeed")
+ }
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match cons_ptr.get_tag() {
+ ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
+ instr!("$succeed")
+ }
+ _ => {
+ instr!("$fail")
+ }
+ }
+ }
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ if arity == 0 {
+ instr!("$succeed")
+ } else {
+ instr!("$fail")
+ }
+ }
+ (HeapCellValueTag::Lis
+ | HeapCellValueTag::Str
+ | HeapCellValueTag::PStrLoc
+ | HeapCellValueTag::CStr) => {
+ instr!("$fail")
+ }
+ _ => {
+ if Literal::try_from(first_arg).is_ok() {
+ instr!("$succeed")
+ } else {
+ instr!("$fail")
+ }
+ }
+ )
}
- ),
+ }
InlinedClauseType::IsCompound(..) => {
- read_heap_cell!(term,
- (HeapCellValueTag::Atom, (_, arity)) => {
- if arity > 0 {
+ self.marker.reset_arg(1);
+
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("compound", r)
+ } else {
+ read_heap_cell!(first_arg,
+ (HeapCellValueTag::Atom, (_, arity)) => {
+ if arity > 0 {
+ instr!("$succeed")
+ } else {
+ instr!("$fail")
+ }
+ }
+ (HeapCellValueTag::Lis
+ | HeapCellValueTag::Str
+ | HeapCellValueTag::PStrLoc
+ | HeapCellValueTag::CStr) => {
instr!("$succeed")
- } else {
- instr!("$fail")
}
- }
- (HeapCellValueTag::Lis
- | HeapCellValueTag::Str
- | HeapCellValueTag::PStrLoc
- | HeapCellValueTag::CStr) => {
- instr!("$succeed")
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
-
- if var_ptr.is_anon() {
+ _ => {
instr!("$fail")
- } else {
- self.marker.reset_arg(1);
-
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
-
- instr!("compound", r)
}
- }
- _ => {
- instr!("$fail")
- }
- )
+ )
+ }
}
InlinedClauseType::IsRational(..) => {
- read_heap_cell!(term,
- (HeapCellValueTag::Cons, cons_ptr) => {
- match cons_ptr.get_tag() {
- ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
- instr!("$succeed")
- }
- _ => {
- instr!("$fail")
+ self.marker.reset_arg(1);
+
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("rational", r)
+ } else {
+ read_heap_cell!(first_arg,
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match cons_ptr.get_tag() {
+ ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
+ instr!("$succeed")
+ }
+ _ => {
+ instr!("$fail")
+ }
}
}
- }
- (HeapCellValueTag::Fixnum) => {
- instr!("$succeed")
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- self.marker.reset_arg(1);
-
- if var_ptr.is_anon() {
+ (HeapCellValueTag::Fixnum) => {
+ instr!("$succeed")
+ }
+ _ => {
instr!("$fail")
- } else {
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
-
- instr!("rational", r)
}
- }
- _ => {
- instr!("$fail")
- }
- )
- }
- InlinedClauseType::IsFloat(..) => read_heap_cell!(term,
- (HeapCellValueTag::F64) => {
- instr!("$succeed")
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- self.marker.reset_arg(1);
-
- if var_ptr.is_anon() {
- instr!("$fail")
- } else {
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
-
- instr!("float", r)
- }
- }
- _ => {
- instr!("$fail")
+ )
}
- ),
- InlinedClauseType::IsNumber(..) => read_heap_cell!(term,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- self.marker.reset_arg(1);
-
- if var_ptr.is_anon() {
- instr!("$fail")
- } else {
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
+ }
+ InlinedClauseType::IsFloat(..) => {
+ self.marker.reset_arg(1);
- instr!("number", r)
- }
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("float", r)
+ } else {
+ read_heap_cell!(first_arg,
+ (HeapCellValueTag::F64) => {
+ instr!("$succeed")
+ }
+ _ => {
+ instr!("$fail")
+ }
+ )
}
- _ => {
- if Number::try_from(term).is_ok() {
+ }
+ InlinedClauseType::IsNumber(..) => {
+ self.marker.reset_arg(1);
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("number", r)
+ } else {
+ if Number::try_from(first_arg).is_ok() {
instr!("$succeed")
} else {
instr!("$fail")
}
}
- ),
- InlinedClauseType::IsNonVar(..) => read_heap_cell!(term,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- self.marker.reset_arg(1);
+ }
+ InlinedClauseType::IsNonVar(..) => {
+ self.marker.reset_arg(1);
- if var_ptr.is_anon() {
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("nonvar", r)
+ } else {
+ if first_arg.is_var() {
instr!("$fail")
} else {
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
-
- instr!("nonvar", r)
+ instr!("$succeed")
}
}
- _ => {
- instr!("$succeed")
- }
- ),
+ }
InlinedClauseType::IsInteger(..) => {
- read_heap_cell!(term,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- self.marker.reset_arg(1);
+ self.marker.reset_arg(1);
- if var_ptr.is_anon() {
- instr!("$fail")
- } else {
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
-
- instr!("integer", r)
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("integer", r)
+ } else {
+ match Number::try_from(first_arg) {
+ Ok(Number::Integer(_) | Number::Fixnum(_)) => {
+ instr!("$succeed")
}
- }
- _ => {
- match Number::try_from(term) {
- Ok(Number::Integer(_) | Number::Fixnum(_)) => {
- instr!("$succeed")
- }
- _ => {
- instr!("$fail")
- }
+ _ => {
+ instr!("$fail")
}
}
- )
- }
- InlinedClauseType::IsVar(..) => read_heap_cell!(term,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- self.marker.reset_arg(1);
+ }
+ },
+ InlinedClauseType::IsVar(..) => {
+ self.marker.reset_arg(1);
- if var_ptr.is_anon() {
+ if let Some(r) = variable_marker(&mut self.marker) {
+ instr!("var", r)
+ } else {
+ if first_arg.is_var() {
instr!("$succeed")
} else {
- let r = self.marker.mark_non_callable(
- var_ptr.to_var_num().unwrap(),
- 1,
- context,
- code,
- );
-
- instr!("var", r)
+ instr!("$fail")
}
}
- _ => {
- instr!("$fail")
- }
- ),
+ },
};
// inlined predicates are never counted, so this overrides nothing.
self.add_call(code, call_instr, CallPolicy::Counted);
-
Ok(())
}
};
let at = read_heap_cell!(var,
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- let var_num = var_ptr.to_var_num().unwrap();
-
- if self.marker.var_data.records[var_num].num_occurrences > 1 {
- self.marker.mark_var::<QueryInstruction>(
- var_num,
- Level::Shallow,
- context,
- code,
- );
-
- self.marker.mark_safe_var_unconditionally(var_num);
- compile_expr!(self, terms, context, code)
- } else {
- /*
- if var.is_var() {
- let h = var.get_value() as usize;
-
- let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
- let var_num = var_ptr.to_var_num().unwrap();
-
- // if var is an anonymous variable, insert
- // is/2 call so that an instantiation error is
- // thrown when the predicate is run.
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
+ let chunk_num = context.chunk_num();
+ match self.marker.var_data.var_locs_to_nums.get(
+ VarPtrIndex { chunk_num, term_loc },
+ ) {
+ VarPtr::Numbered(var_num) => {
if self.marker.var_data.records[var_num].num_occurrences > 1 {
- let r = self.marker.mark_var::<QueryInstruction>(
+ self.marker.mark_var::<QueryInstruction>(
var_num,
Level::Shallow,
context,
);
self.marker.mark_safe_var_unconditionally(var_num);
-
- let at = ArithmeticTerm::Reg(r);
- self.add_call(code, instr!("$get_number", at), call_policy);
-
- return Ok(());
}
}
- */
+ VarPtr::Anon => {}
+ };
- compile_expr!(self, terms, context, code)
- }
+ compile_expr!(self, terms, context, code)
}
_ => {
if Number::try_from(var).is_ok() {
let at = at.unwrap_or(interm!(1));
self.add_call(code, instr!("is", temp_v!(1), at), call_policy);
-
Ok(())
}
fn compile_seq(
&mut self,
- terms: &mut FocusedHeap,
+ focused_heap: &mut FocusedHeap,
clauses: &ChunkedTermVec,
code: &mut CodeDeque,
) -> Result<(), CompilationError> {
- let mut chunk_num = 0;
let mut branch_code_stack = BranchCodeStack::new();
let mut clause_iter = ClauseIterator::new(clauses);
while let Some(clause_item) = clause_iter.next() {
match clause_item {
- ClauseItem::Chunk(chunk) => {
- for (idx, term) in chunk.iter().enumerate() {
- let context = if idx + 1 < chunk.len() {
+ ClauseItem::Chunk { chunk_num, terms } => {
+ for (idx, term) in terms.iter().enumerate() {
+ let context = if idx + 1 < terms.len() {
GenContext::Mid(chunk_num)
} else {
self.marker.in_tail_position = clause_iter.in_tail_position();
..
},
) => self.compile_is_call(
- terms,
+ focused_heap,
clause.term_loc(),
branch_code_stack.code(code),
context,
},
) => self.compile_inlined(
ct,
- terms,
+ focused_heap,
clause.term_loc(),
context,
branch_code_stack.code(code),
}
QueryTerm::Clause(clause) => {
self.compile_query_line(
- terms,
+ focused_heap,
clause,
context,
branch_code_stack.code(code),
}
}
- chunk_num += 1;
self.marker.in_tail_position = false;
self.marker.reset_contents();
}
let fact = self.compile_target::<FactInstruction, _>(
iter,
&IndexMap::with_hasher(FxBuildHasher::default()),
- &mut term.var_locs,
GenContext::Head,
);
let compiled_fact = self.compile_target::<FactInstruction, _>(
iter,
&IndexMap::with_hasher(FxBuildHasher::default()),
- &mut fact.term.var_locs,
GenContext::Head,
);
let query = self.compile_target::<QueryInstruction, _>(
iter,
&clause.code_indices,
- &mut term.var_locs,
context,
);
use crate::allocator::*;
use crate::atom_table::*;
use crate::codegen::SubsumedBranchHits;
-use crate::forms::Level;
+use crate::forms::{GenContext, Level};
use crate::instructions::*;
-use crate::machine::disjuncts::VarData;
+use crate::machine::disjuncts::*;
use crate::machine::heap::{heap_bound_deref, heap_bound_store};
use crate::parser::ast::*;
use crate::targets::*;
VarAlloc::Temp { safety, .. } => {
*safety = VarSafetyStatus::unneeded(branch_designator);
}
- _ => unreachable!(),
+ _ => {
+ // the (permanent) variable might have been freed by
+ // this point, in which case we do nothing.
+ }
}
}
lvl: Level,
context: GenContext,
code: &mut CodeDeque,
- ) {
+ ) -> RegType {
let r = RegType::Temp(self.alloc_reg_to_non_var());
match lvl {
code.push_back(Target::argument_to_variable(r, k));
}
};
+
+ r
}
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
continue;
}
- let h = var.get_value() as usize;
- let var_ptr = term.var_locs.peek_next_var_ptr_at_key(h).unwrap();
- let var_num = var_ptr.to_var_num().unwrap();
- let r = self.get_var_binding(var_num);
-
- if !r.is_perm() && r.reg_num() == 0 {
- self.in_use.insert(idx + 1);
- self.shallow_temp_mappings.insert(idx + 1, var_num);
- self.var_data.records[var_num]
- .allocation
- .set_register(idx + 1);
+ let term_loc = var.get_value() as usize;
+
+ match self.var_data.var_locs_to_nums.get(
+ VarPtrIndex { chunk_num: 0, term_loc },
+ ) {
+ VarPtr::Numbered(var_num) => {
+ let r = self.get_var_binding(var_num);
+
+ if !r.is_perm() && r.reg_num() == 0 {
+ self.in_use.insert(idx + 1);
+ self.shallow_temp_mappings.insert(idx + 1, var_num);
+ self.var_data.records[var_num]
+ .allocation
+ .set_register(idx + 1);
+ }
+ }
+ VarPtr::Anon => {}
}
}
}
Counted,
}
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum GenContext {
+ Head,
+ Mid(usize),
+ Last(usize), // Mid & Last: chunk_num
+}
+
+impl GenContext {
+ #[inline]
+ pub fn chunk_num(&self) -> usize {
+ match self {
+ GenContext::Head => 0,
+ &GenContext::Mid(cn) | &GenContext::Last(cn) => cn,
+ }
+ }
+
+ #[inline]
+ pub fn chunk_type(&self) -> ChunkType {
+ match self {
+ GenContext::Head => ChunkType::Head,
+ GenContext::Mid(_) => ChunkType::Mid,
+ GenContext::Last(_) => ChunkType::Last,
+ }
+ }
+
+ #[inline]
+ pub fn is_last(self) -> bool {
+ matches!(self, GenContext::Last(_))
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ChunkType {
Head,
#[derive(Debug)]
pub enum ChunkedTerms {
Branch(Vec<VecDeque<ChunkedTerms>>),
- Chunk(VecDeque<QueryTerm>),
+ Chunk { chunk_num: usize, terms: VecDeque<QueryTerm> },
}
#[derive(Debug)]
pub struct ChunkedTermVec {
pub chunk_vec: VecDeque<ChunkedTerms>,
+ pub current_chunk_num: usize,
+ pub current_chunk_type: ChunkType,
}
impl Deref for ChunkedTermVec {
pub fn new() -> Self {
Self {
chunk_vec: VecDeque::new(),
+ current_chunk_num: 0,
+ current_chunk_type: ChunkType::Mid,
}
}
.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
}
+ pub fn push_branch_arm(&mut self, branch: VecDeque<ChunkedTerms>) {
+ match self.chunk_vec.back_mut().unwrap() {
+ ChunkedTerms::Branch(branches) => {
+ branches.push(branch);
+ }
+ ChunkedTerms::Chunk { .. } => {
+ self.chunk_vec.push_back(ChunkedTerms::Branch(vec![branch]));
+ }
+ }
+ }
+
+ pub fn try_set_chunk_at_inlined_boundary(&mut self) -> bool {
+ if self.current_chunk_type.is_last() {
+ self.current_chunk_type = ChunkType::Mid;
+ self.current_chunk_num += 1;
+ true
+ } else {
+ false
+ }
+ }
+
+ pub fn try_set_chunk_at_call_boundary(&mut self) -> bool {
+ if self.current_chunk_type.is_last() {
+ self.current_chunk_num += 1;
+ true
+ } else {
+ self.current_chunk_type = ChunkType::Last;
+ false
+ }
+ }
+
#[inline]
pub fn add_chunk(&mut self) {
- self.chunk_vec
- .push_back(ChunkedTerms::Chunk(VecDeque::from(vec![])));
+ let chunk = ChunkedTerms::Chunk {
+ chunk_num: self.current_chunk_num,
+ terms: VecDeque::from(vec![]),
+ };
+ self.chunk_vec.push_back(chunk);
+ }
+
+ pub fn current_gen_context(&self) -> GenContext {
+ self.current_chunk_type.to_gen_context(self.current_chunk_num)
}
pub fn push_chunk_term(&mut self, term: QueryTerm) {
match self.chunk_vec.back_mut() {
Some(ChunkedTerms::Branch(_)) => {
- self.chunk_vec
- .push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
+ let chunk = ChunkedTerms::Chunk {
+ chunk_num: self.current_chunk_num,
+ terms: VecDeque::from(vec![term]),
+ };
+
+ self.chunk_vec.push_back(chunk);
}
- Some(ChunkedTerms::Chunk(chunk)) => {
- chunk.push_back(term);
+ Some(ChunkedTerms::Chunk { terms, .. }) => {
+ terms.push_back(term);
}
None => {
- self.chunk_vec
- .push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
+ let chunk = ChunkedTerms::Chunk {
+ chunk_num: self.current_chunk_num,
+ terms: VecDeque::from(vec![term]),
+ };
+
+ self.chunk_vec.push_back(chunk);
}
}
}
toplevel_spec: Option<DirectedOp>,
last_item_idx: usize,
parent_of_first_op: Option<(DirectedOp, usize)>,
- pub var_names: IndexMap<HeapCellValue, VarPtr>,
+ pub var_names: IndexMap<HeapCellValue, Var>,
pub numbervars_offset: Integer,
pub numbervars: bool,
pub quoted: bool,
if let Some(var) = self.var_names.get(&cell) {
read_heap_cell!(cell,
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
- return Some(var.borrow().to_string());
+ return Some(var.to_string());
}
_ => {
self.iter.push_stack(h);
// short-circuits handle_heap_term.
// self.iter.pop_stack();
- let var_str = var.borrow().to_string();
+ let var_str = var.to_string();
push_space_if_amb!(self, &var_str, {
append_str!(self, &var_str);
Some(var) => {
// If the term is bound to a named variable,
// print the variable's name to output.
- let var_str = var.borrow().to_string();
+ let var_str = var.to_string();
push_space_if_amb!(self, &var_str, {
append_str!(self, &var_str);
printer
.var_names
- .insert(list_loc_as_cell!(1), VarPtr::from("L"));
+ .insert(list_loc_as_cell!(1), Rc::new("L".to_string()));
let output = printer.print();
printer
.var_names
- .insert(list_loc_as_cell!(1), VarPtr::from("L"));
+ .insert(list_loc_as_cell!(1), Rc::new("L".to_string()));
let output = printer.print();
FirstBranch(usize),
NextBranch,
BranchEnd(usize),
- Chunk(&'a VecDeque<QueryTerm>),
+ Chunk { chunk_num: usize, terms: &'a VecDeque<QueryTerm> },
}
#[derive(Debug)]
while let Some(state) = self.state_stack.pop() {
match state {
- ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => {
- depth += 1;
- }
+ ClauseIteratorState::RemainingBranches(terms, focus)
+ if terms.len() == focus => {
+ depth += 1;
+ }
_ => {
self.state_stack.push(state);
break;
fn next(&mut self) -> Option<Self::Item> {
while let Some(state) = self.state_stack.pop() {
match state {
- ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => {
- if focus + 1 < chunks.len() {
- self.state_stack
- .push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
- } else {
- self.remaining_chunks_on_stack -= 1;
- }
-
- match &chunks[focus] {
- ChunkedTerms::Branch(branches) => {
+ ClauseIteratorState::RemainingChunks(chunks, focus)
+ if focus < chunks.len() => {
+ if focus + 1 < chunks.len() {
self.state_stack
- .push(ClauseIteratorState::RemainingBranches(branches, 0));
+ .push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
+ } else {
+ self.remaining_chunks_on_stack -= 1;
}
- ChunkedTerms::Chunk(chunk) => {
- return Some(ClauseItem::Chunk(chunk));
+
+ match &chunks[focus] {
+ ChunkedTerms::Branch(branches) => {
+ self.state_stack
+ .push(ClauseIteratorState::RemainingBranches(branches, 0));
+ }
+ &ChunkedTerms::Chunk { chunk_num, ref terms } => {
+ return Some(ClauseItem::Chunk { chunk_num, terms });
+ }
}
}
- }
ClauseIteratorState::RemainingChunks(chunks, focus) => {
debug_assert_eq!(chunks.len(), focus);
}
) -> Result<Number, MachineStub> {
let stub_gen = || functor_stub(atom!("is"), 2);
- let root_loc = if value.is_ref() {
+ let root_loc = if value.is_ref() && !value.is_stack_var() {
value.get_value() as usize
} else {
let type_error = self.type_error(ValidType::Evaluable, value);
term_reg: RegType,
vars: Vec<HeapCellValue>,
) -> Result<(), SessionError> {
- let cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
-
- // append the variables of vars.
- let focus = cell.get_value() as usize;
- let header_loc = term_nth_arg(&self.machine_st.heap, focus, 0).unwrap();
- let name = term_name(&self.machine_st.heap, header_loc).unwrap();
- let old_arity = term_arity(&self.machine_st.heap, header_loc);
+ let body_cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
let new_header_loc = self.machine_st.heap.len();
- let new_arity = old_arity + vars.len();
-
- self.machine_st.heap.push(atom_as_cell!(name, new_arity));
+ let arity = vars.len();
- for idx in header_loc + 1 .. header_loc + 1 + old_arity {
- self.machine_st.heap.push(self.machine_st.heap[idx]);
- }
+ self.machine_st.heap.push(atom_as_cell!(atom!(""), arity));
for var in vars {
self.machine_st.heap.push(var);
}
- let value = if new_arity > 0 {
+ let head_loc = if arity > 0 {
str_loc_as_cell!(new_header_loc)
} else {
heap_loc_as_cell!(new_header_loc)
};
- let mut compile = |cell| {
+ let term_loc = self.machine_st.heap.len();
+
+ self.machine_st.heap.push(atom_as_cell!(atom!(":-"), 2));
+ self.machine_st.heap.push(head_loc);
+ self.machine_st.heap.push(body_cell);
+
+ let mut compile = || {
use crate::heap_iter::eager_stackful_preorder_iter;
let mut loader: Loader<'_, InlineLoadState<'_>> =
Loader::new(self, InlineTermStream {});
- let mut term = loader.copy_term_from_heap(cell);
+ let mut term = loader.copy_term_from_heap(str_loc_as_cell!(term_loc));
let settings = CodeGenSettings {
global_clock_tick: None,
let value = term.heap[term.focus];
- term.var_locs = var_locs_from_iter(
+ term.inverse_var_locs = inverse_var_locs_from_iter(
eager_stackful_preorder_iter(&mut term.heap, value),
);
loader.compile_standalone_clause(term, settings)
};
- let StandaloneCompileResult { clause_code, .. } = compile(value)?;
+ let StandaloneCompileResult { clause_code, .. } = compile()?;
self.code.extend(clause_code);
Ok(())
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ClassifiedVar {
+ Anon { term_loc: usize },
+ InSitu { var_num: usize },
+ Generated { term_loc: usize },
+}
+
+impl ClassifiedVar {
+ fn term_loc(&self) -> Option<usize> {
+ if let &ClassifiedVar::Generated { term_loc } = self {
+ Some(term_loc)
+ } else {
+ None
+ }
+ }
+}
+
+fn to_classified_var(inverse_var_locs: &InverseVarLocs, term_loc: usize) -> ClassifiedVar {
+ if inverse_var_locs.contains_key(&term_loc) {
+ ClassifiedVar::Generated { term_loc }
+ } else {
+ ClassifiedVar::Anon { term_loc }
+ }
+}
+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct VarInfo {
- var_ptr: VarPtr,
+ var: ClassifiedVar,
chunk_type: ChunkType,
classify_info: ClassifyInfo,
lvl: Level,
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ChunkInfo {
- chunk_num: usize,
term_loc: GenContext,
// pointer to incidence, term occurrence arity.
vars: Vec<VarInfo>,
}
}
-type BranchMapInt = IndexMap<VarPtr, Vec<BranchInfo>>;
+type BranchMapInt = IndexMap<ClassifiedVar, Vec<BranchInfo>>;
#[derive(Debug, Clone)]
pub struct BranchMap(BranchMapInt);
pub struct VariableClassifier {
call_policy: CallPolicy,
current_branch_num: BranchNumber,
- current_chunk_num: usize,
- current_chunk_type: ChunkType,
branch_map: BranchMap,
var_num: usize,
root_set: RootSet,
global_cut_var_num_override: Option<usize>,
}
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub struct VarPtrIndex {
+ pub chunk_num: usize,
+ pub term_loc: usize,
+}
+
+#[derive(Debug)]
+pub enum VarPtr {
+ Numbered(usize),
+ Anon,
+}
+
+#[derive(Debug, Default)]
+pub struct VarLocsToNums {
+ map: IndexMap<VarPtrIndex, usize>,
+}
+
+impl VarLocsToNums {
+ pub fn insert(&mut self, key: VarPtrIndex, var_num: usize) {
+ self.map.insert(key, var_num);
+ }
+
+ pub fn get(&self, idx: VarPtrIndex) -> VarPtr {
+ self.map.get(&idx)
+ .cloned()
+ .map(VarPtr::Numbered)
+ .unwrap_or_else(|| VarPtr::Anon)
+ }
+}
+
#[derive(Debug, Default)]
pub struct VarData {
pub records: VariableRecords,
pub global_cut_var_num: Option<usize>,
pub allocates: bool,
+ pub var_locs_to_nums: VarLocsToNums,
}
impl VarData {
match build_stack.front_mut() {
Some(ChunkedTerms::Branch(_)) => {
- build_stack.push_front(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
+ build_stack.push_front(ChunkedTerms::Chunk {
+ chunk_num: 0,
+ terms: VecDeque::from(vec![term]),
+ });
}
- Some(ChunkedTerms::Chunk(chunk)) => {
- chunk.push_front(term);
+ Some(ChunkedTerms::Chunk { terms, .. }) => {
+ terms.push_front(term);
}
None => {
unreachable!()
Self {
call_policy,
current_branch_num: BranchNumber::default(),
- current_chunk_num: 0,
- current_chunk_type: ChunkType::Head,
branch_map: BranchMap(BranchMapInt::new()),
root_set: RootSet::new(),
var_num: 0,
Ok(self.branch_map.separate_and_classify_variables(
self.var_num,
self.global_cut_var_num,
- self.current_chunk_num,
+ 0,
))
}
let mut var_data = self.branch_map.separate_and_classify_variables(
self.var_num,
self.global_cut_var_num,
- self.current_chunk_num,
+ query_terms.current_chunk_num,
);
var_data.emit_initial_get_level(&mut query_terms);
}
}
- fn try_set_chunk_at_inlined_boundary(&mut self) -> bool {
- if self.current_chunk_type.is_last() {
- self.current_chunk_type = ChunkType::Mid;
- self.current_chunk_num += 1;
- true
- } else {
- false
- }
- }
-
- fn try_set_chunk_at_call_boundary(&mut self) -> bool {
- if self.current_chunk_type.is_last() {
- self.current_chunk_num += 1;
- true
- } else {
- self.current_chunk_type = ChunkType::Last;
- false
- }
- }
-
fn probe_body_term(
&mut self,
arg_c: usize,
arity: usize,
term: &mut FocusedHeap,
term_loc: usize,
+ context: GenContext,
) {
let classify_info = ClassifyInfo { arg_c, arity };
}
let var_loc = subterm.get_value() as usize;
- let var_ptr = term.var_locs.read_next_var_ptr_at_key(var_loc).unwrap();
-
- self.probe_body_var(VarInfo {
- var_ptr: var_ptr.clone(),
- lvl,
- classify_info,
- chunk_type: self.current_chunk_type,
- });
+ let var = to_classified_var(&term.inverse_var_locs, var_loc);
+
+ self.probe_body_var(
+ context,
+ VarInfo {
+ var,
+ lvl,
+ classify_info,
+ chunk_type: context.chunk_type(),
+ },
+ );
}
}
- fn probe_body_var(&mut self, var_info: VarInfo) {
- let term_loc = self
- .current_chunk_type
- .to_gen_context(self.current_chunk_num);
-
- let branch_info_v = self.branch_map.entry(var_info.var_ptr.clone()).or_default();
+ fn probe_body_var(&mut self, context: GenContext, var_info: VarInfo) {
+ let chunk_num = context.chunk_num();
+ let branch_info_v = self.branch_map.entry(var_info.var)
+ .or_default();
let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
!self.root_set.contains(&last_bi.branch_num)
let branch_info = branch_info_v.last_mut().unwrap();
let needs_new_chunk = if let Some(last_ci) = branch_info.chunks.last() {
- last_ci.chunk_num != self.current_chunk_num
+ last_ci.term_loc.chunk_num() != chunk_num
} else {
true
};
if needs_new_chunk {
branch_info.chunks.push(ChunkInfo {
- chunk_num: self.current_chunk_num,
- term_loc,
+ term_loc: context,
vars: vec![],
});
}
chunk_info.vars.push(var_info);
}
- fn probe_in_situ_var(&mut self, var_num: usize) {
+ fn probe_in_situ_var(&mut self, context: GenContext, var_num: usize) {
let classify_info = ClassifyInfo { arg_c: 1, arity: 1 };
let var_info = VarInfo {
- var_ptr: VarPtr::from(Var::InSitu(var_num)),
+ var: ClassifiedVar::InSitu { var_num },
classify_info,
- chunk_type: self.current_chunk_type,
+ chunk_type: context.chunk_type(),
lvl: Level::Shallow,
};
- self.probe_body_var(var_info);
+ self.probe_body_var(context, var_info);
}
fn classify_head_variables(
continue;
}
- let h = subterm.get_value() as usize;
- let var_ptr = term.var_locs.read_next_var_ptr_at_key(h).unwrap().clone();
+ let term_loc = subterm.get_value() as usize;
+ let var = to_classified_var(&term.inverse_var_locs, term_loc);
// the body of the if let here is an inlined
// "probe_head_var". note the difference between it
// and "probe_body_var".
- let branch_info_v = self.branch_map.entry(var_ptr.clone()).or_default();
+ let branch_info_v = self.branch_map.entry(var).or_default();
let needs_new_branch = branch_info_v.is_empty();
if needs_new_branch {
if needs_new_chunk {
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();
let var_info = VarInfo {
- var_ptr,
+ var,
classify_info,
- chunk_type: self.current_chunk_type,
+ chunk_type: ChunkType::Head,
lvl,
};
Ok(())
}
- fn new_cut_state(&mut self) -> TraversalState {
+ fn new_cut_state(&mut self, context: GenContext) -> TraversalState {
let (var_num, is_global) = if let Some(var_num) = self.global_cut_var_num_override {
(var_num, false)
} else if let Some(var_num) = self.global_cut_var_num {
(var_num, true)
};
- self.probe_in_situ_var(var_num);
+ self.probe_in_situ_var(context, var_num);
TraversalState::Cut { var_num, is_global }
}
}];
let mut build_stack = ChunkedTermVec::new();
- self.current_chunk_type = ChunkType::Mid;
-
'outer: while let Some(traversal_st) = state_stack.pop() {
match traversal_st {
TraversalState::AddBranchNum(branch_num) => {
TraversalState::BuildDisjunct(preceding_len) => {
flatten_into_disjunct(&mut build_stack, preceding_len);
- self.current_chunk_type = ChunkType::Mid;
- self.current_chunk_num += 1;
+ build_stack.current_chunk_type = ChunkType::Mid;
+ build_stack.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_num += 1;
+ build_stack.current_chunk_type = ChunkType::Mid;
+ build_stack.current_chunk_num += 1;
}
TraversalState::GetCutPoint { var_num, prev_b } => {
- if self.try_set_chunk_at_inlined_boundary() {
+ if build_stack.try_set_chunk_at_inlined_boundary() {
build_stack.add_chunk();
}
- self.probe_in_situ_var(var_num);
+ let context = build_stack.current_gen_context();
+ self.probe_in_situ_var(context, var_num);
build_stack.push_chunk_term(QueryTerm::GetCutPoint { var_num, prev_b });
}
TraversalState::OverrideGlobalCutVar(var_num) => {
self.global_cut_var_num_override = old_override;
}
TraversalState::Cut { var_num, is_global } => {
- if self.try_set_chunk_at_inlined_boundary() {
+ if build_stack.try_set_chunk_at_inlined_boundary() {
build_stack.add_chunk();
}
- self.probe_in_situ_var(var_num);
+ let context = build_stack.current_gen_context();
+ self.probe_in_situ_var(context, var_num);
build_stack.push_chunk_term(if is_global {
QueryTerm::GlobalCut(var_num)
});
}
TraversalState::CutPrev(var_num) => {
- if self.try_set_chunk_at_inlined_boundary() {
+ if build_stack.try_set_chunk_at_inlined_boundary() {
build_stack.add_chunk();
}
- self.probe_in_situ_var(var_num);
+ let context = build_stack.current_gen_context();
+ self.probe_in_situ_var(context, var_num);
build_stack.push_chunk_term(QueryTerm::LocalCut {
var_num,
mut term_loc,
} => {
// return true iff new chunk should be added.
- let update_chunk_data = |classifier: &mut Self, key: PredicateKey| {
+ let update_chunk_data = |build_stack: &mut ChunkedTermVec, key: PredicateKey| {
if ClauseType::is_inlined(key.0, key.1) {
- classifier.try_set_chunk_at_inlined_boundary()
+ build_stack.try_set_chunk_at_inlined_boundary()
} else {
- classifier.try_set_chunk_at_call_boundary()
+ build_stack.try_set_chunk_at_call_boundary()
}
};
macro_rules! add_chunk {
- ($classifier:ident, $key:expr, $tag:expr, $term_loc:expr) => {{
- if update_chunk_data($classifier, $key) {
+ ($key:expr, $tag:expr, $term_loc:expr) => {{
+ if update_chunk_data(&mut build_stack, $key) {
build_stack.add_chunk();
}
+ let context = build_stack.current_gen_context();
+
for (arg_c, term_loc) in
($term_loc + 1 ..= $term_loc + $key.1).enumerate()
{
- $classifier.probe_body_term(arg_c + 1, $key.1, terms, term_loc);
+ self.probe_body_term(arg_c + 1, $key.1, terms, term_loc, context);
}
build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term(
$key,
terms.as_ref_mut($term_loc),
HeapCellValue::build_with($tag, $term_loc as u64),
- $classifier.call_policy,
+ self.call_policy,
)));
}};
}
macro_rules! add_qualified_chunk {
- ($classifier:ident, $module_name:expr, $key:expr, $tag:expr, $term_loc:expr) => {{
- if update_chunk_data($classifier, $key) {
+ ($module_name:expr, $key:expr, $tag:expr, $term_loc:expr) => {{
+ if update_chunk_data(&mut build_stack, $key) {
build_stack.add_chunk();
}
+ let context = build_stack.current_gen_context();
+
for (arg_c, term_loc) in
($term_loc + 1..$term_loc + $key.1 + 1).enumerate()
{
- $classifier.probe_body_term(arg_c + 1, $key.1, terms, term_loc);
+ self.probe_body_term(arg_c + 1, $key.1, terms, term_loc, context);
}
build_stack.push_chunk_term(QueryTerm::Clause(
$module_name,
terms.as_ref_mut($term_loc),
HeapCellValue::build_with($tag, $term_loc as u64),
- $classifier.call_policy,
+ self.call_policy,
),
));
}};
continue;
}
- add_chunk!(self, (name, 2), HeapCellValueTag::Str, subterm_loc);
+ add_chunk!((name, 2), HeapCellValueTag::Str, subterm_loc);
}
(atom!(","), 2) => {
let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
TraversalState::BuildFinalDisjunct(build_stack_len);
}
- self.current_chunk_type = ChunkType::Mid;
- self.current_chunk_num += 1;
+ build_stack.current_chunk_type = ChunkType::Mid;
+ build_stack.current_chunk_num += 1;
}
(atom!("->"), 2) => {
let if_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
});
state_stack.push(TraversalState::AddBranchNum(branch_num));
- self.current_chunk_type = ChunkType::Mid;
- self.current_chunk_num += 1;
+ build_stack.current_chunk_type = ChunkType::Mid;
+ build_stack.current_chunk_num += 1;
self.var_num += 1;
}
.get_name_and_arity();
add_qualified_chunk!(
- self,
module_name,
key,
HeapCellValueTag::Str,
let key = (predicate_name, predicate_arity);
add_qualified_chunk!(
- self,
module_name,
key,
HeapCellValueTag::Str,
_ => {}
);
- if update_chunk_data(self, (atom!("call"), 2)) {
+ if update_chunk_data(&mut build_stack, (atom!("call"), 2)) {
build_stack.add_chunk();
}
- self.probe_body_term(1, 0, terms, module_name_loc);
- self.probe_body_term(2, 0, terms, predicate_term_loc);
+ let context = build_stack.current_gen_context();
+
+ self.probe_body_term(1, 0, terms, module_name_loc, context);
+ self.probe_body_term(2, 0, terms, predicate_term_loc, context);
let h = terms.heap.len();
self.call_policy = CallPolicy::Counted;
}
(name, arity) => {
- add_chunk!(self, (name, arity), HeapCellValueTag::Str, subterm_loc);
+ add_chunk!((name, arity), HeapCellValueTag::Str, subterm_loc);
}
}
}
debug_assert_eq!(arity, 0);
if name == atom!("!") {
- state_stack.push(self.new_cut_state());
+ let context = build_stack.current_gen_context();
+ state_stack.push(self.new_cut_state(context));
} else {
- add_chunk!(self, (name, 0), HeapCellValueTag::Var, term_loc);
+ add_chunk!((name, 0), HeapCellValueTag::Var, term_loc);
}
}
(HeapCellValueTag::Char, c) => {
if c == '!' {
- state_stack.push(self.new_cut_state());
+ let context = build_stack.current_gen_context();
+ state_stack.push(self.new_cut_state(context));
} else {
return Err(CompilationError::InadmissibleQueryTerm);
}
continue;
}
- add_chunk!(self, (atom!("call"), 1), HeapCellValueTag::Var, h);
+ add_chunk!((atom!("call"), 1), HeapCellValueTag::Var, h);
}
_ => {
return Err(CompilationError::InadmissibleQueryTerm);
records: VariableRecords::new(var_num),
global_cut_var_num,
allocates: current_chunk_num > 0,
+ var_locs_to_nums: VarLocsToNums::default(),
};
for (var, branches) in self.iter_mut() {
- let (mut var_num, var_num_incr) = if let Var::InSitu(var_num) = *var.borrow() {
- (var_num, false)
- } else {
- (var_data.records.len(), true)
+ let (mut var_num, var_num_incr) = match var {
+ &ClassifiedVar::InSitu { var_num} => (var_num, false),
+ _ => (var_data.records.len(), true)
};
for branch in branches.iter_mut() {
for var_info in chunk.vars.iter_mut() {
if var_info.lvl == Level::Shallow {
- let term_loc = var_info.chunk_type.to_gen_context(chunk.chunk_num);
+ let context = var_info
+ .chunk_type
+ .to_gen_context(chunk.term_loc.chunk_num());
+
temp_var_data
.use_set
- .insert((term_loc, var_info.classify_info.arg_c));
+ .insert((context, var_info.classify_info.arg_c));
}
}
for chunk in branch.chunks.iter_mut() {
var_data.records[var_num].num_occurrences += chunk.vars.len();
- for var_info in chunk.vars.iter_mut() {
- let is_anon = var_info.var_ptr.is_anon();
- var_info.var_ptr.set(Var::Generated { is_anon, var_num });
+ if let Some(term_loc) = var.term_loc() {
+ let chunk_num = chunk.term_loc.chunk_num();
+
+ var_data.var_locs_to_nums.insert(
+ VarPtrIndex { chunk_num, term_loc },
+ var_num,
+ );
}
}
}
}
}
+#[cfg(test)]
pub(crate) struct IteratorUMP {
mark_phase: bool,
}
+#[cfg(test)]
fn invert_marker<UMP: UnmarkPolicy>(iter: &mut StacklessPreOrderHeapIter<UMP>) {
if iter.heap[iter.start].get_forwarding_bit() {
while !iter.backward() {}
while iter.forward().is_some() {}
}
+#[cfg(test)]
impl UnmarkPolicy for IteratorUMP {
#[inline(always)]
fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue> {
}
}
+#[cfg(test)]
impl<'a> StacklessPreOrderHeapIter<'a, IteratorUMP> {
- #[cfg(test)]
pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self {
heap[start].set_forwarding_bit(true);
let next = heap[start].get_value();
use crate::heap_print::{HCPrinter, HCValueOutputter, PrinterOutputter};
use crate::machine::mock_wam::CompositeOpDir;
use crate::machine::{copy_and_align_iter, BREAK_FROM_DISPATCH_LOOP_LOC, LIB_QUERY_SUCCESS};
-use crate::parser::ast::{Var, VarPtr};
use crate::parser::parser::{Parser, Tokens};
use indexmap::IndexMap;
.unwrap();
let var_names: IndexMap<_, _> = term
- .var_locs
+ .inverse_var_locs
.iter()
- .map(|(var_loc, var_ptrs)| {
- let var_loc = var_loc + heap_loc;
- let cell = self.machine_st.heap[var_loc];
- let var_ptr = var_ptrs.front().unwrap();
-
- match &*var_ptr.borrow() {
- // NOTE: not the intention behind Var::InSitu here but
- // we can hijack it to store anonymous variables
- // without creating problems.
- Var::Anon => (cell, VarPtr::from(Var::InSitu(var_loc))),
- _ => (cell, var_ptr.clone()),
- }
+ .map(|(var_loc, var)| {
+ let cell = term.heap[*var_loc];
+ (cell + heap_loc, var.clone())
})
.collect();
let machine_st = LS::machine_st(&mut self.payload);
term.copy_term_from_machine_heap(machine_st, cell);
- term.var_locs = var_locs_from_iter(
+ term.inverse_var_locs = inverse_var_locs_from_iter(
fact_iterator::<false>(
&mut term.heap,
&mut stack,
);
let value = term.heap[term.focus];
- term.var_locs = var_locs_from_iter(eager_stackful_preorder_iter(&mut term.heap, value));
+ term.inverse_var_locs = inverse_var_locs_from_iter(
+ eager_stackful_preorder_iter(&mut term.heap, value),
+ );
Ok(term)
}
fn arithmetic_error(&mut self, err: ArithmeticError) -> MachineError {
match err {
ArithmeticError::UninstantiatedVar => self.instantiation_error(),
- ArithmeticError::NonEvaluableFunctor(literal, arity) => {
- let culprit = functor!(atom!("/"), [literal(literal), fixnum(arity)]);
+ ArithmeticError::NonEvaluableFunctor(cell, arity) => {
+ let culprit = functor!(atom!("/"), [cell(cell), fixnum(arity)]);
self.type_error(ValidType::Evaluable, culprit)
}
use std::convert::TryFrom;
use std::fmt;
use std::ops::{Index, IndexMut};
+use std::rc::Rc;
use std::sync::Arc;
pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1];
fn push_var_eq_functors(
heap: &mut Heap,
- iter: impl Iterator<Item = (usize, VarPtr)>, // (&'a VarPtr, &'a HeapCellValue)>,
+ iter: impl Iterator<Item = (usize, Var)>,
atom_tbl: &AtomTable,
) -> Vec<HeapCellValue> {
let mut list_of_var_eqs = vec![];
- for (var_loc, var_ptr) in iter { // (var, binding) in iter {
- let var_atom = AtomTable::build_with(atom_tbl, &*var_ptr.borrow().to_string());
+ for (var_loc, var) in iter { // (var, binding) in iter {
+ let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
let h = heap.len();
let binding = heap[var_loc];
pub fn write_read_term_options(
&mut self,
- mut var_list: Vec<(VarPtr, HeapCellValue, usize)>,
+ mut var_list: Vec<(Var, HeapCellValue, usize)>,
singleton_var_list: Vec<HeapCellValue>,
) -> CallResult {
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
let list_of_var_eqs = push_var_eq_functors(
&mut self.heap,
- var_list.iter().filter_map(|(var_ptr, var, _)| {
- if var_ptr.is_anon() {
- None
- } else {
- let var_loc = var.get_value() as usize;
- Some((var_loc, var_ptr.clone()))
- }
+ var_list.iter().map(|(var_name, var, _)| {
+ (var.get_value() as usize, var_name.clone())
}),
&self.atom_tbl,
);
let singleton_var_list = push_var_eq_functors(
&mut self.heap,
- term.var_locs
+ term.inverse_var_locs
.iter()
- .filter_map(|(var_loc, var_ptrs)| {
- let var_ptr = var_ptrs.front().unwrap();
-
- if var_ptr.is_anon() {
- return None;
- }
-
+ .filter_map(|(var_loc, var_name)| {
// add h to offset the term variable into its heap location.
- let r = Ref::heap_cell(var_loc);
+ let r = Ref::heap_cell(*var_loc);
if singleton_var_set.get(&r).cloned().unwrap_or(false) {
- Some((var_loc, var_ptr.clone()))
+ Some((*var_loc, var_name.clone()))
} else {
None
}
let mut var_list = Vec::with_capacity(singleton_var_set.len());
- for (var_loc, var_ptrs) in term.var_locs.iter() {
- let var_ptr = var_ptrs.front().unwrap().clone();
+ for (var_loc, var_name) in term.inverse_var_locs {
let r = Ref::heap_cell(var_loc);
let cell = self.heap[var_loc];
if let Some(idx) = singleton_var_set.get_index_of(&r) {
- var_list.push((var_ptr, cell, idx));
+ var_list.push((var_name, cell, idx));
}
}
let printer = match self.try_from_list(self.registers[6], stub_gen) {
Ok(addrs) => {
- let mut var_names: IndexMap<HeapCellValue, VarPtr> = IndexMap::new();
+ let mut var_names: IndexMap<HeapCellValue, Var> = IndexMap::new();
for addr in addrs {
read_heap_cell!(addr,
read_heap_cell!(atom,
(HeapCellValueTag::Char, c) => {
- var_names.insert(var, VarPtr::from(c.to_string()));
+ var_names.insert(var, Rc::new(c.to_string()));
}
(HeapCellValueTag::Atom, (name, _arity)) => {
debug_assert_eq!(_arity, 0);
- var_names.insert(var, VarPtr::from(&*name.as_str()));
+ var_names.insert(var, Rc::new(name.as_str().to_owned()));
}
(HeapCellValueTag::Str, s) => {
let (name, arity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
debug_assert_eq!(arity, 0);
- var_names.insert(var, VarPtr::from(&*name.as_str()));
+ var_names.insert(var, Rc::new(name.as_str().to_owned()));
}
_ => {
unreachable!();
print_heap_terms(self.machine_st.heap.iter(), term_write_result.heap_loc);
let var_names = term_write_result
- .var_locs
+ .inverse_var_locs
.iter()
- .map(|(var_loc, var_ptrs)| {
- (self.machine_st.heap[var_loc], var_ptrs.front().unwrap().clone())
+ .map(|(var_loc, var_name)| {
+ (self.machine_st.heap[*var_loc], var_name.clone())
})
.collect();
heap_loc_as_cell!(0),
);
- if (module_loc.is_var() || module_loc == atom_as_cell!(atom!("user"))) && arg_term.is_var() && supp_var.is_var() {
+ if (module_loc.is_var() || module_loc == atom_as_cell!(atom!("user"))) &&
+ arg_term.is_var() &&
+ supp_var.is_var()
+ {
return arg_term == *supp_var;
}
use crate::machine::machine_state::*;
use crate::types::*;
-use std::cell::{Ref, RefCell, RefMut};
-use std::collections::VecDeque;
use std::fmt;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
use std::io::{Error as IOError, ErrorKind};
-use std::ops::{Deref, Neg, RangeBounds};
+use std::ops::Neg;
use std::rc::Rc;
use std::sync::Arc;
use std::vec::Vec;
};
}
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum GenContext {
- Head,
- Mid(usize),
- Last(usize), // Mid & Last: chunk_num
-}
-
-impl GenContext {
- #[inline]
- pub fn chunk_num(self) -> usize {
- match self {
- GenContext::Head => 0,
- GenContext::Mid(cn) | GenContext::Last(cn) => cn,
- }
- }
-
- #[inline]
- pub fn is_last(self) -> bool {
- matches!(self, GenContext::Last(_))
- }
+#[macro_export]
+macro_rules! perm_v {
+ ($x:expr) => {
+ $crate::parser::ast::RegType::Perm($x)
+ };
}
#[bitfield]
#[derive(Debug, Clone)]
pub enum ArithmeticError {
- NonEvaluableFunctor(Literal, usize),
+ NonEvaluableFunctor(HeapCellValue, usize),
UninstantiatedVar,
}
}
}
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct VarPtr(Rc<RefCell<Var>>);
-
-impl Hash for VarPtr {
- #[inline(always)]
- fn hash<H: Hasher>(&self, hasher: &mut H) {
- self.borrow().hash(hasher)
- }
-}
-
-impl Deref for VarPtr {
- type Target = RefCell<Var>;
-
- #[inline(always)]
- fn deref(&self) -> &Self::Target {
- self.0.deref()
- }
-}
-
-impl VarPtr {
- #[inline]
- pub(crate) fn is_anon(&self) -> bool {
- match *self.borrow() {
- Var::Anon | Var::Generated { is_anon: true, .. } => true,
- _ => false,
- }
- }
-
- #[inline(always)]
- pub(crate) fn borrow(&self) -> Ref<'_, Var> {
- self.0.borrow()
- }
-
- #[inline(always)]
- pub(crate) fn borrow_mut(&self) -> RefMut<'_, Var> {
- self.0.borrow_mut()
- }
-
- pub(crate) fn to_var_num(&self) -> Option<usize> {
- match *self.borrow() {
- Var::Generated { var_num, .. } => Some(var_num),
- _ => None,
- }
- }
-
- pub(crate) fn set(&self, var: Var) {
- let mut var_ref = self.borrow_mut();
- *var_ref = var;
- }
-}
-
-impl From<Var> for VarPtr {
- #[inline(always)]
- fn from(value: Var) -> VarPtr {
- VarPtr(Rc::new(RefCell::new(value)))
- }
-}
-
-impl From<String> for VarPtr {
- #[inline(always)]
- fn from(value: String) -> VarPtr {
- VarPtr::from(Var::from(value))
- }
-}
-
-impl From<&str> for VarPtr {
- #[inline(always)]
- fn from(value: &str) -> VarPtr {
- VarPtr::from(value.to_owned())
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum Var {
- Anon,
- Generated { is_anon: bool, var_num: usize },
- InSitu(usize),
- Named(String),
-}
-
-impl From<String> for Var {
- #[inline(always)]
- fn from(value: String) -> Var {
- Var::Named(value)
- }
-}
-
-impl From<&str> for Var {
- #[inline(always)]
- fn from(value: &str) -> Var {
- Var::Named(value.to_owned())
- }
-}
-
-impl Var {
- #[allow(clippy::inherent_to_string)]
- #[inline(always)]
- pub fn to_string(&self) -> String {
- match self {
- Var::Anon => "_".to_owned(),
- Var::InSitu(var_num) | Var::Generated { var_num, .. } => format!("_{}", var_num),
- Var::Named(value) => value.to_owned(),
- }
- }
-}
+pub type Var = Rc<String>;
pub(crate) fn subterm_index(heap: &[HeapCellValue], subterm_loc: usize) -> (usize, HeapCellValue) {
let subterm = heap[subterm_loc];
}
}
-pub fn var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) -> VarLocs {
+pub fn inverse_var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) -> InverseVarLocs {
let mut occurrence_set: IndexMap<HeapCellValue, usize, FxBuildHasher> =
IndexMap::with_hasher(FxBuildHasher::default());
}
}
- VarLocs(
- occurrence_set
- .into_iter()
- .map(|(var, count)| {
- let key = var.get_value() as usize;
- let queue = if count > 1 {
- (0 .. count).map(|_| VarPtr::from(format!("_{}", key))).collect()
- } else {
- (0 .. count).map(|_| VarPtr::from(Var::Anon)).collect()
- };
+ let mut inverse_var_locs = InverseVarLocs::default();
- (key, queue)
- })
- .collect()
- )
+ for (var, count) in occurrence_set {
+ let var_loc = var.get_value() as usize;
+
+ if count > 1 {
+ inverse_var_locs.insert(
+ var_loc,
+ Rc::new(format!("_{}", var_loc)),
+ );
+ }
+ }
+
+ inverse_var_locs
}
/*
}
}
-pub type VarNamesToLocs = IndexMap<String, HeapCellValue, FxBuildHasher>;
-
-#[derive(Debug, Default)]
-pub struct VarLocs(IndexMap<usize, VecDeque<VarPtr>, FxBuildHasher>);
-
-impl VarLocs {
- pub fn get(&self, key: usize) -> Option<&VarPtr> {
- self.0.get(&key)
- .and_then(|queue| {
- queue.front()
- })
- }
-
- // if a queue of VarPtr's is stored at location key, pop the front
- // if it exists and pass it along to wrapper, returning a value of
- // type R. A return value of None indicates that the key doesn't
- // exist (the map containing a key necessarily means its queue
- // value is non-empty).
- fn rotate_latest_mut<R>(
- &mut self,
- key: usize,
- wrapper: impl FnOnce(&VarPtr) -> R,
- ) -> Option<R> {
- self.0.get_mut(&key)
- .and_then(move |queue| {
- if let Some(var_ptr) = queue.pop_front() {
- let result = wrapper(&var_ptr);
- queue.push_back(var_ptr);
- Some(result)
- } else {
- None
- }
- })
- }
-
- pub fn peek_next_var_ptr_at_key(&self, key: usize) -> Option<&VarPtr> {
- self.0.get(&key).and_then(|queue| queue.front())
- }
-
- pub fn read_next_var_ptr_at_key(&mut self, key: usize) -> Option<VarPtr> {
- self.rotate_latest_mut(key, VarPtr::clone)
- }
-
- pub fn push_at_key(&mut self, key: usize, var_ptr: VarPtr) {
- let entry = self.0.entry(key).or_default();
- entry.push_back(var_ptr);
- }
-
- #[inline]
- pub fn iter(&self) -> impl Iterator<Item = (usize, &VecDeque<VarPtr>)> {
- self.0.iter().map(|(&k, v)| (k, v))
- }
-
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.0.is_empty()
- }
-
- #[inline]
- pub fn drain<R>(&mut self, range: R) -> indexmap::map::Drain<usize, VecDeque<VarPtr>>
- where R: RangeBounds<usize>
- {
- self.0.drain(range)
- }
-
- #[inline]
- pub fn insert(&mut self, key: usize, var_ptrs: VecDeque<VarPtr>) {
- self.0.insert(key, var_ptrs);
- }
-}
+pub type VarLocs = IndexMap<Var, HeapCellValue, FxBuildHasher>;
+pub type InverseVarLocs = IndexMap<usize, Var, FxBuildHasher>;
#[derive(Debug)]
pub struct FocusedHeap {
pub heap: Vec<HeapCellValue>,
pub focus: usize,
- pub var_locs: VarLocs,
+ pub inverse_var_locs: InverseVarLocs,
}
impl FocusedHeap {
Self {
heap: vec![],
focus: 0,
- var_locs: VarLocs::default(),
+ inverse_var_locs: InverseVarLocs::default(),
}
}
FocusedHeapRefMut {
heap: &mut self.heap,
focus,
- // var_locs: &self.var_locs,
}
}
use crate::parser::lexer::*;
use crate::types::*;
-use fxhash::FxBuildHasher;
-use indexmap::IndexMap;
-
use std::mem;
use std::ops::Neg;
+use std::rc::Rc;
#[derive(Debug, Clone, Copy, PartialEq)]
enum TokenType {
stack: Vec<TokenDesc>,
terms: Vec<HeapCellValue>,
var_locs: VarLocs,
- var_names_to_locs: VarNamesToLocs,
+ inverse_var_locs: InverseVarLocs,
}
fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserError> {
stack: vec![],
terms: vec![],
var_locs: VarLocs::default(),
- var_names_to_locs: IndexMap::with_hasher(FxBuildHasher::default()),
+ inverse_var_locs: InverseVarLocs::default(),
}
}
stack: vec![],
terms: vec![],
var_locs: VarLocs::default(),
- var_names_to_locs: IndexMap::with_hasher(FxBuildHasher::default()),
+ inverse_var_locs: InverseVarLocs::default(),
}
}
self.terms.push(HeapCellValue::from(c));
TokenType::Term { heap_loc }
}
- Token::Var(var_string) => match self.var_names_to_locs.get(&var_string).cloned() {
- Some(heap_loc) => {
- let heap_idx = heap_loc.get_value() as usize;
-
- self.var_locs.push_at_key(heap_idx, VarPtr::from(var_string));
- self.terms.push(heap_loc);
-
- TokenType::Term { heap_loc }
- }
- None => {
- self.terms.push(heap_loc);
+ Token::Var(var_string) => {
+ let var = Rc::new(var_string);
- if var_string.trim() != "_" {
- self.var_names_to_locs.insert(var_string.clone(), heap_loc);
+ match self.var_locs.get(&var).cloned() {
+ Some(heap_loc) => {
+ self.terms.push(heap_loc);
+ TokenType::Term { heap_loc }
}
+ None => {
+ self.terms.push(heap_loc);
- self.var_locs.push_at_key(
- heap_loc.get_value() as usize,
- if var_string.trim() == "_" {
- VarPtr::from(Var::Anon)
- } else {
- VarPtr::from(var_string)
- },
- );
+ // if var_string == "_", it not being present
+ // as a key of self.var_locs means it is
+ // anonymous.
- TokenType::Term { heap_loc }
+ if var.trim() != "_" {
+ self.var_locs.insert(var.clone(), heap_loc);
+ self.inverse_var_locs.insert(heap_loc.get_value() as usize, var);
+ }
+
+ TokenType::Term { heap_loc }
+ }
}
},
Token::Comma => TokenType::Comma,
pub fn reset(&mut self) {
self.stack.clear();
- self.var_names_to_locs.clear();
+ self.var_locs.clear();
}
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
}) => Ok(FocusedHeap {
heap: mem::replace(&mut self.terms, vec![]),
focus: heap_loc.get_value() as usize,
- var_locs: mem::replace(&mut self.var_locs, VarLocs::default()),
+ inverse_var_locs: mem::replace(&mut self.inverse_var_locs, InverseVarLocs::default()),
}),
_ => Err(ParserError::IncompleteReduction(
self.lexer.loc_to_err_src(),
let heap_len = machine_st.heap.len();
machine_st.heap.extend(copy_and_align_iter(self.heap.drain(..), 0, heap_len as i64));
- let mut var_locs = VarLocs::default();
+ let mut inverse_var_locs = InverseVarLocs::default();
- for (var_loc, var_ptrs) in self.var_locs.drain(..) {
- var_locs.insert(var_loc + heap_len, var_ptrs);
+ for (var_loc, var_name) in self.inverse_var_locs.drain(..) {
+ inverse_var_locs.insert(var_loc + heap_len, var_name);
}
TermWriteResult {
heap_loc: self.focus + heap_len,
- var_locs,
+ inverse_var_locs,
}
}
}
#[derive(Debug)]
pub struct TermWriteResult {
pub heap_loc: usize,
- pub var_locs: VarLocs,
+ pub inverse_var_locs: InverseVarLocs,
}
error,
true),
\+ call_with_inference_limit(g(X), 5, R),
- maplist(assertz, [g(1), g(2), g(3), g(4), g(5)]),
+ maplist(assertz, [g(1), g(2), g(3), g(4), g(5)]), % TODO this line fails!
findall([R,X],
call_with_inference_limit(g(X), 11, R),
[[true, 1],
[true, 4],
[!, 5]]),
findall([R,X],
- (call_with_inference_limit(g(X), 5, R), call(true)),
+ (call_with_inference_limit(g(X), 2, R), call(true)),
[[true, 1],
[true, 2],
[inference_limit_exceeded, _]]),
use crate::parser::ast::*;
+use crate::forms::GenContext;
use bit_set::*;
use fxhash::FxBuildHasher;