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

2
Cargo.lock generated
View File

@@ -1,6 +1,6 @@
[root] [root]
name = "rusty-wam" name = "rusty-wam"
version = "0.5.3" version = "0.5.5"
dependencies = [ dependencies = [
"lalrpop 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lalrpop-util 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-util 0.12.5 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "rusty-wam" name = "rusty-wam"
version = "0.5.4" version = "0.5.6"
authors = ["Mark Thom"] authors = ["Mark Thom"]
build = "build.rs" build = "build.rs"

View File

@@ -11,8 +11,8 @@ pure Prolog.
Pure Prolog is implemented as a simple REPL. "Pure Prolog" is Prolog Pure Prolog is implemented as a simple REPL. "Pure Prolog" is Prolog
without cut, meta- or extra-logical operators, or side effects of any without cut, meta- or extra-logical operators, or side effects of any
kind. In terms of the tutorial pacing, the work has progressed to the kind. In terms of the tutorial pacing, the work has progressed to the
to the end of section 5.3, skipping past 5.4. Atoms and lists to the end of section 5.6, skipping past 5.4. Atoms and lists are the
are the only two data types currently supported. only two data types currently supported.
## Tutorial ## Tutorial
To enter a multi-clause predicate, the brackets ":{" and "}:" are used To enter a multi-clause predicate, the brackets ":{" and "}:" are used

View File

@@ -117,6 +117,15 @@ pub struct Rule {
pub clauses: Vec<Term> 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> { pub enum TermRef<'a> {
AnonVar(Level), AnonVar(Level),
Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term), Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
@@ -159,6 +168,7 @@ pub enum ControlInstruction {
Allocate(usize), Allocate(usize),
Call(Atom, usize), Call(Atom, usize),
Deallocate, Deallocate,
Execute(Atom, usize),
Proceed Proceed
} }

View File

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

View File

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

View File

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