add register marking for non-callable/inlined predicates.
This commit is contained in:
@@ -17,8 +17,8 @@ pub trait Allocator<'a>
|
||||
|
||||
fn reset(&mut self);
|
||||
fn reset_contents(&mut self) {}
|
||||
|
||||
fn advance(&mut self, GenContext, usize);
|
||||
fn reset_arg(&mut self, usize);
|
||||
|
||||
fn advance_arg(&mut self);
|
||||
|
||||
fn bindings(&self) -> &AllocVarDict<'a>;
|
||||
|
||||
@@ -84,8 +84,8 @@ impl<'a> ArithmeticEvaluator<'a> {
|
||||
ArithmeticEvaluator { bindings, interm: Vec::new(), interm_c: 1 }
|
||||
}
|
||||
|
||||
fn get_un_instr(name: &Atom, a1: ArithmeticTerm, t: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
fn get_unary_instr(name: &Atom, a1: ArithmeticTerm, t: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
match name.as_str() {
|
||||
"-" => Ok(ArithmeticInstruction::Neg(a1, t)),
|
||||
@@ -93,8 +93,8 @@ impl<'a> ArithmeticEvaluator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_bin_instr(name: &Atom, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
fn gen_binary_instr(name: &Atom, a1: ArithmeticTerm, a2: ArithmeticTerm, t: usize)
|
||||
-> Result<ArithmeticInstruction, ArithmeticError>
|
||||
{
|
||||
match name.as_str() {
|
||||
"+" => Ok(ArithmeticInstruction::Add(a1, a2, t)),
|
||||
@@ -129,7 +129,7 @@ impl<'a> ArithmeticEvaluator<'a> {
|
||||
a1.interm_or(0)
|
||||
};
|
||||
|
||||
Self::get_un_instr(name, a1, ninterm)
|
||||
Self::get_unary_instr(name, a1, ninterm)
|
||||
},
|
||||
2 => {
|
||||
let a2 = self.interm.pop().unwrap();
|
||||
@@ -153,7 +153,7 @@ impl<'a> ArithmeticEvaluator<'a> {
|
||||
min_interm
|
||||
};
|
||||
|
||||
Self::gen_bin_instr(name, a1, a2, ninterm)
|
||||
Self::gen_binary_instr(name, a1, a2, ninterm)
|
||||
},
|
||||
_ => Err(ArithmeticError::InvalidOp)
|
||||
}
|
||||
@@ -221,7 +221,7 @@ impl<'a> ArithmeticEvaluator<'a> {
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Ok(code)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use prolog::indexing::*;
|
||||
use prolog::iterators::*;
|
||||
use prolog::targets::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use std::mem::swap;
|
||||
use std::vec::Vec;
|
||||
@@ -79,6 +80,29 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
*self.var_count.get(var).unwrap()
|
||||
}
|
||||
|
||||
fn mark_non_callable(&mut self,
|
||||
name: &'a Atom,
|
||||
arity: usize,
|
||||
term_loc: GenContext,
|
||||
vr: &'a Cell<VarReg>,
|
||||
code: &mut Code)
|
||||
-> RegType
|
||||
{
|
||||
match self.marker.bindings().get(name) {
|
||||
Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
|
||||
Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
|
||||
_ => {
|
||||
let mut target = Vec::new();
|
||||
|
||||
self.marker.reset_arg(arity);
|
||||
self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
|
||||
|
||||
code.push(Line::Query(target));
|
||||
vr.get().norm()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_or_increment_void_instr<Target>(target: &mut Vec<Target>)
|
||||
where Target: CompilationTarget<'a>
|
||||
{
|
||||
@@ -297,23 +321,15 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
code.append(&mut arith_code);
|
||||
|
||||
match terms[0].as_ref() {
|
||||
&Term::Var(ref vr, ref name) =>
|
||||
match self.marker.bindings().get(name) {
|
||||
Some(&VarData::Temp(_, t, _)) if t != 0 =>
|
||||
code.push(is_call!(temp_v!(t))),
|
||||
Some(&VarData::Perm(p)) if p != 0 =>
|
||||
code.push(is_call!(perm_v!(p))),
|
||||
_ => {
|
||||
let mut target = Vec::new();
|
||||
|
||||
// reset self.marker.arg_c to 1.
|
||||
self.marker.advance(term_loc, term.arity());
|
||||
self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
|
||||
|
||||
code.push(Line::Query(target));
|
||||
code.push(is_call!(vr.get().norm()));
|
||||
}
|
||||
},
|
||||
&Term::Var(ref vr, ref name) => {
|
||||
let r = self.mark_non_callable(name,
|
||||
term.arity(),
|
||||
term_loc,
|
||||
vr,
|
||||
code);
|
||||
|
||||
code.push(is_call!(r));
|
||||
},
|
||||
&Term::Constant(_, Constant::Float(fl)) => {
|
||||
code.push(query![put_constant!(Level::Shallow,
|
||||
Constant::Float(fl),
|
||||
@@ -340,23 +356,15 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
&Term::Constant(_, _) => {
|
||||
code.push(succeed!());
|
||||
},
|
||||
&Term::Var(ref vr, ref name) =>
|
||||
match self.marker.bindings().get(name) {
|
||||
Some(&VarData::Temp(_, t, _)) if t != 0 =>
|
||||
code.push(is_atomic!(RegType::Temp(t))),
|
||||
Some(&VarData::Perm(p)) if p != 0 =>
|
||||
code.push(is_atomic!(RegType::Perm(p))),
|
||||
_ => {
|
||||
let mut target = Vec::new();
|
||||
&Term::Var(ref vr, ref name) => {
|
||||
let r = self.mark_non_callable(name,
|
||||
term.arity(),
|
||||
term_loc,
|
||||
vr,
|
||||
code);
|
||||
|
||||
// reset self.marker.arg_c to 1.
|
||||
self.marker.advance(term_loc, term.arity());
|
||||
self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
|
||||
|
||||
code.push(Line::Query(target));
|
||||
code.push(is_atomic!(vr.get().norm()));
|
||||
}
|
||||
},
|
||||
code.push(is_atomic!(r));
|
||||
}
|
||||
},
|
||||
&QueryTerm::IsVar(ref inner_term) =>
|
||||
match inner_term[0].as_ref() {
|
||||
@@ -366,26 +374,18 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
&Term::AnonVar => {
|
||||
code.push(succeed!());
|
||||
},
|
||||
&Term::Var(ref vr, ref name) =>
|
||||
match self.marker.bindings().get(name) {
|
||||
Some(&VarData::Temp(_, t, _)) if t != 0 =>
|
||||
code.push(is_var!(RegType::Temp(t))),
|
||||
Some(&VarData::Perm(p)) if p != 0 =>
|
||||
code.push(is_var!(RegType::Perm(p))),
|
||||
_ => {
|
||||
let mut target = Vec::new();
|
||||
&Term::Var(ref vr, ref name) => {
|
||||
let r = self.mark_non_callable(name,
|
||||
term.arity(),
|
||||
term_loc,
|
||||
vr,
|
||||
code);
|
||||
|
||||
// reset self.marker.arg_c to 1.
|
||||
self.marker.advance(term_loc, term.arity());
|
||||
self.marker.mark_var(name, Level::Shallow, vr, term_loc, &mut target);
|
||||
|
||||
code.push(Line::Query(target));
|
||||
code.push(is_var!(vr.get().norm()));
|
||||
}
|
||||
}
|
||||
code.push(is_var!(r));
|
||||
}
|
||||
},
|
||||
_ if chunk_num == 0 => {
|
||||
self.marker.advance(GenContext::Head, term.arity());
|
||||
self.marker.reset_arg(term.arity());
|
||||
|
||||
let iter = term.post_order_iter();
|
||||
code.push(Line::Query(self.compile_target(iter, term_loc, is_exposed)));
|
||||
@@ -441,7 +441,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
|
||||
let mut code = Vec::new();
|
||||
|
||||
self.marker.advance(GenContext::Head, p0.arity());
|
||||
self.marker.reset_arg(p0.arity());
|
||||
self.compile_seq_prelude(&conjunct_info, &mut code);
|
||||
|
||||
if let &QueryTerm::Term(ref term) = p0 {
|
||||
@@ -509,7 +509,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
vs.populate_restricting_sets();
|
||||
|
||||
self.marker.drain_var_data(vs);
|
||||
self.marker.advance(GenContext::Head, term.arity());
|
||||
self.marker.reset_arg(term.arity());
|
||||
|
||||
let mut code = Vec::new();
|
||||
|
||||
@@ -532,7 +532,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
index: usize,
|
||||
is_exposed: bool)
|
||||
{
|
||||
self.marker.advance(term_loc, term.arity());
|
||||
self.marker.reset_arg(term.arity());
|
||||
|
||||
let iter = term.post_order_iter();
|
||||
let compiled_query = Line::Query(self.compile_target(iter, term_loc, is_exposed));
|
||||
|
||||
@@ -348,7 +348,7 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
|
||||
self.bindings
|
||||
}
|
||||
|
||||
fn advance(&mut self, _: GenContext, arity: usize) {
|
||||
fn reset_arg(&mut self, arity: usize) {
|
||||
self.arg_c = 1;
|
||||
self.temp_lb = arity + 1;
|
||||
}
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
use prolog::allocator::*;
|
||||
use prolog::ast::*;
|
||||
use prolog::fixtures::*;
|
||||
use prolog::targets::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::cmp::max;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct NaiveAllocator<'a> {
|
||||
bindings: AllocVarDict<'a>,
|
||||
arg_c: usize,
|
||||
temp_c: usize,
|
||||
}
|
||||
|
||||
impl<'a> Allocator<'a> for NaiveAllocator<'a>
|
||||
{
|
||||
fn new() -> Self {
|
||||
NaiveAllocator {
|
||||
arg_c: 1,
|
||||
temp_c: 1,
|
||||
bindings: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_anon_var<Target>(&mut self, lvl: Level, target: &mut Vec<Target>)
|
||||
where Target: CompilationTarget<'a>
|
||||
{
|
||||
let r = {
|
||||
let temp = self.temp_c;
|
||||
self.temp_c += 1;
|
||||
RegType::Temp(temp)
|
||||
};
|
||||
|
||||
match lvl {
|
||||
Level::Deep => target.push(Target::subterm_to_variable(r)),
|
||||
Level::Shallow => {
|
||||
let k = self.arg_c;
|
||||
self.arg_c += 1;
|
||||
|
||||
target.push(Target::argument_to_variable(r, k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_non_var<Target>(&mut self,
|
||||
lvl: Level,
|
||||
_: GenContext,
|
||||
cell: &Cell<RegType>,
|
||||
_: &mut Vec<Target>)
|
||||
where Target: CompilationTarget<'a>
|
||||
{
|
||||
let r = cell.get();
|
||||
|
||||
if r.reg_num() == 0 {
|
||||
let r = match lvl {
|
||||
Level::Shallow => {
|
||||
let k = self.arg_c;
|
||||
self.arg_c += 1;
|
||||
|
||||
RegType::Temp(k)
|
||||
},
|
||||
_ => {
|
||||
let temp = self.temp_c;
|
||||
self.temp_c += 1;
|
||||
|
||||
RegType::Temp(temp)
|
||||
}
|
||||
};
|
||||
|
||||
cell.set(r);
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_var<Target>(&mut self,
|
||||
var: &'a Var,
|
||||
lvl: Level,
|
||||
cell: &'a Cell<VarReg>,
|
||||
_: GenContext,
|
||||
target: &mut Vec<Target>)
|
||||
where Target: CompilationTarget<'a>
|
||||
{
|
||||
let (r, is_new_var) = match self.get(var) {
|
||||
RegType::Temp(0) => {
|
||||
let o = self.temp_c;
|
||||
self.temp_c += 1;
|
||||
|
||||
(RegType::Temp(o), true)
|
||||
},
|
||||
RegType::Perm(0) => {
|
||||
let pr = cell.get().norm();
|
||||
self.record_register(var, pr);
|
||||
|
||||
(pr, true)
|
||||
},
|
||||
r => (r, false)
|
||||
};
|
||||
|
||||
match lvl {
|
||||
Level::Shallow => {
|
||||
let k = self.arg_c;
|
||||
self.arg_c += 1;
|
||||
|
||||
cell.set(VarReg::ArgAndNorm(r, k));
|
||||
|
||||
if is_new_var {
|
||||
target.push(Target::argument_to_variable(r, k));
|
||||
} else {
|
||||
target.push(Target::argument_to_value(r, k));
|
||||
}
|
||||
},
|
||||
Level::Deep => {
|
||||
cell.set(VarReg::Norm(r));
|
||||
|
||||
if is_new_var {
|
||||
target.push(Target::subterm_to_variable(r));
|
||||
} else {
|
||||
target.push(Target::subterm_to_value(r));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if !r.is_perm() {
|
||||
self.record_register(var, r);
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.bindings.clear();
|
||||
}
|
||||
|
||||
fn advance(&mut self, term_loc: GenContext, arity: usize) {
|
||||
if let GenContext::Head = term_loc {
|
||||
self.arg_c = 1;
|
||||
self.temp_c = max(arity + 1, self.temp_c);
|
||||
} else {
|
||||
self.arg_c = 1;
|
||||
self.temp_c = arity + 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn advance_arg(&mut self) {
|
||||
self.arg_c += 1;
|
||||
}
|
||||
|
||||
fn bindings(&self) -> &AllocVarDict<'a> {
|
||||
&self.bindings
|
||||
}
|
||||
|
||||
fn bindings_mut(&mut self) -> &mut AllocVarDict<'a> {
|
||||
&mut self.bindings
|
||||
}
|
||||
|
||||
fn take_bindings(self) -> AllocVarDict<'a> {
|
||||
self.bindings
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user