add tests, update status.
This commit is contained in:
@@ -16,7 +16,7 @@ argument indexing, and conjunctive queries.
|
||||
Extend rusty-wam to include the following, among other features:
|
||||
|
||||
* call/N as a built-in meta-predicate (_done_).
|
||||
* ISO Prolog compliant throw/catch (_done_).
|
||||
* ISO Prolog compliant throw/catch (_in progress_).
|
||||
* Built-in and user-defined operators of all fixities,
|
||||
with custom associativity and precedence.
|
||||
* Bignum and floating point arithmetic.
|
||||
|
||||
52
src/main.rs
52
src/main.rs
@@ -504,15 +504,15 @@ mod tests {
|
||||
assert_eq!(submit(&mut wam, "?- member(X, [a,b,c,d]), !, member(X, [a,d])."), true);
|
||||
assert_eq!(submit(&mut wam, "?- member(X, [a,b,c,d]), !, member(X, [e])."), false);
|
||||
assert_eq!(submit(&mut wam, "?- member([X,X],[a,b,c,[d,d],[e,d]]),
|
||||
member(X, [a,b,c,d,e,f,g]),
|
||||
member(X, [a,b,c,d,e,f,g]),
|
||||
member(Y, [X, a, b, c, d])."),
|
||||
true);
|
||||
assert_eq!(submit(&mut wam, "?- member([X,X],[a,b,c,[d,d],[e,d]]),
|
||||
member(X, [a,b,c,d,e,f,g]),
|
||||
member(X, [a,b,c,d,e,f,g]),
|
||||
!,
|
||||
member(Y, [X, a, b, c, d])."),
|
||||
true);
|
||||
|
||||
|
||||
submit(&mut wam, "p(a, [f(g(X))]).");
|
||||
submit(&mut wam, "q(Y, c).");
|
||||
|
||||
@@ -545,11 +545,11 @@ mod tests {
|
||||
fn test_queries_on_call_n()
|
||||
{
|
||||
let mut wam = Machine::new();
|
||||
|
||||
|
||||
submit(&mut wam, "maplist(Pred, []).
|
||||
maplist(Pred, [X|Xs]) :- call(Pred, X), maplist(Pred, Xs).");
|
||||
submit(&mut wam, "f(a). f(b). f(c).");
|
||||
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- maplist(f, [X,Y,Z])."), true);
|
||||
assert_eq!(submit(&mut wam, "?- maplist(f, [a,Y,Z])."), true);
|
||||
assert_eq!(submit(&mut wam, "?- maplist(f, [X,a,b])."), true);
|
||||
@@ -580,7 +580,7 @@ mod tests {
|
||||
assert_eq!(submit(&mut wam, "?- f(p, x, y)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- f(p, X, z)."), false);
|
||||
assert_eq!(submit(&mut wam, "?- f(p, z, Y)."), false);
|
||||
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- call(p, X)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- call(p, x)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- call(p, y)."), true);
|
||||
@@ -639,7 +639,7 @@ mod tests {
|
||||
assert_eq!(submit(&mut wam, "?- call(david_lynch, kyle(Film), _)."), false);
|
||||
|
||||
submit(&mut wam, "call_mult(P, X) :- call(call(P), X).");
|
||||
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- call_mult(p(X), Y)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- call_mult(p(X), X)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- call_mult(p(one), X)."), true);
|
||||
@@ -656,10 +656,10 @@ mod tests {
|
||||
assert_eq!(submit(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), Y)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), X, Y)."), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(call(p), X, Y), call(call(call(p(X))), X)."), true);
|
||||
|
||||
|
||||
submit(&mut wam, "f(call(f, undefined)). f(undefined).");
|
||||
submit(&mut wam, "call_var(P) :- P.");
|
||||
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- f(X), call_var(X)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- f(call(f, Q)), call_var(call(f, Q))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- call_var(call(undefined, Q))."), false);
|
||||
@@ -681,25 +681,49 @@ mod tests {
|
||||
submit(&mut wam, "handle(stuff).");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(Exception))."), true);
|
||||
|
||||
|
||||
submit(&mut wam, "f(a). f(X) :- g(X).");
|
||||
submit(&mut wam, "g(x). g(y). g(z).");
|
||||
submit(&mut wam, "handle(x). handle(y).");
|
||||
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), X, handle(X))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(a), _, handle(X))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(b), _, handle(X))."), false);
|
||||
|
||||
submit(&mut wam, "g(x). g(X) :- throw(x).");
|
||||
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), x, handle(X))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), x, handle(z))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(x))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(y))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(z), x, handle(z))."), false);
|
||||
|
||||
submit(&mut wam, "f(X) :- throw(stuff). f(X) :- throw(other_stuff).");
|
||||
submit(&mut wam, "handle(stuff). handle(other_stuff).");
|
||||
|
||||
// this should deterministically succeed with Exception = stuff.
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(Exception))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(stuff))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(other_stuff))."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), Exception, handle(not_stuff))."), false);
|
||||
|
||||
submit(&mut wam, "f(success). f(X) :- catch(g(X), E, handle(E)).");
|
||||
submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X).");
|
||||
submit(&mut wam, "handle(x). handle(y). handle(z).");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), E, E)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(fail), _, _)."), false);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(x), _, _)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(y), _, _)."), true);
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(z), _, _)."), true);
|
||||
|
||||
//TODO: write more tests: multi-layered throw/catch, catch
|
||||
// within catch, throw within catch, etc.
|
||||
submit(&mut wam, "f(success). f(E) :- catch(g(E), E, handle(E)).");
|
||||
submit(&mut wam, "g(g_success). g(g_success_2). g(X) :- throw(X).");
|
||||
submit(&mut wam, "handle(x). handle(y). handle(z). handle(v) :- throw(X).");
|
||||
|
||||
//TODO: fix this test. record the ball properly. currently it
|
||||
// is unwound when the heap is truncated.
|
||||
assert_eq!(submit(&mut wam, "?- catch(f(X), E, E)."), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,8 +159,10 @@ pub enum Term {
|
||||
|
||||
pub enum QueryTerm {
|
||||
CallN(Vec<Box<Term>>),
|
||||
Catch(Vec<Box<Term>>),
|
||||
Cut,
|
||||
Term(Term)
|
||||
Term(Term),
|
||||
Throw(Vec<Box<Term>>)
|
||||
}
|
||||
|
||||
impl QueryTerm {
|
||||
@@ -168,10 +170,14 @@ impl QueryTerm {
|
||||
match self {
|
||||
&QueryTerm::CallN(ref terms) =>
|
||||
QueryTermRef::CallN(terms),
|
||||
&QueryTerm::Catch(ref terms) =>
|
||||
QueryTermRef::Catch(terms),
|
||||
&QueryTerm::Cut =>
|
||||
QueryTermRef::Cut,
|
||||
&QueryTerm::Term(ref term) =>
|
||||
QueryTermRef::Term(term),
|
||||
&QueryTerm::Throw(ref t) =>
|
||||
QueryTermRef::Throw(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,14 +190,16 @@ pub struct Rule {
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ClauseType<'a> {
|
||||
CallN,
|
||||
Catch,
|
||||
Deep(Level, &'a Cell<RegType>, &'a Atom),
|
||||
Root
|
||||
Root,
|
||||
Throw
|
||||
}
|
||||
|
||||
impl<'a> ClauseType<'a> {
|
||||
pub fn level_of_subterms(self) -> Level {
|
||||
match self {
|
||||
ClauseType::CallN => Level::Shallow,
|
||||
ClauseType::CallN | ClauseType::Catch | ClauseType::Throw => Level::Shallow,
|
||||
ClauseType::Deep(_, _, _) => Level::Deep,
|
||||
ClauseType::Root => Level::Shallow
|
||||
}
|
||||
@@ -216,7 +224,9 @@ impl<'a> TermRef<'a> {
|
||||
| TermRef::Var(lvl, _, _) => lvl,
|
||||
TermRef::Clause(ClauseType::Root, _) => Level::Shallow,
|
||||
TermRef::Clause(ClauseType::Deep(lvl, _, _), _) => lvl,
|
||||
TermRef::Clause(ClauseType::CallN, _) => Level::Shallow
|
||||
TermRef::Clause(ClauseType::CallN, _) => Level::Shallow,
|
||||
TermRef::Clause(ClauseType::Throw, _) => Level::Shallow,
|
||||
TermRef::Clause(ClauseType::Catch, _) => Level::Shallow
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,13 +234,17 @@ impl<'a> TermRef<'a> {
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum QueryTermRef<'a> {
|
||||
CallN(&'a Vec<Box<Term>>),
|
||||
Catch(&'a Vec<Box<Term>>),
|
||||
Cut,
|
||||
Term(&'a Term),
|
||||
Throw(&'a Vec<Box<Term>>)
|
||||
}
|
||||
|
||||
impl<'a> QueryTermRef<'a> {
|
||||
pub fn arity(self) -> usize {
|
||||
match self {
|
||||
QueryTermRef::Catch(_) => 3,
|
||||
QueryTermRef::Throw(_) => 1,
|
||||
QueryTermRef::CallN(terms) => terms.len(),
|
||||
QueryTermRef::Cut => 0,
|
||||
QueryTermRef::Term(term) => term.arity(),
|
||||
@@ -276,7 +290,7 @@ impl IndexedChoiceInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BuiltInInstruction {
|
||||
pub enum BuiltInInstruction {
|
||||
CleanUpBlock,
|
||||
CopyTerm,
|
||||
Fail,
|
||||
@@ -297,19 +311,23 @@ pub enum ControlInstruction {
|
||||
Allocate(usize),
|
||||
Call(Atom, usize, usize),
|
||||
CallN(usize),
|
||||
Catch,
|
||||
Deallocate,
|
||||
Execute(Atom, usize),
|
||||
ExecuteN(usize),
|
||||
Proceed
|
||||
Proceed,
|
||||
Throw
|
||||
}
|
||||
|
||||
impl ControlInstruction {
|
||||
pub fn is_jump_instr(&self) -> bool {
|
||||
match self {
|
||||
&ControlInstruction::Call(_, _, _) => true,
|
||||
&ControlInstruction::Execute(_, _) => true,
|
||||
&ControlInstruction::Call(_, _, _) => true,
|
||||
&ControlInstruction::Catch => true,
|
||||
&ControlInstruction::Execute(_, _) => true,
|
||||
&ControlInstruction::CallN(_) => true,
|
||||
&ControlInstruction::ExecuteN(_) => true,
|
||||
&ControlInstruction::Throw => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ fn get_builtins() -> Code {
|
||||
deallocate!(),
|
||||
goto!(58, 0), // goto false.
|
||||
set_ball!(), // throw/1, 56.
|
||||
unwind_stack!(),
|
||||
unwind_stack!(),
|
||||
fail!(), // false/0, 58.
|
||||
proceed!(),
|
||||
try_me_else!(7), // not/1, 60.
|
||||
|
||||
@@ -24,20 +24,18 @@ pub enum EvalSession<'a> {
|
||||
pub struct ConjunctInfo<'a> {
|
||||
pub perm_vs: VariableFixtures<'a>,
|
||||
pub num_of_chunks: usize,
|
||||
pub has_deep_cut: bool,
|
||||
pub has_catch: bool
|
||||
pub has_deep_cut: bool
|
||||
}
|
||||
|
||||
impl<'a> ConjunctInfo<'a>
|
||||
{
|
||||
fn new(perm_vs: VariableFixtures<'a>, num_of_chunks: usize, has_deep_cut: bool, has_catch: bool)
|
||||
-> Self
|
||||
fn new(perm_vs: VariableFixtures<'a>, num_of_chunks: usize, has_deep_cut: bool) -> Self
|
||||
{
|
||||
ConjunctInfo { perm_vs, num_of_chunks, has_deep_cut, has_catch }
|
||||
ConjunctInfo { perm_vs, num_of_chunks, has_deep_cut }
|
||||
}
|
||||
|
||||
fn allocates(&self) -> bool {
|
||||
self.perm_vs.size() > 0 || self.num_of_chunks > 1 || self.has_deep_cut || self.has_catch
|
||||
self.perm_vs.size() > 0 || self.num_of_chunks > 1 || self.has_deep_cut
|
||||
}
|
||||
|
||||
fn perm_vars(&self) -> usize {
|
||||
@@ -45,7 +43,7 @@ impl<'a> ConjunctInfo<'a>
|
||||
}
|
||||
|
||||
fn perm_var_offset(&self) -> usize {
|
||||
self.has_deep_cut as usize + 2 * (self.has_catch as usize)
|
||||
self.has_deep_cut as usize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,14 +195,13 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
|
||||
let num_of_chunks = iter.chunk_num();
|
||||
let has_deep_cut = iter.encountered_deep_cut();
|
||||
let has_catch = iter.encountered_catch();
|
||||
|
||||
vs.populate_restricting_sets();
|
||||
vs.set_perm_vals(has_deep_cut, has_catch);
|
||||
vs.set_perm_vals(has_deep_cut);
|
||||
|
||||
let vs = self.marker.drain_var_data(vs);
|
||||
|
||||
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut, has_catch)
|
||||
ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
|
||||
}
|
||||
|
||||
fn add_conditional_call(compiled_query: &mut Code, qt: QueryTermRef, pvs: usize)
|
||||
@@ -214,6 +211,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
let call = ControlInstruction::CallN(terms.len());
|
||||
compiled_query.push(Line::Control(call));
|
||||
},
|
||||
QueryTermRef::Catch(_) =>
|
||||
compiled_query.push(Line::Control(ControlInstruction::Catch)),
|
||||
QueryTermRef::Term(&Term::Constant(_, Constant::Atom(ref atom))) => {
|
||||
let call = ControlInstruction::Call(atom.clone(), 0, pvs);
|
||||
compiled_query.push(Line::Control(call));
|
||||
@@ -222,6 +221,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
|
||||
let call = ControlInstruction::Call(atom.clone(), terms.len(), pvs);
|
||||
compiled_query.push(Line::Control(call));
|
||||
},
|
||||
QueryTermRef::Throw(_) =>
|
||||
compiled_query.push(Line::Control(ControlInstruction::Throw)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ impl<'a> VariableFixtures<'a>
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
pub fn set_perm_vals(&self, has_deep_cuts: bool, has_catch: bool)
|
||||
pub fn set_perm_vals(&self, has_deep_cuts: bool)
|
||||
{
|
||||
let mut values_vec : Vec<_> = self.values()
|
||||
.filter_map(|ref v| {
|
||||
@@ -231,7 +231,7 @@ impl<'a> VariableFixtures<'a>
|
||||
|
||||
values_vec.sort_by_key(|ref v| v.0);
|
||||
|
||||
let offset = has_deep_cuts as usize + 2 * has_catch as usize;
|
||||
let offset = has_deep_cuts as usize;
|
||||
|
||||
for (i, (_, cells)) in values_vec.into_iter().rev().enumerate() {
|
||||
for cell in cells {
|
||||
|
||||
@@ -104,6 +104,8 @@ impl fmt::Display for ControlInstruction {
|
||||
write!(f, "call {}/{}, {}", name, arity, pvs),
|
||||
&ControlInstruction::CallN(arity) =>
|
||||
write!(f, "call_N {}", arity),
|
||||
&ControlInstruction::Catch =>
|
||||
write!(f, "catch"),
|
||||
&ControlInstruction::ExecuteN(arity) =>
|
||||
write!(f, "execute_N {}", arity),
|
||||
&ControlInstruction::Deallocate =>
|
||||
@@ -111,7 +113,9 @@ impl fmt::Display for ControlInstruction {
|
||||
&ControlInstruction::Execute(ref name, arity) =>
|
||||
write!(f, "execute {}/{}", name, arity),
|
||||
&ControlInstruction::Proceed =>
|
||||
write!(f, "proceed")
|
||||
write!(f, "proceed"),
|
||||
&ControlInstruction::Throw =>
|
||||
write!(f, "throw")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,10 +243,28 @@ fn rewrite_call_n(terms: &mut Vec<Box<Term>>) -> QueryTerm {
|
||||
QueryTerm::CallN(new_terms)
|
||||
}
|
||||
|
||||
fn rewrite_catch(terms: &mut Vec<Box<Term>>) -> QueryTerm {
|
||||
let mut new_terms = Vec::with_capacity(0);
|
||||
swap(&mut new_terms, terms);
|
||||
|
||||
QueryTerm::Catch(new_terms)
|
||||
}
|
||||
|
||||
fn rewrite_throw(terms: &mut Vec<Box<Term>>) -> QueryTerm {
|
||||
let mut new_terms = Vec::with_capacity(0);
|
||||
swap(&mut new_terms, terms);
|
||||
|
||||
QueryTerm::Throw(new_terms)
|
||||
}
|
||||
|
||||
fn rewrite_clause(name: &Atom, terms: &mut Vec<Box<Term>>) -> Option<QueryTerm>
|
||||
{
|
||||
if name == "call" {
|
||||
Some(rewrite_call_n(terms))
|
||||
} else if name == "catch" && terms.len() == 3 {
|
||||
Some(rewrite_catch(terms))
|
||||
} else if name == "throw" && terms.len() == 1 {
|
||||
Some(rewrite_throw(terms))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -370,6 +392,7 @@ Each predicate must have the same name and arity.";
|
||||
let mut cg = CodeGenerator::<DebrayAllocator>::new();
|
||||
|
||||
let compiled_query = cg.compile_query(query);
|
||||
print_code(&compiled_query);
|
||||
wam.submit_query(compiled_query, cg.take_vars())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,11 +72,19 @@ impl<'a> QueryIterator<'a> {
|
||||
|
||||
fn new(term: QueryTermRef<'a>) -> Self {
|
||||
match term {
|
||||
QueryTermRef::CallN(child_terms) => {
|
||||
let state = IteratorState::Clause(1, ClauseType::CallN, child_terms);
|
||||
QueryTermRef::CallN(terms) => {
|
||||
let state = IteratorState::Clause(1, ClauseType::CallN, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
QueryTermRef::Catch(terms) => {
|
||||
let state = IteratorState::Clause(0, ClauseType::Catch, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
QueryTermRef::Term(term) => Self::from_term(term),
|
||||
QueryTermRef::Throw(term) => {
|
||||
let state = IteratorState::Clause(0, ClauseType::Throw, term);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
QueryTermRef::Term(term) => Self::from_term(term),
|
||||
_ => QueryIterator { state_stack: vec![] }
|
||||
}
|
||||
}
|
||||
@@ -101,7 +109,7 @@ impl<'a> Iterator for QueryIterator<'a> {
|
||||
match ct {
|
||||
ClauseType::CallN =>
|
||||
self.push_subterm(Level::Shallow, child_terms[0].as_ref()),
|
||||
ClauseType::Root =>
|
||||
ClauseType::Root | ClauseType::Throw | ClauseType::Catch =>
|
||||
return None,
|
||||
ClauseType::Deep(_, _, _) =>
|
||||
return Some(TermRef::Clause(ct, child_terms))
|
||||
@@ -211,8 +219,7 @@ pub struct ChunkedIterator<'a>
|
||||
{
|
||||
term_loc: GenContext,
|
||||
iter: Box<Iterator<Item=QueryTermRef<'a>> + 'a>,
|
||||
deep_cut_encountered: bool,
|
||||
catch_encountered: bool
|
||||
deep_cut_encountered: bool
|
||||
}
|
||||
|
||||
impl<'a> ChunkedIterator<'a>
|
||||
@@ -226,7 +233,6 @@ impl<'a> ChunkedIterator<'a>
|
||||
term_loc: GenContext::Head,
|
||||
iter: inner_iter,
|
||||
deep_cut_encountered: false,
|
||||
catch_encountered: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,49 +243,34 @@ impl<'a> ChunkedIterator<'a>
|
||||
ChunkedIterator {
|
||||
term_loc: GenContext::Last(0),
|
||||
iter: Box::new(iter),
|
||||
deep_cut_encountered: false,
|
||||
catch_encountered: false
|
||||
}
|
||||
}
|
||||
|
||||
fn iterate_over_query_term(p1: &'a QueryTerm) -> Box<Iterator<Item=QueryTermRef<'a>> + 'a>
|
||||
{
|
||||
match p1 {
|
||||
&QueryTerm::CallN(ref child_terms) =>
|
||||
Box::new(once(QueryTermRef::CallN(child_terms))),
|
||||
&QueryTerm::Term(ref p1) =>
|
||||
Box::new(once(QueryTermRef::Term(p1))),
|
||||
&QueryTerm::Cut =>
|
||||
Box::new(once(QueryTermRef::Cut))
|
||||
deep_cut_encountered: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self
|
||||
{
|
||||
let inner_iter = Self::iterate_over_query_term(p1);
|
||||
let inner_iter = Box::new(once(p1.to_ref()));
|
||||
let iter = inner_iter.chain(clauses.iter().map(|c| c.to_ref()));
|
||||
|
||||
ChunkedIterator {
|
||||
term_loc: GenContext::Last(0),
|
||||
iter: Box::new(iter),
|
||||
deep_cut_encountered: false,
|
||||
catch_encountered: false
|
||||
deep_cut_encountered: false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_rule(rule: &'a Rule) -> Self
|
||||
{
|
||||
let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
|
||||
let iter = once(QueryTermRef::Term(p0));
|
||||
|
||||
let inner_iter = Self::iterate_over_query_term(p1);
|
||||
let iter = once(QueryTermRef::Term(p0));
|
||||
let inner_iter = Box::new(once(p1.to_ref()));
|
||||
let iter = iter.chain(inner_iter.chain(clauses.iter().map(|c| c.to_ref())));
|
||||
|
||||
ChunkedIterator {
|
||||
term_loc: GenContext::Head,
|
||||
iter: Box::new(iter),
|
||||
deep_cut_encountered: false,
|
||||
catch_encountered: false
|
||||
deep_cut_encountered: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,10 +278,6 @@ impl<'a> ChunkedIterator<'a>
|
||||
self.deep_cut_encountered
|
||||
}
|
||||
|
||||
pub fn encountered_catch(&self) -> bool {
|
||||
self.catch_encountered
|
||||
}
|
||||
|
||||
pub fn at_rule_head(&self) -> bool {
|
||||
self.term_loc == GenContext::Head
|
||||
}
|
||||
@@ -307,6 +294,9 @@ impl<'a> ChunkedIterator<'a>
|
||||
|
||||
while let Some(term) = item {
|
||||
match term {
|
||||
//TODO: This can refer to the term at the head of a
|
||||
// goal, not technically a QueryTerm (ie. a term in a
|
||||
// query). Think of a better name.
|
||||
QueryTermRef::Term(inner_term) => {
|
||||
if let GenContext::Head = self.term_loc {
|
||||
result.push(term);
|
||||
@@ -325,6 +315,11 @@ impl<'a> ChunkedIterator<'a>
|
||||
arity = child_terms.len() + 1;
|
||||
break;
|
||||
},
|
||||
QueryTermRef::Catch(child_terms) | QueryTermRef::Throw(child_terms) => {
|
||||
result.push(term);
|
||||
arity = child_terms.len();
|
||||
break;
|
||||
},
|
||||
QueryTermRef::Cut => {
|
||||
result.push(term);
|
||||
|
||||
|
||||
@@ -1286,6 +1286,12 @@ impl MachineState {
|
||||
},
|
||||
&ControlInstruction::Call(ref name, arity, _) =>
|
||||
self.try_call_predicate(code_dir, name.clone(), arity),
|
||||
&ControlInstruction::Catch => {
|
||||
self.cp = self.p + 1;
|
||||
self.num_of_args = 3;
|
||||
self.b0 = self.b;
|
||||
self.p = CodePtr::DirEntry(5);
|
||||
},
|
||||
&ControlInstruction::CallN(arity) =>
|
||||
if let Some((name, arity)) = self.setup_call_n(arity) {
|
||||
self.try_call_predicate(code_dir, name, arity);
|
||||
@@ -1306,6 +1312,12 @@ impl MachineState {
|
||||
},
|
||||
&ControlInstruction::Proceed =>
|
||||
self.p = self.cp,
|
||||
&ControlInstruction::Throw => {
|
||||
self.cp = self.p + 1;
|
||||
self.num_of_args = 1;
|
||||
self.b0 = self.b;
|
||||
self.p = CodePtr::DirEntry(56);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user