optimizations up to section 5.7.
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -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)",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rusty-wam"
|
||||
version = "0.5.4"
|
||||
version = "0.5.6"
|
||||
authors = ["Mark Thom"]
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user