mark variables in ArithmeticEvaluator (#690)
This commit is contained in:
@@ -5,48 +5,52 @@ use crate::fixtures::*;
|
|||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
use crate::instructions::*;
|
use crate::instructions::*;
|
||||||
use crate::machine::machine_indices::*;
|
use crate::machine::machine_indices::*;
|
||||||
|
use crate::targets::*;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub(crate) trait Allocator<'a> {
|
pub(crate) trait Allocator {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
|
|
||||||
fn mark_anon_var<Target>(&mut self, _: Level, _: GenContext, _: &mut Code)
|
fn mark_anon_var<'a, Target: CompilationTarget<'a>>(
|
||||||
where
|
|
||||||
Target: crate::targets::CompilationTarget<'a>;
|
|
||||||
fn mark_non_var<Target>(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
_: Level,
|
lvl: Level,
|
||||||
_: GenContext,
|
context: GenContext,
|
||||||
_: &'a Cell<RegType>,
|
code: &mut Code,
|
||||||
_: &mut Code,
|
);
|
||||||
) where
|
|
||||||
Target: crate::targets::CompilationTarget<'a>;
|
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
|
||||||
fn mark_reserved_var<Target>(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
_: Rc<String>,
|
lvl: Level,
|
||||||
_: Level,
|
context: GenContext,
|
||||||
_: &'a Cell<VarReg>,
|
cell: &'a Cell<RegType>,
|
||||||
_: GenContext,
|
code: &mut Code,
|
||||||
_: &mut Code,
|
);
|
||||||
_: RegType,
|
|
||||||
_: bool,
|
fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
|
||||||
) where
|
|
||||||
Target: crate::targets::CompilationTarget<'a>;
|
|
||||||
fn mark_var<Target>(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
_: Rc<String>,
|
var_name: Rc<String>,
|
||||||
_: Level,
|
lvl: Level,
|
||||||
_: &'a Cell<VarReg>,
|
cell: &'a Cell<VarReg>,
|
||||||
_: GenContext,
|
term_loc: GenContext,
|
||||||
_: &mut Code,
|
code: &mut Code,
|
||||||
) where
|
r: RegType,
|
||||||
Target: crate::targets::CompilationTarget<'a>;
|
is_new_var: bool,
|
||||||
|
);
|
||||||
|
|
||||||
|
fn mark_var<'a, Target: CompilationTarget<'a>>(
|
||||||
|
&mut self,
|
||||||
|
var_name: Rc<String>,
|
||||||
|
lvl: Level,
|
||||||
|
cell: &'a Cell<VarReg>,
|
||||||
|
context: GenContext,
|
||||||
|
code: &mut Code,
|
||||||
|
);
|
||||||
|
|
||||||
fn reset(&mut self);
|
fn reset(&mut self);
|
||||||
fn reset_contents(&mut self) {}
|
fn reset_contents(&mut self) {}
|
||||||
fn reset_arg(&mut self, _: usize);
|
fn reset_arg(&mut self, arg_num: usize);
|
||||||
fn reset_at_head(&mut self, args: &Vec<Term>);
|
fn reset_at_head(&mut self, args: &Vec<Term>);
|
||||||
|
|
||||||
fn advance_arg(&mut self);
|
fn advance_arg(&mut self);
|
||||||
@@ -56,7 +60,7 @@ pub(crate) trait Allocator<'a> {
|
|||||||
|
|
||||||
fn take_bindings(self) -> AllocVarDict;
|
fn take_bindings(self) -> AllocVarDict;
|
||||||
|
|
||||||
fn drain_var_data(
|
fn drain_var_data<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
vs: VariableFixtures<'a>,
|
vs: VariableFixtures<'a>,
|
||||||
num_of_chunks: usize,
|
num_of_chunks: usize,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::allocator::*;
|
||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::fixtures::*;
|
use crate::fixtures::*;
|
||||||
@@ -96,7 +97,7 @@ impl<'a> ArithInstructionIterator<'a> {
|
|||||||
pub(crate) enum ArithTermRef<'a> {
|
pub(crate) enum ArithTermRef<'a> {
|
||||||
Literal(&'a Literal),
|
Literal(&'a Literal),
|
||||||
Op(Atom, usize), // name, arity.
|
Op(Atom, usize), // name, arity.
|
||||||
Var(&'a Cell<VarReg>, Rc<String>),
|
Var(Level, &'a Cell<VarReg>, Rc<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for ArithInstructionIterator<'a> {
|
impl<'a> Iterator for ArithInstructionIterator<'a> {
|
||||||
@@ -124,8 +125,11 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
|
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
|
||||||
TermIterState::Var(_, cell, var) => {
|
TermIterState::Var(lvl, cell, var) => {
|
||||||
return Some(Ok(ArithTermRef::Var(cell, var.clone())));
|
// the expression is the second argument of an
|
||||||
|
// is/2 but the iterator can't see that, so the
|
||||||
|
// level needs to be demoted manually.
|
||||||
|
return Some(Ok(ArithTermRef::Var(lvl.child_level(), cell, var.clone())));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Some(Err(ArithmeticError::NonEvaluableFunctor(
|
return Some(Err(ArithmeticError::NonEvaluableFunctor(
|
||||||
@@ -141,8 +145,8 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct ArithmeticEvaluator<'a> {
|
pub(crate) struct ArithmeticEvaluator<'a, TermMarker> {
|
||||||
bindings: &'a AllocVarDict,
|
marker: &'a mut TermMarker,
|
||||||
interm: Vec<ArithmeticTerm>,
|
interm: Vec<ArithmeticTerm>,
|
||||||
interm_c: usize,
|
interm_c: usize,
|
||||||
}
|
}
|
||||||
@@ -182,10 +186,10 @@ fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: &Literal) -> Result<(), Ari
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ArithmeticEvaluator<'a> {
|
impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> {
|
||||||
pub(crate) fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self {
|
pub(crate) fn new(marker: &'a mut TermMarker, target_int: usize) -> Self {
|
||||||
ArithmeticEvaluator {
|
ArithmeticEvaluator {
|
||||||
bindings,
|
marker,
|
||||||
interm: Vec::new(),
|
interm: Vec::new(),
|
||||||
interm_c: target_int,
|
interm_c: target_int,
|
||||||
}
|
}
|
||||||
@@ -311,20 +315,46 @@ impl<'a> ArithmeticEvaluator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn eval(&mut self, src: &'a Term) -> Result<ArithCont, ArithmeticError> {
|
pub(crate) fn eval(
|
||||||
|
&mut self,
|
||||||
|
src: &'a Term,
|
||||||
|
term_loc: GenContext,
|
||||||
|
) -> Result<ArithCont, ArithmeticError>
|
||||||
|
{
|
||||||
let mut code = vec![];
|
let mut code = vec![];
|
||||||
let mut iter = src.iter()?;
|
let mut iter = src.iter()?;
|
||||||
|
|
||||||
while let Some(term_ref) = iter.next() {
|
while let Some(term_ref) = iter.next() {
|
||||||
match term_ref? {
|
match term_ref? {
|
||||||
ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?,
|
ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?,
|
||||||
ArithTermRef::Var(cell, name) => {
|
ArithTermRef::Var(lvl, cell, name) => {
|
||||||
let r = if cell.get().norm().reg_num() == 0 {
|
let r = if cell.get().norm().reg_num() == 0 {
|
||||||
match self.bindings.get(&name) {
|
let mut getter = || {
|
||||||
Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
|
use crate::targets::QueryInstruction;
|
||||||
Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
|
|
||||||
_ => return Err(ArithmeticError::UninstantiatedVar),
|
loop {
|
||||||
|
match self.marker.bindings().get(&name) {
|
||||||
|
Some(&VarData::Temp(_, t, _)) if t != 0 =>
|
||||||
|
return RegType::Temp(t),
|
||||||
|
Some(&VarData::Perm(p)) if p != 0 =>
|
||||||
|
return RegType::Perm(p),
|
||||||
|
_ => {
|
||||||
|
self.marker.mark_var::<QueryInstruction>(
|
||||||
|
name.clone(),
|
||||||
|
lvl,
|
||||||
|
cell,
|
||||||
|
term_loc,
|
||||||
|
&mut code,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getter()
|
||||||
|
/*
|
||||||
|
_ => return Err(ArithmeticError::UninstantiatedVar),
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
cell.get().norm()
|
cell.get().norm()
|
||||||
};
|
};
|
||||||
|
|||||||
119
src/codegen.rs
119
src/codegen.rs
@@ -208,7 +208,7 @@ pub(crate) struct CodeGenerator<'a, TermMarker> {
|
|||||||
global_jmp_by_locs_offset: usize,
|
global_jmp_by_locs_offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> {
|
||||||
pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self {
|
pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self {
|
||||||
CodeGenerator {
|
CodeGenerator {
|
||||||
atom_tbl,
|
atom_tbl,
|
||||||
@@ -221,7 +221,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_var_count<Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
|
fn update_var_count<'a, Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
|
||||||
for term in iter {
|
for term in iter {
|
||||||
if let TermRef::Var(_, _, var) = term {
|
if let TermRef::Var(_, _, var) = term {
|
||||||
let entry = self.var_count.entry(var).or_insert(0);
|
let entry = self.var_count.entry(var).or_insert(0);
|
||||||
@@ -230,7 +230,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_var_count(&self, var: &'a String) -> usize {
|
fn get_var_count(&self, var: &String) -> usize {
|
||||||
*self.var_count.get(var).unwrap()
|
*self.var_count.get(var).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
name: Rc<String>,
|
name: Rc<String>,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
vr: &'a Cell<VarReg>,
|
vr: &Cell<VarReg>,
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
) -> RegType {
|
) -> RegType {
|
||||||
let mut target = Code::new();
|
let mut target = Code::new();
|
||||||
@@ -256,7 +256,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
name: Rc<String>,
|
name: Rc<String>,
|
||||||
arg: usize,
|
arg: usize,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
vr: &'a Cell<VarReg>,
|
vr: &Cell<VarReg>,
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
) -> RegType {
|
) -> RegType {
|
||||||
match self.marker.bindings().get(&name) {
|
match self.marker.bindings().get(&name) {
|
||||||
@@ -273,7 +273,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_or_increment_void_instr<Target>(target: &mut Code)
|
fn add_or_increment_void_instr<'a, Target>(target: &mut Code)
|
||||||
where
|
where
|
||||||
Target: crate::targets::CompilationTarget<'a>,
|
Target: crate::targets::CompilationTarget<'a>,
|
||||||
{
|
{
|
||||||
@@ -287,10 +287,10 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
target.push(Target::to_void(1));
|
target.push(Target::to_void(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deep_var_instr<Target: crate::targets::CompilationTarget<'a>>(
|
fn deep_var_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cell: &'a Cell<VarReg>,
|
cell: &'a Cell<VarReg>,
|
||||||
var: &'a Rc<String>,
|
var: &Rc<String>,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
is_exposed: bool,
|
is_exposed: bool,
|
||||||
target: &mut Code,
|
target: &mut Code,
|
||||||
@@ -302,7 +302,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subterm_to_instr<Target: crate::targets::CompilationTarget<'a>>(
|
fn subterm_to_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
subterm: &'a Term,
|
subterm: &'a Term,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
@@ -331,7 +331,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_target<Target, Iter>(
|
fn compile_target<'a, Target, Iter>(
|
||||||
&mut self,
|
&mut self,
|
||||||
iter: Iter,
|
iter: Iter,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
@@ -413,7 +413,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
target
|
target
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_var_data(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> {
|
fn collect_var_data<'a>(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> {
|
||||||
let mut vs = VariableFixtures::new();
|
let mut vs = VariableFixtures::new();
|
||||||
|
|
||||||
while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
|
while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
|
||||||
@@ -490,7 +490,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
dealloc_index
|
dealloc_index
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_inlined(
|
fn compile_inlined<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
ct: &InlinedClauseType,
|
ct: &InlinedClauseType,
|
||||||
terms: &'a Vec<Term>,
|
terms: &'a Vec<Term>,
|
||||||
@@ -501,8 +501,8 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
&InlinedClauseType::CompareNumber(mut cmp) => {
|
&InlinedClauseType::CompareNumber(mut cmp) => {
|
||||||
self.marker.reset_arg(2);
|
self.marker.reset_arg(2);
|
||||||
|
|
||||||
let (mut lcode, at_1) = self.call_arith_eval(&terms[0], 1)?;
|
let (mut lcode, at_1) = self.compile_arith_expr(&terms[0], 1, term_loc)?;
|
||||||
let (mut rcode, at_2) = self.call_arith_eval(&terms[1], 2)?;
|
let (mut rcode, at_2) = self.compile_arith_expr(&terms[1], 2, term_loc)?;
|
||||||
|
|
||||||
let at_1 = if let &Term::Var(ref vr, ref name) = &terms[0] {
|
let at_1 = if let &Term::Var(ref vr, ref name) = &terms[0] {
|
||||||
ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 1, term_loc, vr, code))
|
ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 1, term_loc, vr, code))
|
||||||
@@ -655,74 +655,63 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_arith_eval(
|
fn compile_arith_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
term: &'a Term,
|
term: &Term,
|
||||||
target_int: usize,
|
target_int: usize,
|
||||||
|
term_loc: GenContext,
|
||||||
) -> Result<ArithCont, ArithmeticError> {
|
) -> Result<ArithCont, ArithmeticError> {
|
||||||
let mut evaluator = ArithmeticEvaluator::new(&self.marker.bindings(), target_int);
|
let mut evaluator = ArithmeticEvaluator::new(&mut self.marker, target_int);
|
||||||
evaluator.eval(term)
|
evaluator.eval(term, term_loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_is_call(
|
fn compile_is_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
terms: &'a Vec<Term>,
|
terms: &Vec<Term>,
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
use_default_call_policy: bool,
|
use_default_call_policy: bool,
|
||||||
) -> Result<(), CompilationError> {
|
) -> Result<(), CompilationError> {
|
||||||
let (mut acode, at) = self.call_arith_eval(&terms[1], 1)?;
|
macro_rules! compile_expr {
|
||||||
code.append(&mut acode);
|
($self:expr, $terms:expr, $term_loc:expr, $code:expr) => ({
|
||||||
|
let (acode, at) = $self.compile_arith_expr(&$terms[1], 1, $term_loc)?;
|
||||||
|
$code.extend(acode.into_iter());
|
||||||
|
at
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
self.marker.reset_arg(2);
|
self.marker.reset_arg(2);
|
||||||
|
|
||||||
match &terms[0] {
|
let at = match &terms[0] {
|
||||||
&Term::Var(ref vr, ref name) => {
|
&Term::Var(ref vr, ref name) => {
|
||||||
let mut target = vec![];
|
|
||||||
|
|
||||||
self.marker.mark_var::<QueryInstruction>(
|
self.marker.mark_var::<QueryInstruction>(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
Level::Shallow,
|
Level::Shallow,
|
||||||
vr,
|
vr,
|
||||||
term_loc,
|
term_loc,
|
||||||
&mut target,
|
code,
|
||||||
);
|
);
|
||||||
|
|
||||||
if !target.is_empty() {
|
compile_expr!(self, terms, term_loc, code)
|
||||||
code.extend(target.into_iter());
|
|
||||||
}
|
}
|
||||||
}
|
&Term::Literal(_, c @ Literal::Integer(_) |
|
||||||
&Term::Literal(_, c @ Literal::Integer(_))
|
c @ Literal::Float(_) |
|
||||||
| &Term::Literal(_, c @ Literal::Fixnum(_)) => {
|
c @ Literal::Rational(_) |
|
||||||
let v = HeapCellValue::from(c);
|
c @ Literal::Fixnum(_)) => {
|
||||||
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
|
|
||||||
|
|
||||||
self.marker.advance_arg();
|
|
||||||
}
|
|
||||||
&Term::Literal(_, c @ Literal::Float(_)) => {
|
|
||||||
let v = HeapCellValue::from(c);
|
|
||||||
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
|
|
||||||
|
|
||||||
self.marker.advance_arg();
|
|
||||||
}
|
|
||||||
&Term::Literal(_, c @ Literal::Rational(_)) => {
|
|
||||||
let v = HeapCellValue::from(c);
|
let v = HeapCellValue::from(c);
|
||||||
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
|
code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
|
||||||
|
|
||||||
self.marker.advance_arg();
|
self.marker.advance_arg();
|
||||||
|
compile_expr!(self, terms, term_loc, code)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
code.push(instr!("$fail", 0));
|
code.push(instr!("$fail", 0));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let at = if let &Term::Var(ref vr, ref name) = &terms[1] {
|
|
||||||
ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 2, term_loc, vr, code))
|
|
||||||
} else {
|
|
||||||
at.unwrap_or(interm!(1))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let at = at.unwrap_or(interm!(1));
|
||||||
|
|
||||||
Ok(if use_default_call_policy {
|
Ok(if use_default_call_policy {
|
||||||
code.push(instr!("is", default, temp_v!(1), at, 0));
|
code.push(instr!("is", default, temp_v!(1), at, 0));
|
||||||
} else {
|
} else {
|
||||||
@@ -731,7 +720,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) {
|
fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &Cell<VarReg>) {
|
||||||
let r = self.marker.get(Rc::new(String::from("!")));
|
let r = self.marker.get(Rc::new(String::from("!")));
|
||||||
cell.set(VarReg::Norm(r));
|
cell.set(VarReg::Norm(r));
|
||||||
code.push(instr!("$set_cp", cell.get().norm(), 0));
|
code.push(instr!("$set_cp", cell.get().norm(), 0));
|
||||||
@@ -740,7 +729,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
fn compile_get_level_and_unify(
|
fn compile_get_level_and_unify(
|
||||||
&mut self,
|
&mut self,
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
cell: &'a Cell<VarReg>,
|
cell: &Cell<VarReg>,
|
||||||
var: Rc<String>,
|
var: Rc<String>,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
) {
|
) {
|
||||||
@@ -756,7 +745,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
code.push(instr!("get_level_and_unify", cell.get().norm()));
|
code.push(instr!("get_level_and_unify", cell.get().norm()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_seq(
|
fn compile_seq<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
iter: ChunkedIterator<'a>,
|
iter: ChunkedIterator<'a>,
|
||||||
conjunct_info: &ConjunctInfo<'a>,
|
conjunct_info: &ConjunctInfo<'a>,
|
||||||
@@ -820,10 +809,10 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_cleanup(
|
fn compile_cleanup<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
conjunct_info: &ConjunctInfo,
|
conjunct_info: &ConjunctInfo<'a>,
|
||||||
toc: &'a QueryTerm,
|
toc: &'a QueryTerm,
|
||||||
) {
|
) {
|
||||||
// add a proceed to bookend any trailing cuts.
|
// add a proceed to bookend any trailing cuts.
|
||||||
@@ -850,10 +839,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile_rule<'c: 'a>(
|
pub(crate) fn compile_rule(&mut self, rule: &Rule) -> Result<Code, CompilationError> {
|
||||||
&mut self,
|
|
||||||
rule: &'c Rule,
|
|
||||||
) -> Result<Code, CompilationError> {
|
|
||||||
let iter = ChunkedIterator::from_rule(rule);
|
let iter = ChunkedIterator::from_rule(rule);
|
||||||
let conjunct_info = self.collect_var_data(iter);
|
let conjunct_info = self.collect_var_data(iter);
|
||||||
|
|
||||||
@@ -907,7 +893,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
UnsafeVarMarker::from_safe_vars(safe_vars)
|
UnsafeVarMarker::from_safe_vars(safe_vars)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile_fact<'c: 'a>(&mut self, term: &'c Term) -> Code {
|
pub(crate) fn compile_fact(&mut self, term: &Term) -> Code {
|
||||||
self.update_var_count(post_order_iter(term));
|
self.update_var_count(post_order_iter(term));
|
||||||
|
|
||||||
let mut vs = VariableFixtures::new();
|
let mut vs = VariableFixtures::new();
|
||||||
@@ -942,7 +928,7 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
|
|
||||||
fn compile_query_line(
|
fn compile_query_line(
|
||||||
&mut self,
|
&mut self,
|
||||||
term: &'a QueryTerm,
|
term: &QueryTerm,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
code: &mut Code,
|
code: &mut Code,
|
||||||
num_perm_vars_left: usize,
|
num_perm_vars_left: usize,
|
||||||
@@ -1029,9 +1015,9 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
subseqs
|
subseqs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_pred_subseq<'c: 'a, I: Indexer>(
|
fn compile_pred_subseq<I: Indexer>(
|
||||||
&mut self,
|
&mut self,
|
||||||
clauses: &'c [PredicateClause],
|
clauses: &[PredicateClause],
|
||||||
optimal_index: usize,
|
optimal_index: usize,
|
||||||
) -> Result<Code, CompilationError> {
|
) -> Result<Code, CompilationError> {
|
||||||
let mut code = VecDeque::new();
|
let mut code = VecDeque::new();
|
||||||
@@ -1121,19 +1107,12 @@ impl<'a, 'b: 'a, TermMarker: Allocator<'a>> CodeGenerator<'b, TermMarker> {
|
|||||||
Ok(Vec::from(code))
|
Ok(Vec::from(code))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile_predicate<'c: 'a>(
|
pub(crate) fn compile_predicate(
|
||||||
&mut self,
|
&mut self,
|
||||||
clauses: &'c Vec<PredicateClause>,
|
clauses: &Vec<PredicateClause>,
|
||||||
) -> Result<Code, CompilationError> {
|
) -> Result<Code, CompilationError> {
|
||||||
let mut code = Code::new();
|
let mut code = Code::new();
|
||||||
|
|
||||||
/*
|
|
||||||
let optimal_index = match Self::first_instantiated_index(&clauses) {
|
|
||||||
Some(index) => index,
|
|
||||||
None => 0, // Default to first argument indexing.
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
let split_pred = Self::split_predicate(&clauses);
|
let split_pred = Self::split_predicate(&clauses);
|
||||||
let multi_seq = split_pred.len() > 1;
|
let multi_seq = split_pred.len() > 1;
|
||||||
|
|
||||||
|
|||||||
@@ -126,10 +126,11 @@ impl DebrayAllocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn evacuate_arg<'a, Target>(&mut self, chunk_num: usize, target: &mut Vec<Instruction>)
|
fn evacuate_arg<'a, Target: CompilationTarget<'a>>(
|
||||||
where
|
&mut self,
|
||||||
Target: CompilationTarget<'a>,
|
chunk_num: usize,
|
||||||
{
|
code: &mut Code,
|
||||||
|
) {
|
||||||
match self.alloc_in_last_goal_hint(chunk_num) {
|
match self.alloc_in_last_goal_hint(chunk_num) {
|
||||||
Some((var, r)) => {
|
Some((var, r)) => {
|
||||||
let k = self.arg_c;
|
let k = self.arg_c;
|
||||||
@@ -137,7 +138,7 @@ impl DebrayAllocator {
|
|||||||
if r != k {
|
if r != k {
|
||||||
let r = RegType::Temp(r);
|
let r = RegType::Temp(r);
|
||||||
|
|
||||||
target.push(Target::move_to_register(r, k));
|
code.push(Target::move_to_register(r, k));
|
||||||
|
|
||||||
self.contents.swap_remove(&k);
|
self.contents.swap_remove(&k);
|
||||||
self.contents.insert(r.reg_num(), var.clone());
|
self.contents.insert(r.reg_num(), var.clone());
|
||||||
@@ -207,7 +208,7 @@ impl DebrayAllocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Allocator<'a> for DebrayAllocator {
|
impl Allocator for DebrayAllocator {
|
||||||
fn new() -> DebrayAllocator {
|
fn new() -> DebrayAllocator {
|
||||||
DebrayAllocator {
|
DebrayAllocator {
|
||||||
arity: 0,
|
arity: 0,
|
||||||
@@ -219,42 +220,37 @@ impl<'a> Allocator<'a> for DebrayAllocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_anon_var<Target>(
|
fn mark_anon_var<'a, Target: CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
lvl: Level,
|
lvl: Level,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
target: &mut Vec<Instruction>,
|
code: &mut Code,
|
||||||
)
|
) {
|
||||||
where
|
|
||||||
Target: CompilationTarget<'a>,
|
|
||||||
{
|
|
||||||
let r = RegType::Temp(self.alloc_reg_to_non_var());
|
let r = RegType::Temp(self.alloc_reg_to_non_var());
|
||||||
|
|
||||||
match lvl {
|
match lvl {
|
||||||
Level::Deep => target.push(Target::subterm_to_variable(r)),
|
Level::Deep => code.push(Target::subterm_to_variable(r)),
|
||||||
Level::Root | Level::Shallow => {
|
Level::Root | Level::Shallow => {
|
||||||
let k = self.arg_c;
|
let k = self.arg_c;
|
||||||
|
|
||||||
if let GenContext::Last(chunk_num) = term_loc {
|
if let GenContext::Last(chunk_num) = term_loc {
|
||||||
self.evacuate_arg::<Target>(chunk_num, target);
|
self.evacuate_arg::<Target>(chunk_num, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.arg_c += 1;
|
self.arg_c += 1;
|
||||||
|
|
||||||
target.push(Target::argument_to_variable(r, k));
|
code.push(Target::argument_to_variable(r, k));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_non_var<Target>(
|
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
lvl: Level,
|
lvl: Level,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
cell: &Cell<RegType>,
|
cell: &'a Cell<RegType>,
|
||||||
target: &mut Vec<Instruction>,
|
code: &mut Code,
|
||||||
) where
|
) {
|
||||||
Target: CompilationTarget<'a>,
|
|
||||||
{
|
|
||||||
let r = cell.get();
|
let r = cell.get();
|
||||||
|
|
||||||
let r = match lvl {
|
let r = match lvl {
|
||||||
@@ -262,7 +258,7 @@ impl<'a> Allocator<'a> for DebrayAllocator {
|
|||||||
let k = self.arg_c;
|
let k = self.arg_c;
|
||||||
|
|
||||||
if let GenContext::Last(chunk_num) = term_loc {
|
if let GenContext::Last(chunk_num) = term_loc {
|
||||||
self.evacuate_arg::<Target>(chunk_num, target);
|
self.evacuate_arg::<Target>(chunk_num, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.arg_c += 1;
|
self.arg_c += 1;
|
||||||
@@ -278,18 +274,18 @@ impl<'a> Allocator<'a> for DebrayAllocator {
|
|||||||
cell.set(r);
|
cell.set(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_var<Target: CompilationTarget<'a>>(
|
fn mark_var<'a, Target: CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
var: Rc<String>,
|
var: Rc<String>,
|
||||||
lvl: Level,
|
lvl: Level,
|
||||||
cell: &'a Cell<VarReg>,
|
cell: &'a Cell<VarReg>,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
target: &mut Vec<Instruction>,
|
code: &mut Code,
|
||||||
) {
|
) {
|
||||||
let (r, is_new_var) = match self.get(var.clone()) {
|
let (r, is_new_var) = match self.get(var.clone()) {
|
||||||
RegType::Temp(0) => {
|
RegType::Temp(0) => {
|
||||||
// here, r is temporary *and* unassigned.
|
// here, r is temporary *and* unassigned.
|
||||||
let o = self.alloc_reg_to_var::<Target>(&var, lvl, term_loc, target);
|
let o = self.alloc_reg_to_var::<Target>(&var, lvl, term_loc, code);
|
||||||
cell.set(VarReg::Norm(RegType::Temp(o)));
|
cell.set(VarReg::Norm(RegType::Temp(o)));
|
||||||
|
|
||||||
(RegType::Temp(o), true)
|
(RegType::Temp(o), true)
|
||||||
@@ -303,16 +299,16 @@ impl<'a> Allocator<'a> for DebrayAllocator {
|
|||||||
r => (r, false),
|
r => (r, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.mark_reserved_var::<Target>(var, lvl, cell, term_loc, target, r, is_new_var);
|
self.mark_reserved_var::<Target>(var, lvl, cell, term_loc, code, r, is_new_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_reserved_var<Target: CompilationTarget<'a>>(
|
fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
var: Rc<String>,
|
var: Rc<String>,
|
||||||
lvl: Level,
|
lvl: Level,
|
||||||
cell: &'a Cell<VarReg>,
|
cell: &'a Cell<VarReg>,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
target: &mut Vec<Instruction>,
|
code: &mut Code,
|
||||||
r: RegType,
|
r: RegType,
|
||||||
is_new_var: bool,
|
is_new_var: bool,
|
||||||
) {
|
) {
|
||||||
@@ -321,7 +317,7 @@ impl<'a> Allocator<'a> for DebrayAllocator {
|
|||||||
let k = self.arg_c;
|
let k = self.arg_c;
|
||||||
|
|
||||||
if self.is_curr_arg_distinct_from(&var) {
|
if self.is_curr_arg_distinct_from(&var) {
|
||||||
self.evacuate_arg::<Target>(term_loc.chunk_num(), target);
|
self.evacuate_arg::<Target>(term_loc.chunk_num(), code);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.arg_c += 1;
|
self.arg_c += 1;
|
||||||
@@ -330,24 +326,24 @@ impl<'a> Allocator<'a> for DebrayAllocator {
|
|||||||
|
|
||||||
if !self.in_place(&var, term_loc, r, k) {
|
if !self.in_place(&var, term_loc, r, k) {
|
||||||
if is_new_var {
|
if is_new_var {
|
||||||
target.push(Target::argument_to_variable(r, k));
|
code.push(Target::argument_to_variable(r, k));
|
||||||
} else {
|
} else {
|
||||||
target.push(Target::argument_to_value(r, k));
|
code.push(Target::argument_to_value(r, k));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Level::Deep if is_new_var => {
|
Level::Deep if is_new_var => {
|
||||||
if let GenContext::Head = term_loc {
|
if let GenContext::Head = term_loc {
|
||||||
if self.occurs_shallowly_in_head(&var, r.reg_num()) {
|
if self.occurs_shallowly_in_head(&var, r.reg_num()) {
|
||||||
target.push(Target::subterm_to_value(r));
|
code.push(Target::subterm_to_value(r));
|
||||||
} else {
|
} else {
|
||||||
target.push(Target::subterm_to_variable(r));
|
code.push(Target::subterm_to_variable(r));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target.push(Target::subterm_to_variable(r));
|
code.push(Target::subterm_to_variable(r));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Level::Deep => target.push(Target::subterm_to_value(r)),
|
Level::Deep => code.push(Target::subterm_to_value(r)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !r.is_perm() {
|
if !r.is_perm() {
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ staggered_sc(G, _) :- call('$call'(G)).
|
|||||||
staggered_sc(_, G) :- call('$call'(G)).
|
staggered_sc(_, G) :- call('$call'(G)).
|
||||||
|
|
||||||
|
|
||||||
! :- !.
|
!.
|
||||||
|
|
||||||
:- non_counted_backtracking set_cp/1.
|
:- non_counted_backtracking set_cp/1.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user