refine code generation, scale back unsafe variable instructions for conjunctive queries
This commit is contained in:
@@ -133,15 +133,6 @@ pub struct Rule {
|
|||||||
pub clauses: Vec<TermOrCut>
|
pub clauses: Vec<TermOrCut>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rule {
|
|
||||||
pub fn last_clause(&self) -> &TermOrCut {
|
|
||||||
match self.clauses.last() {
|
|
||||||
None => &self.head.1,
|
|
||||||
Some(clause) => clause
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum TermRef<'a> {
|
pub enum TermRef<'a> {
|
||||||
AnonVar(Level),
|
AnonVar(Level),
|
||||||
|
|||||||
@@ -277,14 +277,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
vec![Line::Cut(CutInstruction::Cut(Terminal::Terminal))],
|
vec![Line::Cut(CutInstruction::Cut(Terminal::Terminal))],
|
||||||
&TermOrCutRef::Term(term) if i + 1 < terms.len() => {
|
&TermOrCutRef::Term(term) if i + 1 < terms.len() => {
|
||||||
let num_vars = vs.vars_above_threshold(i + 1);
|
let num_vars = vs.vars_above_threshold(i + 1);
|
||||||
self.compile_internal_query(term,
|
self.compile_query_line(term,
|
||||||
GenContext::Mid(chunk_num),
|
GenContext::Mid(chunk_num),
|
||||||
num_vars,
|
num_vars,
|
||||||
is_exposed)
|
is_exposed)
|
||||||
},
|
},
|
||||||
&TermOrCutRef::Term(term) => {
|
&TermOrCutRef::Term(term) => {
|
||||||
let num_vars = vs.vars_above_threshold(i + 1);
|
let num_vars = vs.vars_above_threshold(i + 1);
|
||||||
self.compile_internal_query(term,
|
self.compile_query_line(term,
|
||||||
GenContext::Last(chunk_num),
|
GenContext::Last(chunk_num),
|
||||||
num_vars,
|
num_vars,
|
||||||
is_exposed)
|
is_exposed)
|
||||||
@@ -318,14 +318,14 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
|
|
||||||
fn compile_neck_cut_or(&mut self,
|
fn compile_neck_cut_or(&mut self,
|
||||||
p1: &'a TermOrCut,
|
p1: &'a TermOrCut,
|
||||||
clauses: &'a [TermOrCut],
|
|
||||||
body: &mut Code,
|
body: &mut Code,
|
||||||
perm_vars: usize,
|
perm_vars: usize,
|
||||||
is_exposed: bool)
|
is_exposed: bool,
|
||||||
|
at_end: bool)
|
||||||
{
|
{
|
||||||
match p1 {
|
match p1 {
|
||||||
&TermOrCut::Cut => {
|
&TermOrCut::Cut => {
|
||||||
let term = if clauses.is_empty() {
|
let term = if at_end {
|
||||||
Terminal::Terminal
|
Terminal::Terminal
|
||||||
} else {
|
} else {
|
||||||
Terminal::Non
|
Terminal::Non
|
||||||
@@ -367,40 +367,34 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
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;
|
||||||
let mut body = Vec::new();
|
let mut code = Vec::new();
|
||||||
|
|
||||||
self.marker.advance(GenContext::Head, p0);
|
self.marker.advance(GenContext::Head, p0);
|
||||||
|
|
||||||
let perm_vars = self.compile_seq_prelude(clauses.len(), &vs, deep_cuts, &mut body);
|
let perm_vars = self.compile_seq_prelude(clauses.len(), &vs, deep_cuts, &mut code);
|
||||||
|
|
||||||
if p0.is_clause() {
|
if p0.is_clause() {
|
||||||
body.push(Line::Fact(self.compile_target(p0, GenContext::Head, false)));
|
code.push(Line::Fact(self.compile_target(p0, GenContext::Head, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let clauses_slice = if clauses.len() > 1 {
|
self.compile_neck_cut_or(p1, &mut code, perm_vars, false, clauses.len() == 0);
|
||||||
&clauses[1 .. ]
|
self.compile_seq(clauses, &vs, &mut code, false);
|
||||||
|
|
||||||
|
if perm_vars > 0 {
|
||||||
|
let index = if let &Line::Control(_) = code.last().unwrap() {
|
||||||
|
code.len() - 2
|
||||||
} else {
|
} else {
|
||||||
&[]
|
code.len() - 1
|
||||||
};
|
};
|
||||||
|
|
||||||
self.compile_neck_cut_or(p1, clauses_slice, &mut body, perm_vars, false);
|
if let &mut Line::Query(ref mut query) = &mut code[index] {
|
||||||
self.compile_seq(clauses, &vs, &mut body, false);
|
|
||||||
|
|
||||||
if clauses.len() > 0 {
|
|
||||||
let mut index = body.len() - 1;
|
|
||||||
|
|
||||||
if let &Line::Control(_) = body.last().unwrap() {
|
|
||||||
index -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let &mut Line::Query(ref mut query) = &mut body[index] {
|
|
||||||
vs.mark_unsafe_vars_in_rule(p0, query);
|
vs.mark_unsafe_vars_in_rule(p0, query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::compile_cleanup(&mut body, clauses.len(), rule.last_clause());
|
Self::compile_cleanup(&mut code, clauses.len(), clauses.last().unwrap_or(p1));
|
||||||
|
|
||||||
body
|
code
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)
|
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)
|
||||||
@@ -452,7 +446,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
code
|
code
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_internal_query(&mut self,
|
fn compile_query_line(&mut self,
|
||||||
term: &'a Term,
|
term: &'a Term,
|
||||||
term_loc: GenContext,
|
term_loc: GenContext,
|
||||||
index: usize,
|
index: usize,
|
||||||
@@ -487,21 +481,19 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
|||||||
deep_cuts,
|
deep_cuts,
|
||||||
&mut code);
|
&mut code);
|
||||||
|
|
||||||
let query_slice = if query.len() > 1 {
|
self.compile_neck_cut_or(p1, &mut code, perm_vars, true, query.len() == 1);
|
||||||
&query[1 .. ]
|
self.compile_seq(&query[1 .. ], &vs, &mut code, true);
|
||||||
|
|
||||||
|
if perm_vars > 0 {
|
||||||
|
let index = if let &Line::Control(_) = code.last().unwrap() {
|
||||||
|
code.len() - 2
|
||||||
} else {
|
} else {
|
||||||
&[]
|
code.len() - 1
|
||||||
};
|
};
|
||||||
|
|
||||||
self.compile_neck_cut_or(p1, query_slice, &mut code, perm_vars, true);
|
if let &mut Line::Query(ref mut query) = &mut code[index] {
|
||||||
self.compile_seq(query_slice, &vs, &mut code, true);
|
vs.mark_unsafe_vars_in_query(query);
|
||||||
|
}
|
||||||
for line in code.iter_mut() {
|
|
||||||
match line {
|
|
||||||
&mut Line::Query(ref mut query) =>
|
|
||||||
vs.mark_unsafe_vars_in_query(query),
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::compile_cleanup(&mut code, query.len() - 1, query.last().unwrap());
|
Self::compile_cleanup(&mut code, query.len() - 1, query.last().unwrap());
|
||||||
|
|||||||
Reference in New Issue
Block a user