optimizations up to section 5.7.

This commit is contained in:
Mark Thom
2017-03-23 01:06:06 -06:00
parent 9362aa6af3
commit e1cc5ecfd6
7 changed files with 58 additions and 24 deletions

View File

@@ -117,6 +117,15 @@ pub struct Rule {
pub clauses: Vec<Term>
}
impl Rule {
pub fn last_clause(&self) -> &Term {
match self.clauses.last() {
None => &self.head.1,
Some(clause) => clause
}
}
}
pub enum TermRef<'a> {
AnonVar(Level),
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
@@ -159,6 +168,7 @@ pub enum ControlInstruction {
Allocate(usize),
Call(Atom, usize),
Deallocate,
Execute(Atom, usize),
Proceed
}

View File

@@ -81,7 +81,7 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
fn iter(term: &'a Term) -> Self::Iterator {
term.post_order_iter()
}
fn to_structure(lvl: Level, atom: Atom, arity: usize, reg: RegType) -> Self {
QueryInstruction::PutStructure(lvl, atom, arity, reg)
}
@@ -443,7 +443,7 @@ impl<'a> CodeGenerator<'a> {
continue;
}
}
for subterm in terms {
target.push(self.subterm_to_instr(subterm.as_ref()));
}
@@ -517,7 +517,8 @@ impl<'a> CodeGenerator<'a> {
vfs
}
fn add_conditional_call(compiled_query: &mut Code, term: &Term) {
fn add_conditional_call(compiled_query: &mut Code, term: &Term)
{
match term {
&Term::Constant(_, Constant::Atom(ref atom)) => {
let call = ControlInstruction::Call(atom.clone(), 0);
@@ -544,7 +545,9 @@ impl<'a> CodeGenerator<'a> {
let mut body = Vec::new();
body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
if clauses.len() > 0 {
body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
}
self.marker.advance(p0);
body.push(Line::Fact(self.compile_target(p0, false)));
@@ -561,7 +564,23 @@ impl<'a> CodeGenerator<'a> {
body
});
body.push(Line::Control(ControlInstruction::Deallocate));
let last_arity = rule.last_clause().arity();
let mut dealloc_index = body.len() - 1;
match rule.last_clause() {
&Term::Clause(_, ref name, _)
| &Term::Constant(_, Constant::Atom(ref name)) => {
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
*ctrl = ControlInstruction::Execute(name.clone(), last_arity);
}
},
_ => dealloc_index = body.len()
};
if clauses.len() > 0 {
body.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
}
body
}
@@ -574,7 +593,7 @@ impl<'a> CodeGenerator<'a> {
compiled_fact.push(proceed);
compiled_fact
}
fn compile_internal_query(&mut self, term: &'a Term) -> Code {
self.marker.advance(term);
@@ -583,7 +602,7 @@ impl<'a> CodeGenerator<'a> {
compiled_query
}
pub fn compile_query(&mut self, term: &'a Term) -> Code {
self.marker.advance(term);

View File

@@ -92,6 +92,8 @@ impl fmt::Display for ControlInstruction {
write!(f, "call {}/{}", name, arity),
&ControlInstruction::Deallocate =>
write!(f, "deallocate"),
&ControlInstruction::Execute(ref name, arity) =>
write!(f, "execute {}/{}", name, arity),
&ControlInstruction::Proceed =>
write!(f, "proceed")
}
@@ -233,7 +235,7 @@ Each predicate must have the same name and arity.";
EvalResult::EntrySuccess
},
&Ok(TopLevel::Query(ref query)) => {
let compiled_query = cg.compile_query(&query);
let compiled_query = cg.compile_query(&query);
wam.run_query(compiled_query, &cg)
},
&Err(_) => {

View File

@@ -681,20 +681,23 @@ impl MachineState {
},
&ControlInstruction::Deallocate => {
let e = self.e;
self.cp = self.and_stack[e].cp;
self.e = self.and_stack[e].e;
let num_frame_e = self.and_stack.top().unwrap().global_index;
let num_frame_b = self.or_stack
.top()
.map(|fr| fr.global_index)
.unwrap_or(0);
self.p += 1;
},
&ControlInstruction::Execute(ref name, arity) => {
let compiled_tl_index = code_dir.get(&(name.clone(), arity))
.map(|index| *index);
self.p = self.and_stack[e].cp;
self.e = self.and_stack[e].e;
if num_frame_e > num_frame_b {
let top_e = self.and_stack.top().unwrap().e;
self.and_stack.drop_frames(top_e - self.e + 1);
}
match compiled_tl_index {
Some(compiled_tl_index) => {
self.num_of_args = arity;
self.p = CodePtr::DirEntry(compiled_tl_index);
},
None => self.fail = true
};
},
&ControlInstruction::Proceed =>
self.p = self.cp,