[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)",
[package]
name = "rusty-wam"
-version = "0.5.4"
+version = "0.5.6"
authors = ["Mark Thom"]
build = "build.rs"
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
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),
Allocate(usize),
Call(Atom, usize),
Deallocate,
+ Execute(Atom, usize),
Proceed
}
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)
}
continue;
}
}
-
+
for subterm in terms {
target.push(self.subterm_to_instr(subterm.as_ref()));
}
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);
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)));
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
}
compiled_fact.push(proceed);
compiled_fact
}
-
+
fn compile_internal_query(&mut self, term: &'a Term) -> Code {
self.marker.advance(term);
compiled_query
}
-
+
pub fn compile_query(&mut self, term: &'a Term) -> Code {
self.marker.advance(term);
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")
}
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(_) => {
},
&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 = 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,