variable revision
This commit is contained in:
@@ -911,7 +911,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
functor!(atom!("intermediate"), [fixnum(i)])
|
functor!(atom!("intermediate"), [fixnum(i)])
|
||||||
}
|
}
|
||||||
ArithmeticTerm::Number(n) => {
|
ArithmeticTerm::Number(n) => {
|
||||||
vec![HeapCellValue::from((n, arena))]
|
functor!(atom!("number"), [cell(HeapCellValue::from((n, arena)))])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub(crate) trait Allocator {
|
|||||||
lvl: Level,
|
lvl: Level,
|
||||||
context: GenContext,
|
context: GenContext,
|
||||||
code: &mut CodeDeque,
|
code: &mut CodeDeque,
|
||||||
);
|
) -> RegType;
|
||||||
|
|
||||||
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
|
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use crate::debray_allocator::*;
|
|||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::iterators::*;
|
use crate::iterators::*;
|
||||||
|
use crate::machine::disjuncts::*;
|
||||||
use crate::machine::stack::Stack;
|
use crate::machine::stack::Stack;
|
||||||
use crate::parser::ast::FocusedHeap;
|
use crate::parser::ast::FocusedHeap;
|
||||||
use crate::targets::QueryInstruction;
|
use crate::targets::QueryInstruction;
|
||||||
@@ -173,7 +174,7 @@ fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: Literal) -> Result<(), Arit
|
|||||||
Literal::Atom(name) if name == atom!("epsilon") => interm.push(ArithmeticTerm::Number(
|
Literal::Atom(name) if name == atom!("epsilon") => interm.push(ArithmeticTerm::Number(
|
||||||
Number::Float(OrderedFloat(f64::EPSILON)),
|
Number::Float(OrderedFloat(f64::EPSILON)),
|
||||||
)),
|
)),
|
||||||
_ => return Err(ArithmeticError::NonEvaluableFunctor(c, 0)),
|
_ => return Err(ArithmeticError::NonEvaluableFunctor(HeapCellValue::from(c), 0)),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -216,7 +217,7 @@ impl<'a> ArithmeticEvaluator<'a> {
|
|||||||
atom!("float_fractional_part") => Ok(Instruction::FloatFractionalPart(a1, t)),
|
atom!("float_fractional_part") => Ok(Instruction::FloatFractionalPart(a1, t)),
|
||||||
atom!("sign") => Ok(Instruction::Sign(a1, t)),
|
atom!("sign") => Ok(Instruction::Sign(a1, t)),
|
||||||
atom!("\\") => Ok(Instruction::BitwiseComplement(a1, t)),
|
atom!("\\") => Ok(Instruction::BitwiseComplement(a1, t)),
|
||||||
_ => Err(ArithmeticError::NonEvaluableFunctor(Literal::Atom(name), 1)),
|
_ => Err(ArithmeticError::NonEvaluableFunctor(atom_as_cell!(name), 1)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +249,7 @@ impl<'a> ArithmeticEvaluator<'a> {
|
|||||||
atom!("rem") => Ok(Instruction::Rem(a1, a2, t)),
|
atom!("rem") => Ok(Instruction::Rem(a1, a2, t)),
|
||||||
atom!("gcd") => Ok(Instruction::Gcd(a1, a2, t)),
|
atom!("gcd") => Ok(Instruction::Gcd(a1, a2, t)),
|
||||||
atom!("atan2") => Ok(Instruction::ATan2(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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +305,7 @@ impl<'a> ArithmeticEvaluator<'a> {
|
|||||||
self.get_binary_instr(name, a1, a2, ninterm)
|
self.get_binary_instr(name, a1, a2, ninterm)
|
||||||
}
|
}
|
||||||
_ => Err(ArithmeticError::NonEvaluableFunctor(
|
_ => Err(ArithmeticError::NonEvaluableFunctor(
|
||||||
Literal::Atom(name),
|
atom_as_cell!(name),
|
||||||
arity,
|
arity,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
@@ -321,30 +322,38 @@ impl<'a> ArithmeticEvaluator<'a> {
|
|||||||
let mut stack = Stack::uninitialized();
|
let mut stack = Stack::uninitialized();
|
||||||
let mut iter = query_iterator::<false>(&mut src.heap, &mut stack, term_loc);
|
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() {
|
while let Some(term) = iter.next() {
|
||||||
read_heap_cell!(term,
|
read_heap_cell!(term,
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
|
||||||
let lvl = iter.level();
|
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 {
|
let r = match self.marker.var_data.var_locs_to_nums.get(VarPtrIndex { chunk_num, term_loc }) {
|
||||||
self.marker.mark_non_callable(var_num, arg, context, &mut code)
|
VarPtr::Numbered(var_num) => {
|
||||||
} else if context.is_last() || old_r.reg_num() == 0 {
|
let old_r = self.marker.get_var_binding(var_num);
|
||||||
let r = old_r;
|
|
||||||
|
|
||||||
if r.reg_num() == 0 {
|
if lvl == Level::Root {
|
||||||
self.marker.mark_var::<QueryInstruction>(
|
self.marker.mark_non_callable(var_num, arg, context, &mut code)
|
||||||
var_num, lvl, context, &mut code,
|
} else if context.is_last() || old_r.reg_num() == 0 {
|
||||||
)
|
let r = old_r;
|
||||||
} else {
|
|
||||||
self.marker.increment_running_count(var_num);
|
if r.reg_num() == 0 {
|
||||||
r
|
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));
|
self.interm.push(ArithmeticTerm::Reg(r));
|
||||||
@@ -359,7 +368,7 @@ impl<'a> ArithmeticEvaluator<'a> {
|
|||||||
_ => {
|
_ => {
|
||||||
match Literal::try_from(term) {
|
match Literal::try_from(term) {
|
||||||
Ok(lit) => push_literal(&mut self.interm, lit)?,
|
Ok(lit) => push_literal(&mut self.interm, lit)?,
|
||||||
_ => unreachable!()
|
_ => return Err(ArithmeticError::NonEvaluableFunctor(term, 0)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -547,6 +556,7 @@ impl Div<Number> for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl PartialEq for Number {
|
impl PartialEq for Number {
|
||||||
fn eq(&self, rhs: &Self) -> bool {
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
@@ -630,6 +640,7 @@ impl PartialOrd for Number {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Ord for Number {
|
impl Ord for Number {
|
||||||
fn cmp(&self, rhs: &Number) -> Ordering {
|
fn cmp(&self, rhs: &Number) -> Ordering {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
|
|||||||
613
src/codegen.rs
613
src/codegen.rs
@@ -420,28 +420,27 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
fn subterm_to_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
|
fn subterm_to_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
subterm: HeapCellValue,
|
subterm: HeapCellValue,
|
||||||
var_locs: &mut VarLocs,
|
|
||||||
heap_loc: usize,
|
heap_loc: usize,
|
||||||
context: GenContext,
|
context: GenContext,
|
||||||
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
|
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
|
||||||
target: &mut CodeDeque,
|
target: &mut CodeDeque,
|
||||||
) -> Option<RegType> {
|
) -> Option<RegType> {
|
||||||
let subterm = unmark_cell_bits!(subterm);
|
let subterm = unmark_cell_bits!(subterm);
|
||||||
|
let chunk_num = context.chunk_num();
|
||||||
|
|
||||||
read_heap_cell!(subterm,
|
read_heap_cell!(subterm,
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
|
||||||
let var_ptr = var_locs.read_next_var_ptr_at_key(h).unwrap();
|
match self.marker.var_data.var_locs_to_nums.get(VarPtrIndex { chunk_num, term_loc }) {
|
||||||
|
VarPtr::Numbered(var_num) => {
|
||||||
if var_ptr.is_anon() {
|
self.deep_var_instr::<Target>(
|
||||||
Self::add_or_increment_void_instr::<Target>(target);
|
var_num,
|
||||||
} else {
|
context,
|
||||||
let var_num = var_ptr.to_var_num().unwrap();
|
target,
|
||||||
|
);
|
||||||
self.deep_var_instr::<Target>(
|
}
|
||||||
var_num,
|
VarPtr::Anon => {
|
||||||
context,
|
Self::add_or_increment_void_instr::<Target>(target);
|
||||||
target,
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
@@ -482,7 +481,6 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
mut iter: Iter,
|
mut iter: Iter,
|
||||||
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
|
index_ptrs: &IndexMap<usize, CodeIndex, FxBuildHasher>,
|
||||||
var_locs: &mut VarLocs,
|
|
||||||
context: GenContext,
|
context: GenContext,
|
||||||
) -> CodeDeque
|
) -> CodeDeque
|
||||||
where
|
where
|
||||||
@@ -491,29 +489,33 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
CodeGenerator<'b>: AddToFreeList<'a, Target>,
|
CodeGenerator<'b>: AddToFreeList<'a, Target>,
|
||||||
{
|
{
|
||||||
let mut target = CodeDeque::new();
|
let mut target = CodeDeque::new();
|
||||||
|
let chunk_num = context.chunk_num();
|
||||||
|
|
||||||
while let Some(term) = iter.next() {
|
while let Some(term) = iter.next() {
|
||||||
let lvl = iter.level();
|
let lvl = iter.level();
|
||||||
let term = unmark_cell_bits!(term);
|
let term = unmark_cell_bits!(term);
|
||||||
|
|
||||||
read_heap_cell!(term,
|
read_heap_cell!(term,
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
|
||||||
if lvl == Level::Shallow {
|
if lvl == Level::Shallow {
|
||||||
let var_ptr = var_locs.read_next_var_ptr_at_key(h).unwrap();
|
match self.marker.var_data.var_locs_to_nums.get(
|
||||||
|
VarPtrIndex { chunk_num, term_loc }
|
||||||
if var_ptr.is_anon() {
|
) {
|
||||||
if let GenContext::Head = context {
|
VarPtr::Numbered(var_num) => {
|
||||||
self.marker.advance_arg();
|
self.marker.mark_var::<Target>(
|
||||||
} else {
|
var_num,
|
||||||
self.marker.mark_anon_var::<Target>(lvl, context, &mut target);
|
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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -544,7 +546,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
let (subterm_loc, subterm) = subterm_index(iter.deref(), subterm_loc);
|
let (subterm_loc, subterm) = subterm_index(iter.deref(), subterm_loc);
|
||||||
|
|
||||||
self.subterm_to_instr::<Target>(
|
self.subterm_to_instr::<Target>(
|
||||||
subterm, var_locs, subterm_loc, context, index_ptrs, &mut target,
|
subterm, subterm_loc, context, index_ptrs, &mut target,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@@ -580,7 +582,6 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
|
|
||||||
let head_r_opt = self.subterm_to_instr::<Target>(
|
let head_r_opt = self.subterm_to_instr::<Target>(
|
||||||
head,
|
head,
|
||||||
var_locs,
|
|
||||||
head_loc,
|
head_loc,
|
||||||
context,
|
context,
|
||||||
index_ptrs,
|
index_ptrs,
|
||||||
@@ -589,7 +590,6 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
|
|
||||||
let tail_r_opt = self.subterm_to_instr::<Target>(
|
let tail_r_opt = self.subterm_to_instr::<Target>(
|
||||||
tail,
|
tail,
|
||||||
var_locs,
|
|
||||||
tail_loc,
|
tail_loc,
|
||||||
context,
|
context,
|
||||||
index_ptrs,
|
index_ptrs,
|
||||||
@@ -623,7 +623,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
|
|
||||||
let (tail_loc, tail) = subterm_index(iter.deref(), heap_loc + 1);
|
let (tail_loc, tail) = subterm_index(iter.deref(), heap_loc + 1);
|
||||||
self.subterm_to_instr::<Target>(
|
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) => {
|
(HeapCellValueTag::PStrOffset, l) => {
|
||||||
@@ -644,7 +644,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
target.push_back(Target::to_pstr(lvl, pstr_offset_atom, r, true));
|
target.push_back(Target::to_pstr(lvl, pstr_offset_atom, r, true));
|
||||||
|
|
||||||
self.subterm_to_instr::<Target>(
|
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 => {
|
_ if lvl == Level::Shallow => {
|
||||||
@@ -693,21 +693,53 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
context: GenContext,
|
context: GenContext,
|
||||||
code: &mut CodeDeque,
|
code: &mut CodeDeque,
|
||||||
) -> Result<(), CompilationError> {
|
) -> 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 {
|
let call_instr = match ct {
|
||||||
&InlinedClauseType::CompareNumber(mut cmp) => {
|
&InlinedClauseType::CompareNumber(mut cmp) => {
|
||||||
self.marker.reset_arg(2);
|
self.marker.reset_arg(2);
|
||||||
|
|
||||||
let (mut lcode, at_1) =
|
let (mut lcode, at_1) =
|
||||||
self.compile_arith_expr(terms, term_loc + 1, 1, context, 1)?;
|
if let Some(r) = variable_marker(&mut self.marker) {
|
||||||
|
(CodeDeque::default(), Some(ArithmeticTerm::Reg(r)))
|
||||||
if !terms.deref_loc(term_loc + 1).is_var() {
|
} else {
|
||||||
self.marker.advance_arg();
|
self.compile_arith_expr(terms, first_arg_loc, 1, context, 1)?
|
||||||
}
|
};
|
||||||
|
|
||||||
let (mut rcode, at_2) =
|
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 lcode);
|
||||||
code.append(&mut rcode);
|
code.append(&mut rcode);
|
||||||
@@ -717,65 +749,175 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
|
|
||||||
compare_number_instr!(cmp, at_1, at_2)
|
compare_number_instr!(cmp, at_1, at_2)
|
||||||
}
|
}
|
||||||
InlinedClauseType::IsAtom(..) => read_heap_cell!(term,
|
InlinedClauseType::IsAtom(..) => {
|
||||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
self.marker.reset_arg(1);
|
||||||
if arity == 0 {
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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(..) => {
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
instr!("$fail")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InlinedClauseType::IsRational(..) => {
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
instr!("$fail")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InlinedClauseType::IsFloat(..) => {
|
||||||
|
self.marker.reset_arg(1);
|
||||||
|
|
||||||
|
if let Some(r) = variable_marker(&mut self.marker) {
|
||||||
|
instr!("float", r)
|
||||||
|
} else {
|
||||||
|
read_heap_cell!(first_arg,
|
||||||
|
(HeapCellValueTag::F64) => {
|
||||||
|
instr!("$succeed")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
instr!("$fail")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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")
|
instr!("$succeed")
|
||||||
} else {
|
} else {
|
||||||
instr!("$fail")
|
instr!("$fail")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Char) => {
|
}
|
||||||
instr!("$succeed")
|
InlinedClauseType::IsNonVar(..) => {
|
||||||
}
|
self.marker.reset_arg(1);
|
||||||
(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() {
|
if let Some(r) = variable_marker(&mut self.marker) {
|
||||||
|
instr!("nonvar", r)
|
||||||
|
} else {
|
||||||
|
if first_arg.is_var() {
|
||||||
instr!("$fail")
|
instr!("$fail")
|
||||||
} else {
|
} else {
|
||||||
let r = self.marker.mark_non_callable(
|
instr!("$succeed")
|
||||||
var_ptr.to_var_num().unwrap(),
|
|
||||||
1,
|
|
||||||
context,
|
|
||||||
code,
|
|
||||||
);
|
|
||||||
|
|
||||||
instr!("atom", r)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
}
|
||||||
instr!("$fail")
|
InlinedClauseType::IsInteger(..) => {
|
||||||
}
|
self.marker.reset_arg(1);
|
||||||
),
|
|
||||||
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() {
|
if let Some(r) = variable_marker(&mut self.marker) {
|
||||||
instr!("$fail")
|
instr!("integer", r)
|
||||||
} else {
|
} else {
|
||||||
self.marker.reset_arg(1);
|
match Number::try_from(first_arg) {
|
||||||
|
Ok(Number::Integer(_) | Number::Fixnum(_)) => {
|
||||||
let r = self.marker.mark_non_callable(
|
|
||||||
var_ptr.to_var_num().unwrap(),
|
|
||||||
1,
|
|
||||||
context,
|
|
||||||
code,
|
|
||||||
);
|
|
||||||
|
|
||||||
instr!("atomic", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Fixnum |
|
|
||||||
HeapCellValueTag::Char |
|
|
||||||
HeapCellValueTag::F64) => {
|
|
||||||
instr!("$succeed")
|
|
||||||
}
|
|
||||||
(HeapCellValueTag::Cons, cons_ptr) => {
|
|
||||||
match cons_ptr.get_tag() {
|
|
||||||
ArenaHeaderTag::Integer | ArenaHeaderTag::Rational => {
|
|
||||||
instr!("$succeed")
|
instr!("$succeed")
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -783,233 +925,24 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Atom, (_name, arity)) => {
|
},
|
||||||
if arity == 0 {
|
InlinedClauseType::IsVar(..) => {
|
||||||
|
self.marker.reset_arg(1);
|
||||||
|
|
||||||
|
if let Some(r) = variable_marker(&mut self.marker) {
|
||||||
|
instr!("var", r)
|
||||||
|
} else {
|
||||||
|
if first_arg.is_var() {
|
||||||
instr!("$succeed")
|
instr!("$succeed")
|
||||||
} else {
|
} else {
|
||||||
instr!("$fail")
|
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::IsCompound(..) => {
|
|
||||||
read_heap_cell!(term,
|
|
||||||
(HeapCellValueTag::Atom, (_, arity)) => {
|
|
||||||
if arity > 0 {
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(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() {
|
|
||||||
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,
|
|
||||||
);
|
|
||||||
|
|
||||||
instr!("number", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if Number::try_from(term).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);
|
|
||||||
|
|
||||||
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!("nonvar", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
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);
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
match Number::try_from(term) {
|
|
||||||
Ok(Number::Integer(_) | Number::Fixnum(_)) => {
|
|
||||||
instr!("$succeed")
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
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);
|
|
||||||
|
|
||||||
if var_ptr.is_anon() {
|
|
||||||
instr!("$succeed")
|
|
||||||
} else {
|
|
||||||
let r = self.marker.mark_non_callable(
|
|
||||||
var_ptr.to_var_num().unwrap(),
|
|
||||||
1,
|
|
||||||
context,
|
|
||||||
code,
|
|
||||||
);
|
|
||||||
|
|
||||||
instr!("var", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
instr!("$fail")
|
|
||||||
}
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// inlined predicates are never counted, so this overrides nothing.
|
// inlined predicates are never counted, so this overrides nothing.
|
||||||
self.add_call(code, call_instr, CallPolicy::Counted);
|
self.add_call(code, call_instr, CallPolicy::Counted);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,34 +985,15 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let at = read_heap_cell!(var,
|
let at = read_heap_cell!(var,
|
||||||
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, term_loc) => {
|
||||||
let var_ptr = terms.var_locs.read_next_var_ptr_at_key(h).unwrap();
|
let chunk_num = context.chunk_num();
|
||||||
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.
|
|
||||||
|
|
||||||
|
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 {
|
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,
|
var_num,
|
||||||
Level::Shallow,
|
Level::Shallow,
|
||||||
context,
|
context,
|
||||||
@@ -1087,17 +1001,12 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
self.marker.mark_safe_var_unconditionally(var_num);
|
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() {
|
if Number::try_from(var).is_ok() {
|
||||||
@@ -1115,25 +1024,23 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
|
|
||||||
let at = at.unwrap_or(interm!(1));
|
let at = at.unwrap_or(interm!(1));
|
||||||
self.add_call(code, instr!("is", temp_v!(1), at), call_policy);
|
self.add_call(code, instr!("is", temp_v!(1), at), call_policy);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_seq(
|
fn compile_seq(
|
||||||
&mut self,
|
&mut self,
|
||||||
terms: &mut FocusedHeap,
|
focused_heap: &mut FocusedHeap,
|
||||||
clauses: &ChunkedTermVec,
|
clauses: &ChunkedTermVec,
|
||||||
code: &mut CodeDeque,
|
code: &mut CodeDeque,
|
||||||
) -> Result<(), CompilationError> {
|
) -> Result<(), CompilationError> {
|
||||||
let mut chunk_num = 0;
|
|
||||||
let mut branch_code_stack = BranchCodeStack::new();
|
let mut branch_code_stack = BranchCodeStack::new();
|
||||||
let mut clause_iter = ClauseIterator::new(clauses);
|
let mut clause_iter = ClauseIterator::new(clauses);
|
||||||
|
|
||||||
while let Some(clause_item) = clause_iter.next() {
|
while let Some(clause_item) = clause_iter.next() {
|
||||||
match clause_item {
|
match clause_item {
|
||||||
ClauseItem::Chunk(chunk) => {
|
ClauseItem::Chunk { chunk_num, terms } => {
|
||||||
for (idx, term) in chunk.iter().enumerate() {
|
for (idx, term) in terms.iter().enumerate() {
|
||||||
let context = if idx + 1 < chunk.len() {
|
let context = if idx + 1 < terms.len() {
|
||||||
GenContext::Mid(chunk_num)
|
GenContext::Mid(chunk_num)
|
||||||
} else {
|
} else {
|
||||||
self.marker.in_tail_position = clause_iter.in_tail_position();
|
self.marker.in_tail_position = clause_iter.in_tail_position();
|
||||||
@@ -1201,7 +1108,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
..
|
..
|
||||||
},
|
},
|
||||||
) => self.compile_is_call(
|
) => self.compile_is_call(
|
||||||
terms,
|
focused_heap,
|
||||||
clause.term_loc(),
|
clause.term_loc(),
|
||||||
branch_code_stack.code(code),
|
branch_code_stack.code(code),
|
||||||
context,
|
context,
|
||||||
@@ -1214,7 +1121,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
},
|
},
|
||||||
) => self.compile_inlined(
|
) => self.compile_inlined(
|
||||||
ct,
|
ct,
|
||||||
terms,
|
focused_heap,
|
||||||
clause.term_loc(),
|
clause.term_loc(),
|
||||||
context,
|
context,
|
||||||
branch_code_stack.code(code),
|
branch_code_stack.code(code),
|
||||||
@@ -1241,7 +1148,7 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
}
|
}
|
||||||
QueryTerm::Clause(clause) => {
|
QueryTerm::Clause(clause) => {
|
||||||
self.compile_query_line(
|
self.compile_query_line(
|
||||||
terms,
|
focused_heap,
|
||||||
clause,
|
clause,
|
||||||
context,
|
context,
|
||||||
branch_code_stack.code(code),
|
branch_code_stack.code(code),
|
||||||
@@ -1254,7 +1161,6 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_num += 1;
|
|
||||||
self.marker.in_tail_position = false;
|
self.marker.in_tail_position = false;
|
||||||
self.marker.reset_contents();
|
self.marker.reset_contents();
|
||||||
}
|
}
|
||||||
@@ -1324,7 +1230,6 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
let fact = self.compile_target::<FactInstruction, _>(
|
let fact = self.compile_target::<FactInstruction, _>(
|
||||||
iter,
|
iter,
|
||||||
&IndexMap::with_hasher(FxBuildHasher::default()),
|
&IndexMap::with_hasher(FxBuildHasher::default()),
|
||||||
&mut term.var_locs,
|
|
||||||
GenContext::Head,
|
GenContext::Head,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1360,7 +1265,6 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
let compiled_fact = self.compile_target::<FactInstruction, _>(
|
let compiled_fact = self.compile_target::<FactInstruction, _>(
|
||||||
iter,
|
iter,
|
||||||
&IndexMap::with_hasher(FxBuildHasher::default()),
|
&IndexMap::with_hasher(FxBuildHasher::default()),
|
||||||
&mut fact.term.var_locs,
|
|
||||||
GenContext::Head,
|
GenContext::Head,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1389,7 +1293,6 @@ impl<'b> CodeGenerator<'b> {
|
|||||||
let query = self.compile_target::<QueryInstruction, _>(
|
let query = self.compile_target::<QueryInstruction, _>(
|
||||||
iter,
|
iter,
|
||||||
&clause.code_indices,
|
&clause.code_indices,
|
||||||
&mut term.var_locs,
|
|
||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::allocator::*;
|
use crate::allocator::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::codegen::SubsumedBranchHits;
|
use crate::codegen::SubsumedBranchHits;
|
||||||
use crate::forms::Level;
|
use crate::forms::{GenContext, Level};
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine::disjuncts::VarData;
|
use crate::machine::disjuncts::*;
|
||||||
use crate::machine::heap::{heap_bound_deref, heap_bound_store};
|
use crate::machine::heap::{heap_bound_deref, heap_bound_store};
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
use crate::targets::*;
|
use crate::targets::*;
|
||||||
@@ -556,7 +556,10 @@ impl DebrayAllocator {
|
|||||||
VarAlloc::Temp { safety, .. } => {
|
VarAlloc::Temp { safety, .. } => {
|
||||||
*safety = VarSafetyStatus::unneeded(branch_designator);
|
*safety = VarSafetyStatus::unneeded(branch_designator);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => {
|
||||||
|
// the (permanent) variable might have been freed by
|
||||||
|
// this point, in which case we do nothing.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,7 +706,7 @@ impl Allocator for DebrayAllocator {
|
|||||||
lvl: Level,
|
lvl: Level,
|
||||||
context: GenContext,
|
context: GenContext,
|
||||||
code: &mut CodeDeque,
|
code: &mut CodeDeque,
|
||||||
) {
|
) -> RegType {
|
||||||
let r = RegType::Temp(self.alloc_reg_to_non_var());
|
let r = RegType::Temp(self.alloc_reg_to_non_var());
|
||||||
|
|
||||||
match lvl {
|
match lvl {
|
||||||
@@ -720,6 +723,8 @@ impl Allocator for DebrayAllocator {
|
|||||||
code.push_back(Target::argument_to_variable(r, k));
|
code.push_back(Target::argument_to_variable(r, k));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
|
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
|
||||||
@@ -934,17 +939,23 @@ impl Allocator for DebrayAllocator {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let h = var.get_value() as usize;
|
let term_loc = 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 {
|
match self.var_data.var_locs_to_nums.get(
|
||||||
self.in_use.insert(idx + 1);
|
VarPtrIndex { chunk_num: 0, term_loc },
|
||||||
self.shallow_temp_mappings.insert(idx + 1, var_num);
|
) {
|
||||||
self.var_data.records[var_num]
|
VarPtr::Numbered(var_num) => {
|
||||||
.allocation
|
let r = self.get_var_binding(var_num);
|
||||||
.set_register(idx + 1);
|
|
||||||
|
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 => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
99
src/forms.rs
99
src/forms.rs
@@ -72,6 +72,37 @@ pub enum CallPolicy {
|
|||||||
Counted,
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum ChunkType {
|
pub enum ChunkType {
|
||||||
Head,
|
Head,
|
||||||
@@ -98,12 +129,14 @@ impl ChunkType {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ChunkedTerms {
|
pub enum ChunkedTerms {
|
||||||
Branch(Vec<VecDeque<ChunkedTerms>>),
|
Branch(Vec<VecDeque<ChunkedTerms>>),
|
||||||
Chunk(VecDeque<QueryTerm>),
|
Chunk { chunk_num: usize, terms: VecDeque<QueryTerm> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ChunkedTermVec {
|
pub struct ChunkedTermVec {
|
||||||
pub chunk_vec: VecDeque<ChunkedTerms>,
|
pub chunk_vec: VecDeque<ChunkedTerms>,
|
||||||
|
pub current_chunk_num: usize,
|
||||||
|
pub current_chunk_type: ChunkType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for ChunkedTermVec {
|
impl Deref for ChunkedTermVec {
|
||||||
@@ -128,6 +161,8 @@ impl ChunkedTermVec {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
chunk_vec: VecDeque::new(),
|
chunk_vec: VecDeque::new(),
|
||||||
|
current_chunk_num: 0,
|
||||||
|
current_chunk_type: ChunkType::Mid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,24 +171,70 @@ impl ChunkedTermVec {
|
|||||||
.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
|
.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]
|
#[inline]
|
||||||
pub fn add_chunk(&mut self) {
|
pub fn add_chunk(&mut self) {
|
||||||
self.chunk_vec
|
let chunk = ChunkedTerms::Chunk {
|
||||||
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![])));
|
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) {
|
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(_)) => {
|
||||||
self.chunk_vec
|
let chunk = ChunkedTerms::Chunk {
|
||||||
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
|
chunk_num: self.current_chunk_num,
|
||||||
|
terms: VecDeque::from(vec![term]),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.chunk_vec.push_back(chunk);
|
||||||
}
|
}
|
||||||
Some(ChunkedTerms::Chunk(chunk)) => {
|
Some(ChunkedTerms::Chunk { terms, .. }) => {
|
||||||
chunk.push_back(term);
|
terms.push_back(term);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.chunk_vec
|
let chunk = ChunkedTerms::Chunk {
|
||||||
.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
|
chunk_num: self.current_chunk_num,
|
||||||
|
terms: VecDeque::from(vec![term]),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.chunk_vec.push_back(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ pub struct HCPrinter<'a, Outputter> {
|
|||||||
toplevel_spec: Option<DirectedOp>,
|
toplevel_spec: Option<DirectedOp>,
|
||||||
last_item_idx: usize,
|
last_item_idx: usize,
|
||||||
parent_of_first_op: Option<(DirectedOp, 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_offset: Integer,
|
||||||
pub numbervars: bool,
|
pub numbervars: bool,
|
||||||
pub quoted: bool,
|
pub quoted: bool,
|
||||||
@@ -795,7 +795,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
if let Some(var) = self.var_names.get(&cell) {
|
if let Some(var) = self.var_names.get(&cell) {
|
||||||
read_heap_cell!(cell,
|
read_heap_cell!(cell,
|
||||||
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
|
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
|
||||||
return Some(var.borrow().to_string());
|
return Some(var.to_string());
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.iter.push_stack(h);
|
self.iter.push_stack(h);
|
||||||
@@ -837,7 +837,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
// short-circuits handle_heap_term.
|
// short-circuits handle_heap_term.
|
||||||
// self.iter.pop_stack();
|
// self.iter.pop_stack();
|
||||||
|
|
||||||
let var_str = var.borrow().to_string();
|
let var_str = var.to_string();
|
||||||
|
|
||||||
push_space_if_amb!(self, &var_str, {
|
push_space_if_amb!(self, &var_str, {
|
||||||
append_str!(self, &var_str);
|
append_str!(self, &var_str);
|
||||||
@@ -865,7 +865,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
Some(var) => {
|
Some(var) => {
|
||||||
// If the term is bound to a named variable,
|
// If the term is bound to a named variable,
|
||||||
// print the variable's name to output.
|
// 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, {
|
push_space_if_amb!(self, &var_str, {
|
||||||
append_str!(self, &var_str);
|
append_str!(self, &var_str);
|
||||||
@@ -1924,7 +1924,7 @@ mod tests {
|
|||||||
|
|
||||||
printer
|
printer
|
||||||
.var_names
|
.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();
|
let output = printer.print();
|
||||||
|
|
||||||
@@ -1993,7 +1993,7 @@ mod tests {
|
|||||||
|
|
||||||
printer
|
printer
|
||||||
.var_names
|
.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();
|
let output = printer.print();
|
||||||
|
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ pub(crate) enum ClauseItem<'a> {
|
|||||||
FirstBranch(usize),
|
FirstBranch(usize),
|
||||||
NextBranch,
|
NextBranch,
|
||||||
BranchEnd(usize),
|
BranchEnd(usize),
|
||||||
Chunk(&'a VecDeque<QueryTerm>),
|
Chunk { chunk_num: usize, terms: &'a VecDeque<QueryTerm> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -275,9 +275,10 @@ 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(terms, focus)
|
||||||
depth += 1;
|
if terms.len() == focus => {
|
||||||
}
|
depth += 1;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.state_stack.push(state);
|
self.state_stack.push(state);
|
||||||
break;
|
break;
|
||||||
@@ -295,24 +296,25 @@ impl<'a> Iterator for ClauseIterator<'a> {
|
|||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while let Some(state) = self.state_stack.pop() {
|
while let Some(state) = self.state_stack.pop() {
|
||||||
match state {
|
match state {
|
||||||
ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => {
|
ClauseIteratorState::RemainingChunks(chunks, focus)
|
||||||
if focus + 1 < chunks.len() {
|
if focus < chunks.len() => {
|
||||||
self.state_stack
|
if focus + 1 < chunks.len() {
|
||||||
.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
|
|
||||||
} else {
|
|
||||||
self.remaining_chunks_on_stack -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
match &chunks[focus] {
|
|
||||||
ChunkedTerms::Branch(branches) => {
|
|
||||||
self.state_stack
|
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) => {
|
ClauseIteratorState::RemainingChunks(chunks, focus) => {
|
||||||
debug_assert_eq!(chunks.len(), focus);
|
debug_assert_eq!(chunks.len(), focus);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1156,7 +1156,7 @@ impl MachineState {
|
|||||||
) -> Result<Number, MachineStub> {
|
) -> Result<Number, MachineStub> {
|
||||||
let stub_gen = || functor_stub(atom!("is"), 2);
|
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
|
value.get_value() as usize
|
||||||
} else {
|
} else {
|
||||||
let type_error = self.type_error(ValidType::Evaluable, value);
|
let type_error = self.type_error(ValidType::Evaluable, value);
|
||||||
|
|||||||
@@ -2283,40 +2283,36 @@ impl Machine {
|
|||||||
term_reg: RegType,
|
term_reg: RegType,
|
||||||
vars: Vec<HeapCellValue>,
|
vars: Vec<HeapCellValue>,
|
||||||
) -> Result<(), SessionError> {
|
) -> Result<(), SessionError> {
|
||||||
let cell = self.machine_st.store(self.machine_st.deref(self.machine_st[term_reg]));
|
let body_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 new_header_loc = self.machine_st.heap.len();
|
let new_header_loc = self.machine_st.heap.len();
|
||||||
let new_arity = old_arity + vars.len();
|
let arity = vars.len();
|
||||||
|
|
||||||
self.machine_st.heap.push(atom_as_cell!(name, new_arity));
|
self.machine_st.heap.push(atom_as_cell!(atom!(""), arity));
|
||||||
|
|
||||||
for idx in header_loc + 1 .. header_loc + 1 + old_arity {
|
|
||||||
self.machine_st.heap.push(self.machine_st.heap[idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for var in vars {
|
for var in vars {
|
||||||
self.machine_st.heap.push(var);
|
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)
|
str_loc_as_cell!(new_header_loc)
|
||||||
} else {
|
} else {
|
||||||
heap_loc_as_cell!(new_header_loc)
|
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;
|
use crate::heap_iter::eager_stackful_preorder_iter;
|
||||||
|
|
||||||
let mut loader: Loader<'_, InlineLoadState<'_>> =
|
let mut loader: Loader<'_, InlineLoadState<'_>> =
|
||||||
Loader::new(self, InlineTermStream {});
|
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 {
|
let settings = CodeGenSettings {
|
||||||
global_clock_tick: None,
|
global_clock_tick: None,
|
||||||
@@ -2326,14 +2322,14 @@ impl Machine {
|
|||||||
|
|
||||||
let value = term.heap[term.focus];
|
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),
|
eager_stackful_preorder_iter(&mut term.heap, value),
|
||||||
);
|
);
|
||||||
|
|
||||||
loader.compile_standalone_clause(term, settings)
|
loader.compile_standalone_clause(term, settings)
|
||||||
};
|
};
|
||||||
|
|
||||||
let StandaloneCompileResult { clause_code, .. } = compile(value)?;
|
let StandaloneCompileResult { clause_code, .. } = compile()?;
|
||||||
self.code.extend(clause_code);
|
self.code.extend(clause_code);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -80,9 +80,34 @@ impl BranchNumber {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct VarInfo {
|
pub struct VarInfo {
|
||||||
var_ptr: VarPtr,
|
var: ClassifiedVar,
|
||||||
chunk_type: ChunkType,
|
chunk_type: ChunkType,
|
||||||
classify_info: ClassifyInfo,
|
classify_info: ClassifyInfo,
|
||||||
lvl: Level,
|
lvl: Level,
|
||||||
@@ -90,7 +115,6 @@ pub struct VarInfo {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ChunkInfo {
|
pub struct ChunkInfo {
|
||||||
chunk_num: usize,
|
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
// pointer to incidence, term occurrence arity.
|
// pointer to incidence, term occurrence arity.
|
||||||
vars: Vec<VarInfo>,
|
vars: Vec<VarInfo>,
|
||||||
@@ -111,7 +135,7 @@ impl BranchInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type BranchMapInt = IndexMap<VarPtr, Vec<BranchInfo>>;
|
type BranchMapInt = IndexMap<ClassifiedVar, Vec<BranchInfo>>;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BranchMap(BranchMapInt);
|
pub struct BranchMap(BranchMapInt);
|
||||||
@@ -174,8 +198,6 @@ enum TraversalState {
|
|||||||
pub struct VariableClassifier {
|
pub struct VariableClassifier {
|
||||||
call_policy: CallPolicy,
|
call_policy: CallPolicy,
|
||||||
current_branch_num: BranchNumber,
|
current_branch_num: BranchNumber,
|
||||||
current_chunk_num: usize,
|
|
||||||
current_chunk_type: ChunkType,
|
|
||||||
branch_map: BranchMap,
|
branch_map: BranchMap,
|
||||||
var_num: usize,
|
var_num: usize,
|
||||||
root_set: RootSet,
|
root_set: RootSet,
|
||||||
@@ -183,11 +205,42 @@ pub struct VariableClassifier {
|
|||||||
global_cut_var_num_override: Option<usize>,
|
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)]
|
#[derive(Debug, Default)]
|
||||||
pub struct VarData {
|
pub struct VarData {
|
||||||
pub records: VariableRecords,
|
pub records: VariableRecords,
|
||||||
pub global_cut_var_num: Option<usize>,
|
pub global_cut_var_num: Option<usize>,
|
||||||
pub allocates: bool,
|
pub allocates: bool,
|
||||||
|
pub var_locs_to_nums: VarLocsToNums,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VarData {
|
impl VarData {
|
||||||
@@ -211,10 +264,13 @@ impl VarData {
|
|||||||
|
|
||||||
match build_stack.front_mut() {
|
match build_stack.front_mut() {
|
||||||
Some(ChunkedTerms::Branch(_)) => {
|
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)) => {
|
Some(ChunkedTerms::Chunk { terms, .. }) => {
|
||||||
chunk.push_front(term);
|
terms.push_front(term);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@@ -256,8 +312,6 @@ impl VariableClassifier {
|
|||||||
Self {
|
Self {
|
||||||
call_policy,
|
call_policy,
|
||||||
current_branch_num: BranchNumber::default(),
|
current_branch_num: BranchNumber::default(),
|
||||||
current_chunk_num: 0,
|
|
||||||
current_chunk_type: ChunkType::Head,
|
|
||||||
branch_map: BranchMap(BranchMapInt::new()),
|
branch_map: BranchMap(BranchMapInt::new()),
|
||||||
root_set: RootSet::new(),
|
root_set: RootSet::new(),
|
||||||
var_num: 0,
|
var_num: 0,
|
||||||
@@ -276,7 +330,7 @@ impl VariableClassifier {
|
|||||||
Ok(self.branch_map.separate_and_classify_variables(
|
Ok(self.branch_map.separate_and_classify_variables(
|
||||||
self.var_num,
|
self.var_num,
|
||||||
self.global_cut_var_num,
|
self.global_cut_var_num,
|
||||||
self.current_chunk_num,
|
0,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +352,7 @@ impl VariableClassifier {
|
|||||||
let mut var_data = self.branch_map.separate_and_classify_variables(
|
let mut var_data = self.branch_map.separate_and_classify_variables(
|
||||||
self.var_num,
|
self.var_num,
|
||||||
self.global_cut_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);
|
var_data.emit_initial_get_level(&mut query_terms);
|
||||||
@@ -327,32 +381,13 @@ impl VariableClassifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
fn probe_body_term(
|
||||||
&mut self,
|
&mut self,
|
||||||
arg_c: usize,
|
arg_c: usize,
|
||||||
arity: usize,
|
arity: usize,
|
||||||
term: &mut FocusedHeap,
|
term: &mut FocusedHeap,
|
||||||
term_loc: usize,
|
term_loc: usize,
|
||||||
|
context: GenContext,
|
||||||
) {
|
) {
|
||||||
let classify_info = ClassifyInfo { arg_c, arity };
|
let classify_info = ClassifyInfo { arg_c, arity };
|
||||||
|
|
||||||
@@ -372,23 +407,24 @@ impl VariableClassifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let var_loc = subterm.get_value() as usize;
|
let var_loc = subterm.get_value() as usize;
|
||||||
let var_ptr = term.var_locs.read_next_var_ptr_at_key(var_loc).unwrap();
|
let var = to_classified_var(&term.inverse_var_locs, var_loc);
|
||||||
|
|
||||||
self.probe_body_var(VarInfo {
|
self.probe_body_var(
|
||||||
var_ptr: var_ptr.clone(),
|
context,
|
||||||
lvl,
|
VarInfo {
|
||||||
classify_info,
|
var,
|
||||||
chunk_type: self.current_chunk_type,
|
lvl,
|
||||||
});
|
classify_info,
|
||||||
|
chunk_type: context.chunk_type(),
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn probe_body_var(&mut self, var_info: VarInfo) {
|
fn probe_body_var(&mut self, context: GenContext, var_info: VarInfo) {
|
||||||
let term_loc = self
|
let chunk_num = context.chunk_num();
|
||||||
.current_chunk_type
|
let branch_info_v = self.branch_map.entry(var_info.var)
|
||||||
.to_gen_context(self.current_chunk_num);
|
.or_default();
|
||||||
|
|
||||||
let branch_info_v = self.branch_map.entry(var_info.var_ptr.clone()).or_default();
|
|
||||||
|
|
||||||
let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
|
let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
|
||||||
!self.root_set.contains(&last_bi.branch_num)
|
!self.root_set.contains(&last_bi.branch_num)
|
||||||
@@ -403,15 +439,14 @@ impl VariableClassifier {
|
|||||||
let branch_info = branch_info_v.last_mut().unwrap();
|
let branch_info = branch_info_v.last_mut().unwrap();
|
||||||
|
|
||||||
let needs_new_chunk = if let Some(last_ci) = branch_info.chunks.last() {
|
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 {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
|
||||||
if needs_new_chunk {
|
if needs_new_chunk {
|
||||||
branch_info.chunks.push(ChunkInfo {
|
branch_info.chunks.push(ChunkInfo {
|
||||||
chunk_num: self.current_chunk_num,
|
term_loc: context,
|
||||||
term_loc,
|
|
||||||
vars: vec![],
|
vars: vec![],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -420,17 +455,17 @@ impl VariableClassifier {
|
|||||||
chunk_info.vars.push(var_info);
|
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 classify_info = ClassifyInfo { arg_c: 1, arity: 1 };
|
||||||
|
|
||||||
let var_info = VarInfo {
|
let var_info = VarInfo {
|
||||||
var_ptr: VarPtr::from(Var::InSitu(var_num)),
|
var: ClassifiedVar::InSitu { var_num },
|
||||||
classify_info,
|
classify_info,
|
||||||
chunk_type: self.current_chunk_type,
|
chunk_type: context.chunk_type(),
|
||||||
lvl: Level::Shallow,
|
lvl: Level::Shallow,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.probe_body_var(var_info);
|
self.probe_body_var(context, var_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn classify_head_variables(
|
fn classify_head_variables(
|
||||||
@@ -473,13 +508,13 @@ impl VariableClassifier {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let h = subterm.get_value() as usize;
|
let term_loc = subterm.get_value() as usize;
|
||||||
let var_ptr = term.var_locs.read_next_var_ptr_at_key(h).unwrap().clone();
|
let var = to_classified_var(&term.inverse_var_locs, term_loc);
|
||||||
|
|
||||||
// the body of the if let here is an inlined
|
// the body of the if let here is an inlined
|
||||||
// "probe_head_var". note the difference between it
|
// "probe_head_var". note the difference between it
|
||||||
// and "probe_body_var".
|
// 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();
|
let needs_new_branch = branch_info_v.is_empty();
|
||||||
|
|
||||||
if needs_new_branch {
|
if needs_new_branch {
|
||||||
@@ -491,7 +526,6 @@ impl VariableClassifier {
|
|||||||
|
|
||||||
if needs_new_chunk {
|
if needs_new_chunk {
|
||||||
branch_info.chunks.push(ChunkInfo {
|
branch_info.chunks.push(ChunkInfo {
|
||||||
chunk_num: self.current_chunk_num,
|
|
||||||
term_loc: GenContext::Head,
|
term_loc: GenContext::Head,
|
||||||
vars: vec![],
|
vars: vec![],
|
||||||
});
|
});
|
||||||
@@ -499,9 +533,9 @@ impl VariableClassifier {
|
|||||||
|
|
||||||
let chunk_info = branch_info.chunks.last_mut().unwrap();
|
let chunk_info = branch_info.chunks.last_mut().unwrap();
|
||||||
let var_info = VarInfo {
|
let var_info = VarInfo {
|
||||||
var_ptr,
|
var,
|
||||||
classify_info,
|
classify_info,
|
||||||
chunk_type: self.current_chunk_type,
|
chunk_type: ChunkType::Head,
|
||||||
lvl,
|
lvl,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -515,7 +549,7 @@ impl VariableClassifier {
|
|||||||
Ok(())
|
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 {
|
let (var_num, is_global) = if let Some(var_num) = self.global_cut_var_num_override {
|
||||||
(var_num, false)
|
(var_num, false)
|
||||||
} else if let Some(var_num) = self.global_cut_var_num {
|
} else if let Some(var_num) = self.global_cut_var_num {
|
||||||
@@ -529,7 +563,7 @@ impl VariableClassifier {
|
|||||||
(var_num, true)
|
(var_num, true)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.probe_in_situ_var(var_num);
|
self.probe_in_situ_var(context, var_num);
|
||||||
|
|
||||||
TraversalState::Cut { var_num, is_global }
|
TraversalState::Cut { var_num, is_global }
|
||||||
}
|
}
|
||||||
@@ -546,8 +580,6 @@ impl VariableClassifier {
|
|||||||
}];
|
}];
|
||||||
let mut build_stack = ChunkedTermVec::new();
|
let mut build_stack = ChunkedTermVec::new();
|
||||||
|
|
||||||
self.current_chunk_type = ChunkType::Mid;
|
|
||||||
|
|
||||||
'outer: while let Some(traversal_st) = state_stack.pop() {
|
'outer: while let Some(traversal_st) = state_stack.pop() {
|
||||||
match traversal_st {
|
match traversal_st {
|
||||||
TraversalState::AddBranchNum(branch_num) => {
|
TraversalState::AddBranchNum(branch_num) => {
|
||||||
@@ -568,21 +600,22 @@ impl VariableClassifier {
|
|||||||
TraversalState::BuildDisjunct(preceding_len) => {
|
TraversalState::BuildDisjunct(preceding_len) => {
|
||||||
flatten_into_disjunct(&mut build_stack, preceding_len);
|
flatten_into_disjunct(&mut build_stack, preceding_len);
|
||||||
|
|
||||||
self.current_chunk_type = ChunkType::Mid;
|
build_stack.current_chunk_type = ChunkType::Mid;
|
||||||
self.current_chunk_num += 1;
|
build_stack.current_chunk_num += 1;
|
||||||
}
|
}
|
||||||
TraversalState::BuildFinalDisjunct(preceding_len) => {
|
TraversalState::BuildFinalDisjunct(preceding_len) => {
|
||||||
flatten_into_disjunct(&mut build_stack, preceding_len);
|
flatten_into_disjunct(&mut build_stack, preceding_len);
|
||||||
|
|
||||||
self.current_chunk_type = ChunkType::Mid;
|
build_stack.current_chunk_type = ChunkType::Mid;
|
||||||
self.current_chunk_num += 1;
|
build_stack.current_chunk_num += 1;
|
||||||
}
|
}
|
||||||
TraversalState::GetCutPoint { var_num, prev_b } => {
|
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();
|
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 });
|
build_stack.push_chunk_term(QueryTerm::GetCutPoint { var_num, prev_b });
|
||||||
}
|
}
|
||||||
TraversalState::OverrideGlobalCutVar(var_num) => {
|
TraversalState::OverrideGlobalCutVar(var_num) => {
|
||||||
@@ -592,11 +625,12 @@ impl VariableClassifier {
|
|||||||
self.global_cut_var_num_override = old_override;
|
self.global_cut_var_num_override = old_override;
|
||||||
}
|
}
|
||||||
TraversalState::Cut { var_num, is_global } => {
|
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();
|
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 {
|
build_stack.push_chunk_term(if is_global {
|
||||||
QueryTerm::GlobalCut(var_num)
|
QueryTerm::GlobalCut(var_num)
|
||||||
@@ -608,11 +642,12 @@ impl VariableClassifier {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
TraversalState::CutPrev(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();
|
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 {
|
build_stack.push_chunk_term(QueryTerm::LocalCut {
|
||||||
var_num,
|
var_num,
|
||||||
@@ -630,24 +665,26 @@ impl VariableClassifier {
|
|||||||
mut term_loc,
|
mut term_loc,
|
||||||
} => {
|
} => {
|
||||||
// return true iff new chunk should be added.
|
// 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) {
|
if ClauseType::is_inlined(key.0, key.1) {
|
||||||
classifier.try_set_chunk_at_inlined_boundary()
|
build_stack.try_set_chunk_at_inlined_boundary()
|
||||||
} else {
|
} else {
|
||||||
classifier.try_set_chunk_at_call_boundary()
|
build_stack.try_set_chunk_at_call_boundary()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! add_chunk {
|
macro_rules! add_chunk {
|
||||||
($classifier:ident, $key:expr, $tag:expr, $term_loc:expr) => {{
|
($key:expr, $tag:expr, $term_loc:expr) => {{
|
||||||
if update_chunk_data($classifier, $key) {
|
if update_chunk_data(&mut build_stack, $key) {
|
||||||
build_stack.add_chunk();
|
build_stack.add_chunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let context = build_stack.current_gen_context();
|
||||||
|
|
||||||
for (arg_c, term_loc) in
|
for (arg_c, term_loc) in
|
||||||
($term_loc + 1 ..= $term_loc + $key.1).enumerate()
|
($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(
|
build_stack.push_chunk_term(QueryTerm::Clause(clause_to_query_term(
|
||||||
@@ -655,21 +692,23 @@ impl VariableClassifier {
|
|||||||
$key,
|
$key,
|
||||||
terms.as_ref_mut($term_loc),
|
terms.as_ref_mut($term_loc),
|
||||||
HeapCellValue::build_with($tag, $term_loc as u64),
|
HeapCellValue::build_with($tag, $term_loc as u64),
|
||||||
$classifier.call_policy,
|
self.call_policy,
|
||||||
)));
|
)));
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! add_qualified_chunk {
|
macro_rules! add_qualified_chunk {
|
||||||
($classifier:ident, $module_name:expr, $key:expr, $tag:expr, $term_loc:expr) => {{
|
($module_name:expr, $key:expr, $tag:expr, $term_loc:expr) => {{
|
||||||
if update_chunk_data($classifier, $key) {
|
if update_chunk_data(&mut build_stack, $key) {
|
||||||
build_stack.add_chunk();
|
build_stack.add_chunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let context = build_stack.current_gen_context();
|
||||||
|
|
||||||
for (arg_c, term_loc) in
|
for (arg_c, term_loc) in
|
||||||
($term_loc + 1..$term_loc + $key.1 + 1).enumerate()
|
($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(
|
build_stack.push_chunk_term(QueryTerm::Clause(
|
||||||
@@ -679,7 +718,7 @@ impl VariableClassifier {
|
|||||||
$module_name,
|
$module_name,
|
||||||
terms.as_ref_mut($term_loc),
|
terms.as_ref_mut($term_loc),
|
||||||
HeapCellValue::build_with($tag, $term_loc as u64),
|
HeapCellValue::build_with($tag, $term_loc as u64),
|
||||||
$classifier.call_policy,
|
self.call_policy,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}};
|
}};
|
||||||
@@ -698,7 +737,7 @@ impl VariableClassifier {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_chunk!(self, (name, 2), HeapCellValueTag::Str, subterm_loc);
|
add_chunk!((name, 2), HeapCellValueTag::Str, subterm_loc);
|
||||||
}
|
}
|
||||||
(atom!(","), 2) => {
|
(atom!(","), 2) => {
|
||||||
let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
|
let head_loc = terms.nth_arg(subterm_loc, 1).unwrap();
|
||||||
@@ -764,8 +803,8 @@ impl VariableClassifier {
|
|||||||
TraversalState::BuildFinalDisjunct(build_stack_len);
|
TraversalState::BuildFinalDisjunct(build_stack_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.current_chunk_type = ChunkType::Mid;
|
build_stack.current_chunk_type = ChunkType::Mid;
|
||||||
self.current_chunk_num += 1;
|
build_stack.current_chunk_num += 1;
|
||||||
}
|
}
|
||||||
(atom!("->"), 2) => {
|
(atom!("->"), 2) => {
|
||||||
let if_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
|
let if_term_loc = terms.nth_arg(subterm_loc, 1).unwrap();
|
||||||
@@ -841,8 +880,8 @@ impl VariableClassifier {
|
|||||||
});
|
});
|
||||||
state_stack.push(TraversalState::AddBranchNum(branch_num));
|
state_stack.push(TraversalState::AddBranchNum(branch_num));
|
||||||
|
|
||||||
self.current_chunk_type = ChunkType::Mid;
|
build_stack.current_chunk_type = ChunkType::Mid;
|
||||||
self.current_chunk_num += 1;
|
build_stack.current_chunk_num += 1;
|
||||||
|
|
||||||
self.var_num += 1;
|
self.var_num += 1;
|
||||||
}
|
}
|
||||||
@@ -862,7 +901,6 @@ impl VariableClassifier {
|
|||||||
.get_name_and_arity();
|
.get_name_and_arity();
|
||||||
|
|
||||||
add_qualified_chunk!(
|
add_qualified_chunk!(
|
||||||
self,
|
|
||||||
module_name,
|
module_name,
|
||||||
key,
|
key,
|
||||||
HeapCellValueTag::Str,
|
HeapCellValueTag::Str,
|
||||||
@@ -874,7 +912,6 @@ impl VariableClassifier {
|
|||||||
let key = (predicate_name, predicate_arity);
|
let key = (predicate_name, predicate_arity);
|
||||||
|
|
||||||
add_qualified_chunk!(
|
add_qualified_chunk!(
|
||||||
self,
|
|
||||||
module_name,
|
module_name,
|
||||||
key,
|
key,
|
||||||
HeapCellValueTag::Str,
|
HeapCellValueTag::Str,
|
||||||
@@ -890,12 +927,14 @@ impl VariableClassifier {
|
|||||||
_ => {}
|
_ => {}
|
||||||
);
|
);
|
||||||
|
|
||||||
if update_chunk_data(self, (atom!("call"), 2)) {
|
if update_chunk_data(&mut build_stack, (atom!("call"), 2)) {
|
||||||
build_stack.add_chunk();
|
build_stack.add_chunk();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.probe_body_term(1, 0, terms, module_name_loc);
|
let context = build_stack.current_gen_context();
|
||||||
self.probe_body_term(2, 0, terms, predicate_term_loc);
|
|
||||||
|
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();
|
let h = terms.heap.len();
|
||||||
|
|
||||||
@@ -920,7 +959,7 @@ impl VariableClassifier {
|
|||||||
self.call_policy = CallPolicy::Counted;
|
self.call_policy = CallPolicy::Counted;
|
||||||
}
|
}
|
||||||
(name, arity) => {
|
(name, arity) => {
|
||||||
add_chunk!(self, (name, arity), HeapCellValueTag::Str, subterm_loc);
|
add_chunk!((name, arity), HeapCellValueTag::Str, subterm_loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -928,14 +967,16 @@ impl VariableClassifier {
|
|||||||
debug_assert_eq!(arity, 0);
|
debug_assert_eq!(arity, 0);
|
||||||
|
|
||||||
if name == atom!("!") {
|
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 {
|
} else {
|
||||||
add_chunk!(self, (name, 0), HeapCellValueTag::Var, term_loc);
|
add_chunk!((name, 0), HeapCellValueTag::Var, term_loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Char, c) => {
|
(HeapCellValueTag::Char, c) => {
|
||||||
if 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 {
|
} else {
|
||||||
return Err(CompilationError::InadmissibleQueryTerm);
|
return Err(CompilationError::InadmissibleQueryTerm);
|
||||||
}
|
}
|
||||||
@@ -947,7 +988,7 @@ impl VariableClassifier {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_chunk!(self, (atom!("call"), 1), HeapCellValueTag::Var, h);
|
add_chunk!((atom!("call"), 1), HeapCellValueTag::Var, h);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(CompilationError::InadmissibleQueryTerm);
|
return Err(CompilationError::InadmissibleQueryTerm);
|
||||||
@@ -975,13 +1016,13 @@ impl BranchMap {
|
|||||||
records: VariableRecords::new(var_num),
|
records: VariableRecords::new(var_num),
|
||||||
global_cut_var_num,
|
global_cut_var_num,
|
||||||
allocates: current_chunk_num > 0,
|
allocates: current_chunk_num > 0,
|
||||||
|
var_locs_to_nums: VarLocsToNums::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for (var, branches) in self.iter_mut() {
|
for (var, branches) in self.iter_mut() {
|
||||||
let (mut var_num, var_num_incr) = if let Var::InSitu(var_num) = *var.borrow() {
|
let (mut var_num, var_num_incr) = match var {
|
||||||
(var_num, false)
|
&ClassifiedVar::InSitu { var_num} => (var_num, false),
|
||||||
} else {
|
_ => (var_data.records.len(), true)
|
||||||
(var_data.records.len(), true)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for branch in branches.iter_mut() {
|
for branch in branches.iter_mut() {
|
||||||
@@ -999,10 +1040,13 @@ impl BranchMap {
|
|||||||
|
|
||||||
for var_info in chunk.vars.iter_mut() {
|
for var_info in chunk.vars.iter_mut() {
|
||||||
if var_info.lvl == Level::Shallow {
|
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
|
temp_var_data
|
||||||
.use_set
|
.use_set
|
||||||
.insert((term_loc, var_info.classify_info.arg_c));
|
.insert((context, var_info.classify_info.arg_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,9 +1062,13 @@ impl BranchMap {
|
|||||||
for chunk in branch.chunks.iter_mut() {
|
for chunk in branch.chunks.iter_mut() {
|
||||||
var_data.records[var_num].num_occurrences += chunk.vars.len();
|
var_data.records[var_num].num_occurrences += chunk.vars.len();
|
||||||
|
|
||||||
for var_info in chunk.vars.iter_mut() {
|
if let Some(term_loc) = var.term_loc() {
|
||||||
let is_anon = var_info.var_ptr.is_anon();
|
let chunk_num = chunk.term_loc.chunk_num();
|
||||||
var_info.var_ptr.set(Var::Generated { is_anon, var_num });
|
|
||||||
|
var_data.var_locs_to_nums.insert(
|
||||||
|
VarPtrIndex { chunk_num, term_loc },
|
||||||
|
var_num,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,10 +33,12 @@ pub(crate) trait UnmarkPolicy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub(crate) struct IteratorUMP {
|
pub(crate) struct IteratorUMP {
|
||||||
mark_phase: bool,
|
mark_phase: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
fn invert_marker<UMP: UnmarkPolicy>(iter: &mut StacklessPreOrderHeapIter<UMP>) {
|
fn invert_marker<UMP: UnmarkPolicy>(iter: &mut StacklessPreOrderHeapIter<UMP>) {
|
||||||
if iter.heap[iter.start].get_forwarding_bit() {
|
if iter.heap[iter.start].get_forwarding_bit() {
|
||||||
while !iter.backward() {}
|
while !iter.backward() {}
|
||||||
@@ -50,6 +52,7 @@ fn invert_marker<UMP: UnmarkPolicy>(iter: &mut StacklessPreOrderHeapIter<UMP>) {
|
|||||||
while iter.forward().is_some() {}
|
while iter.forward().is_some() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
impl UnmarkPolicy for IteratorUMP {
|
impl UnmarkPolicy for IteratorUMP {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue> {
|
fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue> {
|
||||||
@@ -150,8 +153,8 @@ impl<'a> StacklessPreOrderHeapIter<'a, MarkerUMP> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
impl<'a> StacklessPreOrderHeapIter<'a, IteratorUMP> {
|
impl<'a> StacklessPreOrderHeapIter<'a, IteratorUMP> {
|
||||||
#[cfg(test)]
|
|
||||||
pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self {
|
pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self {
|
||||||
heap[start].set_forwarding_bit(true);
|
heap[start].set_forwarding_bit(true);
|
||||||
let next = heap[start].get_value();
|
let next = heap[start].get_value();
|
||||||
|
|||||||
@@ -467,11 +467,20 @@ impl Iterator for QueryState<'_> {
|
|||||||
// this should halt the search for solutions as it
|
// this should halt the search for solutions as it
|
||||||
// does in the Scryer top-level. the exception term is
|
// does in the Scryer top-level. the exception term is
|
||||||
// contained in self.machine_st.ball.
|
// contained in self.machine_st.ball.
|
||||||
let h = machine.machine_st.heap.len();
|
let h = machine.machine_st.heap.cell_len();
|
||||||
machine
|
|
||||||
|
if let Err(resource_err_loc) = machine
|
||||||
.machine_st
|
.machine_st
|
||||||
.heap
|
.heap
|
||||||
.extend(machine.machine_st.ball.stub.clone());
|
.append(&machine.machine_st.ball.stub)
|
||||||
|
{
|
||||||
|
return Some(Err(Term::from_heapcell(
|
||||||
|
machine,
|
||||||
|
machine.machine_st.heap[resource_err_loc],
|
||||||
|
&mut IndexMap::new(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
let exception_term =
|
let exception_term =
|
||||||
Term::from_heapcell(machine, machine.machine_st.heap[h], &mut var_names.clone());
|
Term::from_heapcell(machine, machine.machine_st.heap[h], &mut var_names.clone());
|
||||||
|
|
||||||
@@ -487,7 +496,7 @@ impl Iterator for QueryState<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if machine.machine_st.p == LIB_QUERY_SUCCESS {
|
if machine.machine_st.p == LIB_QUERY_SUCCESS {
|
||||||
if term_write_result.var_dict.is_empty() {
|
if term_write_result.inverse_var_locs.is_empty() {
|
||||||
self.machine.machine_st.backtrack();
|
self.machine.machine_st.backtrack();
|
||||||
return Some(Ok(LeafAnswer::True));
|
return Some(Ok(LeafAnswer::True));
|
||||||
}
|
}
|
||||||
@@ -496,47 +505,39 @@ impl Iterator for QueryState<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut bindings: BTreeMap<String, Term> = BTreeMap::new();
|
let mut bindings: BTreeMap<String, Term> = BTreeMap::new();
|
||||||
|
let inverse_var_locs = &term_write_result.inverse_var_locs;
|
||||||
|
|
||||||
let var_dict = &term_write_result.var_dict;
|
for (var_loc, var_name) in inverse_var_locs.iter() {
|
||||||
|
|
||||||
for (var_key, term_to_be_printed) in var_dict.iter() {
|
|
||||||
let mut var_name = var_key.to_string();
|
|
||||||
if var_name.starts_with('_') {
|
if var_name.starts_with('_') {
|
||||||
let should_print = var_names.values().any(|x| match x.borrow().clone() {
|
let should_print = var_names.values().any(|v| v == var_name);
|
||||||
Var::Named(v) => v == var_name,
|
|
||||||
_ => false,
|
|
||||||
});
|
|
||||||
if !should_print {
|
if !should_print {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut term =
|
let var_loc = *var_loc;
|
||||||
Term::from_heapcell(machine, *term_to_be_printed, &mut var_names.clone());
|
let term =
|
||||||
|
Term::from_heapcell(machine, heap_loc_as_cell!(var_loc), &mut var_names.clone());
|
||||||
|
|
||||||
if let Term::Var(ref term_str) = term {
|
if let Term::Var(ref term_str) = term {
|
||||||
if *term_str == var_name {
|
if *term_str == **var_name {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Var dict is in the order things appear in the query. If var_name appears
|
// inverse_var_locs is in the order things appear in
|
||||||
// after term in the query, switch their places.
|
// the query. If var_name appears after term in the
|
||||||
let var_name_idx = var_dict
|
// query, switch their places.
|
||||||
.get_index_of(&VarKey::VarPtr(Var::Named(var_name.clone()).into()))
|
let var_cell = machine
|
||||||
.unwrap();
|
.machine_st
|
||||||
let term_idx =
|
.store(machine.machine_st.deref(machine.machine_st.heap[var_loc]));
|
||||||
var_dict.get_index_of(&VarKey::VarPtr(Var::Named(term_str.clone()).into()));
|
|
||||||
if let Some(idx) = term_idx {
|
if (var_cell.get_value() as usize) < var_loc {
|
||||||
if idx < var_name_idx {
|
bindings.insert(term_str.clone(), Term::Var(var_name.to_string()));
|
||||||
let new_term = Term::Var(var_name);
|
continue;
|
||||||
let new_var_name = term_str.into();
|
|
||||||
term = new_term;
|
|
||||||
var_name = new_var_name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bindings.insert(var_name, term);
|
bindings.insert(var_name.to_string(), term);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: there are outstanding choicepoints, backtrack
|
// NOTE: there are outstanding choicepoints, backtrack
|
||||||
@@ -605,27 +606,10 @@ impl Machine {
|
|||||||
|
|
||||||
self.allocate_stub_choice_point();
|
self.allocate_stub_choice_point();
|
||||||
|
|
||||||
// Write parsed term to heap
|
|
||||||
let term_write_result =
|
|
||||||
write_term_to_heap(&term, &mut self.machine_st.heap, &self.machine_st.atom_tbl)
|
|
||||||
.expect("couldn't write term to heap");
|
|
||||||
|
|
||||||
let var_names: IndexMap<_, _> = term_write_result
|
|
||||||
.var_dict
|
|
||||||
.iter()
|
|
||||||
.map(|(var_key, cell)| match var_key {
|
|
||||||
// NOTE: not the intention behind Var::InSitu here but
|
|
||||||
// we can hijack it to store anonymous variables
|
|
||||||
// without creating problems.
|
|
||||||
VarKey::AnonVar(h) => (*cell, VarPtr::from(Var::InSitu(*h))),
|
|
||||||
VarKey::VarPtr(var_ptr) => (*cell, var_ptr.clone()),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Write term to heap
|
// Write term to heap
|
||||||
self.machine_st.registers[1] = self.machine_st.heap[term_write_result.heap_loc];
|
self.machine_st.registers[1] = self.machine_st.heap[term.focus];
|
||||||
|
|
||||||
self.machine_st.cp = LIB_QUERY_SUCCESS; // BREAK_FROM_DISPATCH_LOOP_LOC;
|
self.machine_st.cp = LIB_QUERY_SUCCESS; // BREAK_FROM_DISPATCH_LOOP_LOC;
|
||||||
|
|
||||||
let call_index_p = self
|
let call_index_p = self
|
||||||
.indices
|
.indices
|
||||||
.code_dir
|
.code_dir
|
||||||
@@ -634,12 +618,22 @@ impl Machine {
|
|||||||
.local()
|
.local()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let var_names: IndexMap<_, _> = term
|
||||||
|
.inverse_var_locs
|
||||||
|
.iter()
|
||||||
|
.map(|(var_loc, var)| {
|
||||||
|
let cell = self.machine_st.heap[*var_loc];
|
||||||
|
(cell, var.clone())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
self.machine_st.execute_at_index(1, call_index_p);
|
self.machine_st.execute_at_index(1, call_index_p);
|
||||||
|
|
||||||
let stub_b = self.machine_st.b;
|
let stub_b = self.machine_st.b;
|
||||||
|
|
||||||
QueryState {
|
QueryState {
|
||||||
machine: self,
|
machine: self,
|
||||||
term: term_write_result,
|
term,
|
||||||
stub_b,
|
stub_b,
|
||||||
var_names,
|
var_names,
|
||||||
called: false,
|
called: false,
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
let machine_st = LS::machine_st(&mut self.payload);
|
let machine_st = LS::machine_st(&mut self.payload);
|
||||||
|
|
||||||
term.copy_term_from_machine_heap(machine_st, cell);
|
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>(
|
fact_iterator::<false>(
|
||||||
&mut term.heap,
|
&mut term.heap,
|
||||||
&mut stack,
|
&mut stack,
|
||||||
@@ -1107,7 +1107,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let value = term.heap[term.focus];
|
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)
|
Ok(term)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -472,8 +472,8 @@ impl MachineState {
|
|||||||
fn arithmetic_error(&mut self, err: ArithmeticError) -> MachineError {
|
fn arithmetic_error(&mut self, err: ArithmeticError) -> MachineError {
|
||||||
match err {
|
match err {
|
||||||
ArithmeticError::UninstantiatedVar => self.instantiation_error(),
|
ArithmeticError::UninstantiatedVar => self.instantiation_error(),
|
||||||
ArithmeticError::NonEvaluableFunctor(literal, arity) => {
|
ArithmeticError::NonEvaluableFunctor(cell, arity) => {
|
||||||
let culprit = functor!(atom!("/"), [literal(literal), fixnum(arity)]);
|
let culprit = functor!(atom!("/"), [cell(cell), fixnum(arity)]);
|
||||||
|
|
||||||
self.type_error(ValidType::Evaluable, culprit)
|
self.type_error(ValidType::Evaluable, culprit)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use indexmap::IndexMap;
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1];
|
pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1];
|
||||||
@@ -202,13 +203,13 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
|
|||||||
|
|
||||||
fn push_var_eq_functors(
|
fn push_var_eq_functors(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
iter: impl Iterator<Item = (usize, VarPtr)>, // (&'a VarPtr, &'a HeapCellValue)>,
|
iter: impl Iterator<Item = (usize, Var)>,
|
||||||
atom_tbl: &AtomTable,
|
atom_tbl: &AtomTable,
|
||||||
) -> Vec<HeapCellValue> {
|
) -> Vec<HeapCellValue> {
|
||||||
let mut list_of_var_eqs = vec![];
|
let mut list_of_var_eqs = vec![];
|
||||||
|
|
||||||
for (var_loc, var_ptr) in iter { // (var, binding) in iter {
|
for (var_loc, var) in iter { // (var, binding) in iter {
|
||||||
let var_atom = AtomTable::build_with(atom_tbl, &*var_ptr.borrow().to_string());
|
let var_atom = AtomTable::build_with(atom_tbl, &var.to_string());
|
||||||
let h = heap.len();
|
let h = heap.len();
|
||||||
let binding = heap[var_loc];
|
let binding = heap[var_loc];
|
||||||
|
|
||||||
@@ -541,20 +542,15 @@ impl MachineState {
|
|||||||
|
|
||||||
pub fn write_read_term_options(
|
pub fn write_read_term_options(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut var_list: Vec<(VarPtr, HeapCellValue, usize)>,
|
mut var_list: Vec<(Var, HeapCellValue, usize)>,
|
||||||
singleton_var_list: Vec<HeapCellValue>,
|
singleton_var_list: Vec<HeapCellValue>,
|
||||||
) -> CallResult {
|
) -> CallResult {
|
||||||
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
|
var_list.sort_by(|(_, _, idx_1), (_, _, idx_2)| idx_1.cmp(idx_2));
|
||||||
|
|
||||||
let list_of_var_eqs = push_var_eq_functors(
|
let list_of_var_eqs = push_var_eq_functors(
|
||||||
&mut self.heap,
|
&mut self.heap,
|
||||||
var_list.iter().filter_map(|(var_ptr, var, _)| {
|
var_list.iter().map(|(var_name, var, _)| {
|
||||||
if var_ptr.is_anon() {
|
(var.get_value() as usize, var_name.clone())
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let var_loc = var.get_value() as usize;
|
|
||||||
Some((var_loc, var_ptr.clone()))
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
&self.atom_tbl,
|
&self.atom_tbl,
|
||||||
);
|
);
|
||||||
@@ -630,20 +626,14 @@ impl MachineState {
|
|||||||
|
|
||||||
let singleton_var_list = push_var_eq_functors(
|
let singleton_var_list = push_var_eq_functors(
|
||||||
&mut self.heap,
|
&mut self.heap,
|
||||||
term.var_locs
|
term.inverse_var_locs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(var_loc, var_ptrs)| {
|
.filter_map(|(var_loc, var_name)| {
|
||||||
let var_ptr = var_ptrs.front().unwrap();
|
|
||||||
|
|
||||||
if var_ptr.is_anon() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add h to offset the term variable into its heap location.
|
// 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) {
|
if singleton_var_set.get(&r).cloned().unwrap_or(false) {
|
||||||
Some((var_loc, var_ptr.clone()))
|
Some((*var_loc, var_name.clone()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -659,13 +649,12 @@ impl MachineState {
|
|||||||
|
|
||||||
let mut var_list = Vec::with_capacity(singleton_var_set.len());
|
let mut var_list = Vec::with_capacity(singleton_var_set.len());
|
||||||
|
|
||||||
for (var_loc, var_ptrs) in term.var_locs.iter() {
|
for (var_loc, var_name) in term.inverse_var_locs {
|
||||||
let var_ptr = var_ptrs.front().unwrap().clone();
|
|
||||||
let r = Ref::heap_cell(var_loc);
|
let r = Ref::heap_cell(var_loc);
|
||||||
let cell = self.heap[var_loc];
|
let cell = self.heap[var_loc];
|
||||||
|
|
||||||
if let Some(idx) = singleton_var_set.get_index_of(&r) {
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,7 +776,7 @@ impl MachineState {
|
|||||||
|
|
||||||
let printer = match self.try_from_list(self.registers[6], stub_gen) {
|
let printer = match self.try_from_list(self.registers[6], stub_gen) {
|
||||||
Ok(addrs) => {
|
Ok(addrs) => {
|
||||||
let mut var_names: IndexMap<HeapCellValue, VarPtr> = IndexMap::new();
|
let mut var_names: IndexMap<HeapCellValue, Var> = IndexMap::new();
|
||||||
|
|
||||||
for addr in addrs {
|
for addr in addrs {
|
||||||
read_heap_cell!(addr,
|
read_heap_cell!(addr,
|
||||||
@@ -805,18 +794,18 @@ impl MachineState {
|
|||||||
|
|
||||||
read_heap_cell!(atom,
|
read_heap_cell!(atom,
|
||||||
(HeapCellValueTag::Char, c) => {
|
(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)) => {
|
(HeapCellValueTag::Atom, (name, _arity)) => {
|
||||||
debug_assert_eq!(_arity, 0);
|
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) => {
|
(HeapCellValueTag::Str, s) => {
|
||||||
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
let (name, arity) = cell_as_atom_cell!(self.heap[s])
|
||||||
.get_name_and_arity();
|
.get_name_and_arity();
|
||||||
|
|
||||||
debug_assert_eq!(arity, 0);
|
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!();
|
unreachable!();
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ impl MockWAM {
|
|||||||
print_heap_terms(self.machine_st.heap.iter(), term_write_result.heap_loc);
|
print_heap_terms(self.machine_st.heap.iter(), term_write_result.heap_loc);
|
||||||
|
|
||||||
let var_names = term_write_result
|
let var_names = term_write_result
|
||||||
.var_locs
|
.inverse_var_locs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(var_loc, var_ptrs)| {
|
.map(|(var_loc, var_name)| {
|
||||||
(self.machine_st.heap[var_loc], var_ptrs.front().unwrap().clone())
|
(self.machine_st.heap[*var_loc], var_name.clone())
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,10 @@ use crate::machine::machine_indices::*;
|
|||||||
use crate::machine::machine_state::*;
|
use crate::machine::machine_state::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use std::cell::{Ref, RefCell, RefMut};
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::Hash;
|
||||||
use std::io::{Error as IOError, ErrorKind};
|
use std::io::{Error as IOError, ErrorKind};
|
||||||
use std::ops::{Deref, Neg, RangeBounds};
|
use std::ops::Neg;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
@@ -311,26 +309,11 @@ macro_rules! temp_v {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[macro_export]
|
||||||
pub enum GenContext {
|
macro_rules! perm_v {
|
||||||
Head,
|
($x:expr) => {
|
||||||
Mid(usize),
|
$crate::parser::ast::RegType::Perm($x)
|
||||||
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(_))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bitfield]
|
#[bitfield]
|
||||||
@@ -426,7 +409,7 @@ pub fn default_op_dir() -> OpDir {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ArithmeticError {
|
pub enum ArithmeticError {
|
||||||
NonEvaluableFunctor(Literal, usize),
|
NonEvaluableFunctor(HeapCellValue, usize),
|
||||||
UninstantiatedVar,
|
UninstantiatedVar,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,111 +668,7 @@ impl Literal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
pub type Var = Rc<String>;
|
||||||
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(crate) fn subterm_index(heap: &[HeapCellValue], subterm_loc: usize) -> (usize, HeapCellValue) {
|
pub(crate) fn subterm_index(heap: &[HeapCellValue], subterm_loc: usize) -> (usize, HeapCellValue) {
|
||||||
let subterm = heap[subterm_loc];
|
let subterm = heap[subterm_loc];
|
||||||
@@ -1050,7 +929,7 @@ pub fn term_arity(heap: &[HeapCellValue], mut term_loc: usize) -> usize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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> =
|
let mut occurrence_set: IndexMap<HeapCellValue, usize, FxBuildHasher> =
|
||||||
IndexMap::with_hasher(FxBuildHasher::default());
|
IndexMap::with_hasher(FxBuildHasher::default());
|
||||||
|
|
||||||
@@ -1061,21 +940,20 @@ pub fn var_locs_from_iter<I: Iterator<Item = HeapCellValue>>(iter: I) -> VarLocs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VarLocs(
|
let mut inverse_var_locs = InverseVarLocs::default();
|
||||||
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()
|
|
||||||
};
|
|
||||||
|
|
||||||
(key, queue)
|
for (var, count) in occurrence_set {
|
||||||
})
|
let var_loc = var.get_value() as usize;
|
||||||
.collect()
|
|
||||||
)
|
if count > 1 {
|
||||||
|
inverse_var_locs.insert(
|
||||||
|
var_loc,
|
||||||
|
Rc::new(format!("_{}", var_loc)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inverse_var_locs
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1137,82 +1015,14 @@ pub fn term_nth_arg(heap: &[HeapCellValue], mut term_loc: usize, n: usize) -> Op
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type VarNamesToLocs = IndexMap<String, HeapCellValue, FxBuildHasher>;
|
pub type VarLocs = IndexMap<Var, HeapCellValue, FxBuildHasher>;
|
||||||
|
pub type InverseVarLocs = IndexMap<usize, Var, 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FocusedHeap {
|
pub struct FocusedHeap {
|
||||||
pub heap: Vec<HeapCellValue>,
|
pub heap: Vec<HeapCellValue>,
|
||||||
pub focus: usize,
|
pub focus: usize,
|
||||||
pub var_locs: VarLocs,
|
pub inverse_var_locs: InverseVarLocs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FocusedHeap {
|
impl FocusedHeap {
|
||||||
@@ -1220,7 +1030,7 @@ impl FocusedHeap {
|
|||||||
Self {
|
Self {
|
||||||
heap: vec![],
|
heap: vec![],
|
||||||
focus: 0,
|
focus: 0,
|
||||||
var_locs: VarLocs::default(),
|
inverse_var_locs: InverseVarLocs::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1251,7 +1061,6 @@ impl FocusedHeap {
|
|||||||
FocusedHeapRefMut {
|
FocusedHeapRefMut {
|
||||||
heap: &mut self.heap,
|
heap: &mut self.heap,
|
||||||
focus,
|
focus,
|
||||||
// var_locs: &self.var_locs,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ use crate::parser::char_reader::*;
|
|||||||
use crate::parser::lexer::*;
|
use crate::parser::lexer::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
|
|
||||||
use fxhash::FxBuildHasher;
|
|
||||||
use indexmap::IndexMap;
|
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
enum TokenType {
|
enum TokenType {
|
||||||
@@ -184,7 +182,7 @@ pub struct Parser<'a, R> {
|
|||||||
stack: Vec<TokenDesc>,
|
stack: Vec<TokenDesc>,
|
||||||
terms: Vec<HeapCellValue>,
|
terms: Vec<HeapCellValue>,
|
||||||
var_locs: VarLocs,
|
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> {
|
fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserError> {
|
||||||
@@ -326,7 +324,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
stack: vec![],
|
stack: vec![],
|
||||||
terms: vec![],
|
terms: vec![],
|
||||||
var_locs: VarLocs::default(),
|
var_locs: VarLocs::default(),
|
||||||
var_names_to_locs: IndexMap::with_hasher(FxBuildHasher::default()),
|
inverse_var_locs: InverseVarLocs::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +335,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
stack: vec![],
|
stack: vec![],
|
||||||
terms: vec![],
|
terms: vec![],
|
||||||
var_locs: VarLocs::default(),
|
var_locs: VarLocs::default(),
|
||||||
var_names_to_locs: IndexMap::with_hasher(FxBuildHasher::default()),
|
inverse_var_locs: InverseVarLocs::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,32 +499,28 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
self.terms.push(HeapCellValue::from(c));
|
self.terms.push(HeapCellValue::from(c));
|
||||||
TokenType::Term { heap_loc }
|
TokenType::Term { heap_loc }
|
||||||
}
|
}
|
||||||
Token::Var(var_string) => match self.var_names_to_locs.get(&var_string).cloned() {
|
Token::Var(var_string) => {
|
||||||
Some(heap_loc) => {
|
let var = Rc::new(var_string);
|
||||||
let heap_idx = heap_loc.get_value() as usize;
|
|
||||||
|
|
||||||
self.var_locs.push_at_key(heap_idx, VarPtr::from(var_string));
|
match self.var_locs.get(&var).cloned() {
|
||||||
self.terms.push(heap_loc);
|
Some(heap_loc) => {
|
||||||
|
self.terms.push(heap_loc);
|
||||||
TokenType::Term { heap_loc }
|
TokenType::Term { heap_loc }
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.terms.push(heap_loc);
|
|
||||||
|
|
||||||
if var_string.trim() != "_" {
|
|
||||||
self.var_names_to_locs.insert(var_string.clone(), heap_loc);
|
|
||||||
}
|
}
|
||||||
|
None => {
|
||||||
|
self.terms.push(heap_loc);
|
||||||
|
|
||||||
self.var_locs.push_at_key(
|
// if var_string == "_", it not being present
|
||||||
heap_loc.get_value() as usize,
|
// as a key of self.var_locs means it is
|
||||||
if var_string.trim() == "_" {
|
// anonymous.
|
||||||
VarPtr::from(Var::Anon)
|
|
||||||
} else {
|
|
||||||
VarPtr::from(var_string)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
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,
|
Token::Comma => TokenType::Comma,
|
||||||
@@ -755,7 +749,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
|
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.stack.clear();
|
self.stack.clear();
|
||||||
self.var_names_to_locs.clear();
|
self.var_locs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
|
fn expand_comma_compacted_terms(&mut self, index: usize) -> usize {
|
||||||
@@ -1356,7 +1350,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
}) => Ok(FocusedHeap {
|
}) => Ok(FocusedHeap {
|
||||||
heap: mem::replace(&mut self.terms, vec![]),
|
heap: mem::replace(&mut self.terms, vec![]),
|
||||||
focus: heap_loc.get_value() as usize,
|
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(
|
_ => Err(ParserError::IncompleteReduction(
|
||||||
self.lexer.loc_to_err_src(),
|
self.lexer.loc_to_err_src(),
|
||||||
|
|||||||
10
src/read.rs
10
src/read.rs
@@ -52,15 +52,15 @@ impl FocusedHeap {
|
|||||||
let heap_len = machine_st.heap.len();
|
let heap_len = machine_st.heap.len();
|
||||||
machine_st.heap.extend(copy_and_align_iter(self.heap.drain(..), 0, heap_len as i64));
|
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(..) {
|
for (var_loc, var_name) in self.inverse_var_locs.drain(..) {
|
||||||
var_locs.insert(var_loc + heap_len, var_ptrs);
|
inverse_var_locs.insert(var_loc + heap_len, var_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
TermWriteResult {
|
TermWriteResult {
|
||||||
heap_loc: self.focus + heap_len,
|
heap_loc: self.focus + heap_len,
|
||||||
var_locs,
|
inverse_var_locs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,5 +309,5 @@ impl CharRead for ReadlineStream {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TermWriteResult {
|
pub struct TermWriteResult {
|
||||||
pub heap_loc: usize,
|
pub heap_loc: usize,
|
||||||
pub var_locs: VarLocs,
|
pub inverse_var_locs: InverseVarLocs,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ test_queries_on_call_with_inference_limit :-
|
|||||||
error,
|
error,
|
||||||
true),
|
true),
|
||||||
\+ call_with_inference_limit(g(X), 5, R),
|
\+ 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],
|
findall([R,X],
|
||||||
call_with_inference_limit(g(X), 11, R),
|
call_with_inference_limit(g(X), 11, R),
|
||||||
[[true, 1],
|
[[true, 1],
|
||||||
@@ -30,7 +30,7 @@ test_queries_on_call_with_inference_limit :-
|
|||||||
[true, 4],
|
[true, 4],
|
||||||
[!, 5]]),
|
[!, 5]]),
|
||||||
findall([R,X],
|
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, 1],
|
||||||
[true, 2],
|
[true, 2],
|
||||||
[inference_limit_exceeded, _]]),
|
[inference_limit_exceeded, _]]),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
use crate::forms::GenContext;
|
||||||
|
|
||||||
use bit_set::*;
|
use bit_set::*;
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
|
|||||||
Reference in New Issue
Block a user