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]
name = "rusty-wam"
version = "0.5.3"
version = "0.5.5"
dependencies = [
"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)",

View File

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

View File

@@ -11,8 +11,8 @@ pure 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
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
are the only two data types currently supported.
to the end of section 5.6, skipping past 5.4. Atoms and lists are the
only two data types currently supported.
## Tutorial
To enter a multi-clause predicate, the brackets ":{" and "}:" are used

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

@@ -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
}

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")
}

View File

@@ -682,19 +682,22 @@ impl MachineState {
&ControlInstruction::Deallocate => {
let e = self.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.cp = self.and_stack[e].cp;
self.e = self.and_stack[e].e;
self.p = self.and_stack[e].cp;
self.e = self.and_stack[e].e;
self.p += 1;
},
&ControlInstruction::Execute(ref name, arity) => {
let compiled_tl_index = code_dir.get(&(name.clone(), arity))
.map(|index| *index);
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,