fix void instrs
This commit is contained in:
@@ -90,11 +90,7 @@ impl VarReg {
|
|||||||
match self {
|
match self {
|
||||||
VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg
|
VarReg::ArgAndNorm(reg, _) | VarReg::Norm(reg) => reg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_temp(self) -> bool {
|
|
||||||
!self.norm().is_perm()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for VarReg {
|
impl Default for VarReg {
|
||||||
|
|||||||
@@ -27,43 +27,17 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
fn update_var_count<Iter>(&mut self, iter: Iter)
|
fn update_var_count<Iter>(&mut self, iter: Iter)
|
||||||
where Iter : Iterator<Item=TermRef<'a>>
|
where Iter : Iterator<Item=TermRef<'a>>
|
||||||
{
|
{
|
||||||
let mut var_count = HashMap::new();
|
|
||||||
|
|
||||||
for term in iter {
|
for term in iter {
|
||||||
if let TermRef::Var(_, _, var) = term {
|
if let TermRef::Var(_, _, var) = term {
|
||||||
if self.marker.contains_var(var) {
|
|
||||||
var_count.insert(var, 2);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let entry = var_count.entry(var).or_insert(0);
|
let entry = self.var_count.entry(var).or_insert(0);
|
||||||
*entry += 1;
|
*entry += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.var_count = var_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_singleton_vars(&self, terms: &Vec<Box<Term>>) -> bool
|
fn get_var_count(&self, var: &'a Var) -> usize {
|
||||||
{
|
*self.var_count.get(var).unwrap()
|
||||||
for term in terms {
|
|
||||||
match term.as_ref() {
|
|
||||||
&Term::AnonVar => {},
|
|
||||||
&Term::Var(ref cell, ref var) if cell.get().is_temp() =>
|
|
||||||
if self.var_count.get(var).unwrap() != &1 {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
_ => return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void_subterms<Target>(subterms: usize) -> Target
|
|
||||||
where Target: CompilationTarget<'a>
|
|
||||||
{
|
|
||||||
Target::to_void(subterms)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_structure<Target>(&mut self,
|
fn to_structure<Target>(&mut self,
|
||||||
@@ -83,7 +57,7 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
fn to_constant<Target>(&mut self,
|
fn to_constant<Target>(&mut self,
|
||||||
lvl: Level,
|
lvl: Level,
|
||||||
cell: &'a Cell<RegType>,
|
cell: &'a Cell<RegType>,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
constant: &'a Constant,
|
constant: &'a Constant,
|
||||||
target: &mut Vec<Target>)
|
target: &mut Vec<Target>)
|
||||||
-> Target
|
-> Target
|
||||||
@@ -123,15 +97,44 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
Target::clause_arg_to_instr(cell.get())
|
Target::clause_arg_to_instr(cell.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flatten_void_instrs<Target>(target: Vec<Target>) -> Vec<Target>
|
||||||
|
where Target: CompilationTarget<'a>
|
||||||
|
{
|
||||||
|
let mut compressed_target = Vec::new();
|
||||||
|
let mut void_count = 0;
|
||||||
|
|
||||||
|
for term in target.into_iter() {
|
||||||
|
if Target::is_void_instr(&term) {
|
||||||
|
void_count += 1;
|
||||||
|
} else {
|
||||||
|
if void_count > 0 {
|
||||||
|
compressed_target.push(Target::to_void(void_count));
|
||||||
|
void_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
compressed_target.push(term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if void_count > 0 {
|
||||||
|
compressed_target.push(Target::to_void(void_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
compressed_target
|
||||||
|
}
|
||||||
|
|
||||||
fn subterm_to_instr<Target>(&mut self,
|
fn subterm_to_instr<Target>(&mut self,
|
||||||
subterm: &'a Term,
|
subterm: &'a Term,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
|
is_exposed: bool,
|
||||||
target: &mut Vec<Target>)
|
target: &mut Vec<Target>)
|
||||||
where Target: CompilationTarget<'a>
|
where Target: CompilationTarget<'a>
|
||||||
{
|
{
|
||||||
match subterm {
|
match subterm {
|
||||||
&Term::AnonVar =>
|
&Term::AnonVar if is_exposed =>
|
||||||
self.marker.mark_anon_var(Level::Deep, target),
|
self.marker.mark_anon_var(Level::Deep, target),
|
||||||
|
&Term::AnonVar =>
|
||||||
|
target.push(Target::to_void(1)),
|
||||||
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _) => {
|
&Term::Cons(ref cell, _, _) | &Term::Clause(ref cell, _, _) => {
|
||||||
let instr = self.non_var_subterm(Level::Deep, term_loc, cell, target);
|
let instr = self.non_var_subterm(Level::Deep, term_loc, cell, target);
|
||||||
target.push(instr);
|
target.push(instr);
|
||||||
@@ -139,14 +142,15 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
&Term::Constant(_, ref constant) =>
|
&Term::Constant(_, ref constant) =>
|
||||||
target.push(self.constant_subterm(constant)),
|
target.push(self.constant_subterm(constant)),
|
||||||
&Term::Var(ref cell, ref var) =>
|
&Term::Var(ref cell, ref var) =>
|
||||||
self.marker.mark_var(var, Level::Deep, cell, term_loc, target)
|
if is_exposed || self.get_var_count(var) > 1 {
|
||||||
|
self.marker.mark_var(var, Level::Deep, cell, term_loc, target);
|
||||||
|
} else {
|
||||||
|
target.push(Target::to_void(1));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_target<Target>(&mut self,
|
fn compile_target<Target>(&mut self, term: &'a Term, term_loc: GenContext, is_exposed: bool)
|
||||||
term: &'a Term,
|
|
||||||
term_loc: GenContext,
|
|
||||||
has_exposed_vars: bool)
|
|
||||||
-> Vec<Target>
|
-> Vec<Target>
|
||||||
where Target: CompilationTarget<'a>
|
where Target: CompilationTarget<'a>
|
||||||
{
|
{
|
||||||
@@ -165,33 +169,26 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
|
|
||||||
target.push(str_instr);
|
target.push(str_instr);
|
||||||
|
|
||||||
if !has_exposed_vars {
|
|
||||||
if self.all_singleton_vars(terms) {
|
|
||||||
target.push(Self::void_subterms(terms.len()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for subterm in terms {
|
for subterm in terms {
|
||||||
self.subterm_to_instr(subterm.as_ref(), term_loc, &mut target);
|
self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, &mut target);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TermRef::Cons(lvl, cell, head, tail) => {
|
TermRef::Cons(lvl, cell, head, tail) => {
|
||||||
let list_instr = self.to_list(lvl, term_loc, cell, &mut target);
|
let list_instr = self.to_list(lvl, term_loc, cell, &mut target);
|
||||||
target.push(list_instr);
|
target.push(list_instr);
|
||||||
|
|
||||||
self.subterm_to_instr(head, term_loc, &mut target);
|
self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
|
||||||
self.subterm_to_instr(tail, term_loc, &mut target);
|
self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
|
||||||
},
|
},
|
||||||
TermRef::Constant(lvl @ Level::Shallow, cell, constant) => {
|
TermRef::Constant(lvl @ Level::Shallow, cell, constant) => {
|
||||||
let const_instr = self.to_constant(lvl, cell, term_loc, constant, &mut target);
|
let const_instr = self.to_constant(lvl, cell, term_loc, constant, &mut target);
|
||||||
target.push(const_instr);
|
target.push(const_instr);
|
||||||
},
|
},
|
||||||
TermRef::AnonVar(lvl @ Level::Shallow) =>
|
TermRef::AnonVar(lvl @ Level::Shallow) =>
|
||||||
if has_exposed_vars {
|
if let GenContext::Head = term_loc {
|
||||||
self.marker.mark_anon_var(lvl, &mut target);
|
|
||||||
} else {
|
|
||||||
self.marker.advance_arg();
|
self.marker.advance_arg();
|
||||||
|
} else {
|
||||||
|
self.marker.mark_anon_var(lvl, &mut target);
|
||||||
},
|
},
|
||||||
TermRef::Var(lvl @ Level::Shallow, ref cell, ref var) =>
|
TermRef::Var(lvl @ Level::Shallow, ref cell, ref var) =>
|
||||||
self.marker.mark_var(var, lvl, cell, term_loc, &mut target),
|
self.marker.mark_var(var, lvl, cell, term_loc, &mut target),
|
||||||
@@ -199,10 +196,10 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
target
|
Self::flatten_void_instrs(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_var_data(iter: ChunkedIterator<'a>) -> (VariableFixtures, bool)
|
fn collect_var_data(&mut self, iter: ChunkedIterator<'a>) -> (VariableFixtures<'a>, bool)
|
||||||
{
|
{
|
||||||
let mut vs = VariableFixtures::new();
|
let mut vs = VariableFixtures::new();
|
||||||
let has_deep_cut = iter.contains_deep_cut();
|
let has_deep_cut = iter.contains_deep_cut();
|
||||||
@@ -219,8 +216,10 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match term_or_cut_ref {
|
match term_or_cut_ref {
|
||||||
&TermOrCutRef::Term(term) =>
|
&TermOrCutRef::Term(term) => {
|
||||||
vs.mark_vars_in_chunk(term, last_term_arity, chunk_num, term_loc),
|
self.update_var_count(term.breadth_first_iter());
|
||||||
|
vs.mark_vars_in_chunk(term, last_term_arity, chunk_num, term_loc);
|
||||||
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -268,7 +267,7 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
pub fn compile_rule(&mut self, rule: &'a Rule) -> Code
|
pub fn compile_rule(&mut self, rule: &'a Rule) -> Code
|
||||||
{
|
{
|
||||||
let iter = ChunkedIterator::from_rule(rule);
|
let iter = ChunkedIterator::from_rule(rule);
|
||||||
let (mut vs, deep_cuts) = Self::collect_var_data(iter);
|
let (mut vs, deep_cuts) = self.collect_var_data(iter);
|
||||||
vs = self.marker.drain_var_data(vs);
|
vs = self.marker.drain_var_data(vs);
|
||||||
|
|
||||||
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
|
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
|
||||||
@@ -286,17 +285,6 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match p1 {
|
|
||||||
&TermOrCut::Cut => {
|
|
||||||
let iter = p0.breadth_first_iter();
|
|
||||||
self.update_var_count(iter);
|
|
||||||
},
|
|
||||||
&TermOrCut::Term(ref p1) => {
|
|
||||||
let iter = p0.breadth_first_iter().chain(p1.breadth_first_iter());
|
|
||||||
self.update_var_count(iter);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if p0.is_clause() {
|
if p0.is_clause() {
|
||||||
body.push(Line::Fact(self.compile_target(p0, GenContext::Head, false)));
|
body.push(Line::Fact(self.compile_target(p0, GenContext::Head, false)));
|
||||||
}
|
}
|
||||||
@@ -404,10 +392,9 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
pub fn compile_fact(&mut self, term: &'a Term) -> Code
|
pub fn compile_fact(&mut self, term: &'a Term) -> Code
|
||||||
{
|
{
|
||||||
let iter = ChunkedIterator::from_term(term, true);
|
let iter = ChunkedIterator::from_term(term, true);
|
||||||
let (vs, _) = Self::collect_var_data(iter);
|
let (vs, _) = self.collect_var_data(iter);
|
||||||
self.marker.drain_var_data(vs);
|
self.marker.drain_var_data(vs);
|
||||||
|
|
||||||
self.update_var_count(term.breadth_first_iter());
|
|
||||||
self.marker.advance(term);
|
self.marker.advance(term);
|
||||||
|
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
@@ -427,7 +414,6 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
fn compile_internal_query(&mut self, term: &'a Term, term_loc: GenContext, index: usize) -> Code
|
fn compile_internal_query(&mut self, term: &'a Term, term_loc: GenContext, index: usize) -> Code
|
||||||
{
|
{
|
||||||
self.marker.advance(term);
|
self.marker.advance(term);
|
||||||
self.update_var_count(term.breadth_first_iter());
|
|
||||||
|
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
|
|
||||||
@@ -444,17 +430,15 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
pub fn compile_query(&mut self, term: &'a Term) -> Code
|
pub fn compile_query(&mut self, term: &'a Term) -> Code
|
||||||
{
|
{
|
||||||
let iter = ChunkedIterator::from_term(term, true);
|
let iter = ChunkedIterator::from_term(term, true);
|
||||||
let (vs, _) = Self::collect_var_data(iter);
|
let (vs, _) = self.collect_var_data(iter);
|
||||||
|
|
||||||
self.marker.drain_var_data(vs);
|
self.marker.drain_var_data(vs);
|
||||||
|
|
||||||
self.marker.advance(term);
|
self.marker.advance(term);
|
||||||
self.update_var_count(term.breadth_first_iter());
|
|
||||||
|
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
|
|
||||||
if term.is_clause() {
|
if term.is_clause() {
|
||||||
let compiled_query = self.compile_target(term, GenContext::Last(0), false);
|
let compiled_query = self.compile_target(term, GenContext::Last(0), true);
|
||||||
code.push(Line::Query(compiled_query));
|
code.push(Line::Query(compiled_query));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -200,8 +200,7 @@ impl<'a> TermMarker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete after anon_vars are handled by means of *_void stuff.
|
|
||||||
pub fn mark_anon_var<Target>(&mut self, lvl: Level, target: &mut Vec<Target>)
|
pub fn mark_anon_var<Target>(&mut self, lvl: Level, target: &mut Vec<Target>)
|
||||||
where Target: CompilationTarget<'a>
|
where Target: CompilationTarget<'a>
|
||||||
{
|
{
|
||||||
@@ -326,10 +325,6 @@ impl<'a> TermMarker<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_var(&self, var: &'a Var) -> bool {
|
|
||||||
self.bindings.contains_key(var)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn record_register(&mut self, var: &'a Var, r: RegType) {
|
fn record_register(&mut self, var: &'a Var, r: RegType) {
|
||||||
match self.bindings.get_mut(var).unwrap() {
|
match self.bindings.get_mut(var).unwrap() {
|
||||||
&mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
|
&mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ pub trait CompilationTarget<'a> {
|
|||||||
fn to_structure(Level, Atom, usize, RegType) -> Self;
|
fn to_structure(Level, Atom, usize, RegType) -> Self;
|
||||||
fn to_void(usize) -> Self;
|
fn to_void(usize) -> Self;
|
||||||
|
|
||||||
|
fn is_void_instr(&self) -> bool;
|
||||||
|
|
||||||
fn constant_subterm(Constant) -> Self;
|
fn constant_subterm(Constant) -> Self;
|
||||||
|
|
||||||
fn argument_to_variable(RegType, usize) -> Self;
|
fn argument_to_variable(RegType, usize) -> Self;
|
||||||
@@ -47,6 +49,13 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
|
|||||||
FactInstruction::UnifyVoid(subterms)
|
FactInstruction::UnifyVoid(subterms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_void_instr(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
&FactInstruction::UnifyVoid(_) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn constant_subterm(constant: Constant) -> Self {
|
fn constant_subterm(constant: Constant) -> Self {
|
||||||
FactInstruction::UnifyConstant(constant)
|
FactInstruction::UnifyConstant(constant)
|
||||||
}
|
}
|
||||||
@@ -99,6 +108,13 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
|
|||||||
QueryInstruction::SetVoid(subterms)
|
QueryInstruction::SetVoid(subterms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_void_instr(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
&QueryInstruction::SetVoid(_) => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn constant_subterm(constant: Constant) -> Self {
|
fn constant_subterm(constant: Constant) -> Self {
|
||||||
QueryInstruction::SetConstant(constant)
|
QueryInstruction::SetConstant(constant)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user