assert_eq!(submit(&mut wam, "?- f(p(three), X, X)."), false);
assert_eq!(submit(&mut wam, "?- f(p(three), one, Y)."), false);
assert_eq!(submit(&mut wam, "?- f(p(three), one, two)."), false);
- assert_eq!(submit(&mut wam, "?- f(p(three), one, three)."), false);
+ assert_eq!(submit(&mut wam, "?- f(p(three), one, three)."), false);
+
+ submit(&mut wam, "f(P, X) :- call(P, X).");
+
+ assert_eq!(submit(&mut wam, "?- f(p(one), one)."), true);
}
}
Head, Mid(usize), Last(usize) // Mid & Last: chunk_num
}
+impl GenContext {
+ pub fn chunk_num(self) -> usize {
+ match self {
+ GenContext::Head => 0,
+ GenContext::Mid(cn) | GenContext::Last(cn) => cn
+ }
+ }
+}
+
pub enum PredicateClause {
Fact(Term),
Rule(Rule)
}
pub enum QueryTerm {
- CallN(Cell<VarReg>, Var, Vec<Box<Term>>),
+ CallN(Vec<Box<Term>>),
Cut,
Term(Term)
}
pub fn arity(&self) -> usize {
match self {
&QueryTerm::Term(ref term) => term.arity(),
- &QueryTerm::CallN(_, _, ref terms) => terms.len() + 1,
+ &QueryTerm::CallN(ref terms) => terms.len(),
_ => 0
}
}
pub fn to_ref(&self) -> QueryTermRef {
match self {
- &QueryTerm::CallN(ref cell, ref var, ref terms) =>
- QueryTermRef::CallN(cell, var, terms),
+ &QueryTerm::CallN(ref terms) =>
+ QueryTermRef::CallN(terms),
&QueryTerm::Cut =>
QueryTermRef::Cut,
&QueryTerm::Term(ref term) =>
#[derive(Clone, Copy)]
pub enum ClauseType<'a> {
- CallN(&'a Cell<VarReg>, &'a Var),
+ CallN,
Deep(Level, &'a Cell<RegType>, &'a Atom),
Root
}
impl<'a> ClauseType<'a> {
pub fn level_of_subterms(self) -> Level {
match self {
- ClauseType::CallN(_, _) => Level::Shallow,
+ ClauseType::CallN => Level::Shallow,
ClauseType::Deep(_, _, _) => Level::Deep,
ClauseType::Root => Level::Shallow
}
| 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
}
}
}
#[derive(Clone, Copy)]
pub enum QueryTermRef<'a> {
- CallN(&'a Cell<VarReg>, &'a Var, &'a Vec<Box<Term>>),
+ CallN(&'a Vec<Box<Term>>),
Cut,
Term(&'a Term)
}
pub fn arity(self) -> usize {
match self {
QueryTermRef::Term(term) => term.arity(),
- QueryTermRef::CallN(_, _, terms) => terms.len() + 1,
+ QueryTermRef::CallN(terms) => terms.len(),
_ => 0
}
}
match self {
QueryTermRef::Term(&Term::Clause(_, _, _))
| QueryTermRef::Term(&Term::Constant(_, Constant::Atom(_)))
- | QueryTermRef::CallN(_, _, _) =>
- true,
+ | QueryTermRef::CallN(_) => true,
_ => false
}
}
where Target: CompilationTarget<'a>
{
match ct {
- ClauseType::CallN(_, _) =>
- for subterm in terms {
- self.subterm_to_instr(subterm.as_ref(), term_loc, is_exposed, target);
- },
ClauseType::Deep(lvl, cell, atom) => {
self.marker.mark_non_var(lvl, term_loc, cell, target);
target.push(Target::to_structure(lvl, atom.clone(), terms.len(), cell.get()));
fn add_conditional_call(compiled_query: &mut Code, qt: QueryTermRef, pvs: usize)
{
match qt {
- QueryTermRef::CallN(_, _, terms) => {
+ QueryTermRef::CallN(terms) => {
let call = ControlInstruction::CallN(terms.len());
compiled_query.push(Line::Control(call));
},
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
*ctrl = ControlInstruction::Execute(name.clone(), last_arity);
},
- &QueryTerm::CallN(_, _, ref terms) =>
+ &QueryTerm::CallN(ref terms) =>
if let &mut Line::Control(ref mut ctrl) = body.last_mut().unwrap() {
*ctrl = ControlInstruction::ExecuteN(terms.len());
},
in_use: BTreeSet<usize>,
}
-impl<'a> DebrayAllocator<'a> {
+impl<'a> DebrayAllocator<'a> {
+ fn is_curr_arg_distinct_from(&self, var: &'a Var) -> bool {
+ match self.contents.get(&self.arg_c) {
+ Some(t_var) if **t_var != *var => true,
+ _ => false
+ }
+ }
+
fn occurs_shallowly_in_head(&self, var: &'a Var, r: usize) -> bool
{
match self.bindings.get(var).unwrap() {
match term_loc {
GenContext::Head =>
if let Level::Shallow = lvl {
+ self.evacuate_arg(0, target);
self.alloc_with_cr(var)
} else {
self.alloc_with_ca(var)
RegType::Perm(0) => {
let pr = cell.get().norm();
self.record_register(var, pr);
+
(pr, true)
},
- r => (r, false)
+ r => (r, false)
};
match lvl {
Level::Shallow => {
let k = self.arg_c;
+
+ if !r.is_perm() {
+ if self.is_curr_arg_distinct_from(var) {
+ self.evacuate_arg(term_loc.chunk_num(), target);
+ }
+ }
+
self.arg_c += 1;
cell.set(VarReg::ArgAndNorm(r, k));
Level::Deep =>
target.push(Target::subterm_to_value(r))
};
-
+
if !r.is_perm() {
let o = r.reg_num();
self.contents.insert(o, var);
self.record_register(var, r);
self.in_use.insert(o);
- }
+ }
}
fn reset(&mut self) {
let compiled_fact = cg.compile_fact(fact);
wam.add_fact(fact, compiled_fact);
-
+
EvalSession::EntrySuccess
},
&TopLevel::Rule(ref rule) => {
fn new(term: QueryTermRef<'a>) -> Self {
match term {
- QueryTermRef::CallN(cell, var, child_terms) => {
- let state = IteratorState::Clause(0, ClauseType::CallN(cell, var), child_terms);
-
+ QueryTermRef::CallN(child_terms) => {
+ let state = IteratorState::Clause(0, ClauseType::CallN, child_terms);
QueryIterator { state_stack: vec![state] }
},
QueryTermRef::Term(term) => Self::from_term(term),
IteratorState::Clause(child_num, ct, child_terms) => {
if child_num == child_terms.len() {
match ct {
- ClauseType::Root =>
+ ClauseType::CallN | ClauseType::Root =>
return None,
ClauseType::Deep(_, _, _) =>
- return Some(TermRef::Clause(ct, child_terms)),
- ClauseType::CallN(cell, var) => {
- let state = IteratorState::Var(Level::Shallow, cell, var);
- self.state_stack.push(state);
- }
+ return Some(TermRef::Clause(ct, child_terms))
};
} else {
self.push_clause(child_num + 1, ct, child_terms);
self.push_subterm(ct.level_of_subterms(), child_term);
}
- match ct {
- ClauseType::Root =>
- continue,
+ match ct {
ClauseType::Deep(_, _, _) =>
return Some(TermRef::Clause(ct, child_terms)),
- ClauseType::CallN(cell, var) => {
- let state = IteratorState::Var(Level::Shallow, cell, var);
- self.state_queue.push_back(state);
- }
+ _ =>
+ continue
};
},
IteratorState::InitialCons(lvl, cell, head, tail) => {
let iter = once(QueryTermRef::Term(p0));
let inner_iter : Box<Iterator<Item=QueryTermRef<'a>>> = match p1 {
- &QueryTerm::CallN(ref cell, ref var, ref child_terms) =>
- Box::new(once(QueryTermRef::CallN(cell, var, child_terms))),
+ &QueryTerm::CallN(ref child_terms) =>
+ Box::new(once(QueryTermRef::CallN(child_terms))),
&QueryTerm::Term(ref p1) =>
Box::new(once(QueryTermRef::Term(p1))),
_ => Box::new(empty())
break;
}
},
- QueryTermRef::CallN(_, _, child_terms) => {
+ QueryTermRef::CallN(child_terms) => {
result.push(term);
arity = child_terms.len() + 1;
break;
&ControlInstruction::Call(ref name, arity, _) =>
self.try_call_predicate(code_dir, name.clone(), arity),
&ControlInstruction::CallN(arity) => {
- let addr = self.deref(self.registers[arity + 1].clone());
+ let addr = self.deref(self.registers[arity].clone());
match self.store(addr) {
Addr::Str(a) => {
self.registers[i] = self.heap[a + i].as_addr(a + i);
}
- self.try_call_predicate(code_dir, name, arity + narity);
+ self.try_call_predicate(code_dir, name, arity + narity - 1);
} else {
self.fail = true;
}
},
Addr::Con(Constant::Atom(name)) =>
- self.try_call_predicate(code_dir, name, arity),
+ self.try_call_predicate(code_dir, name, arity - 1),
_ => self.fail = true
};
},
&ControlInstruction::Execute(ref name, arity) =>
self.try_execute_predicate(code_dir, name.clone(), arity),
&ControlInstruction::ExecuteN(arity) => {
- let addr = self.deref(self.registers[arity + 1].clone());
+ let addr = self.deref(self.registers[arity].clone());
match self.store(addr) {
Addr::Str(a) => {
self.registers[i] = self.heap[a + i].as_addr(a + i);
}
- self.try_execute_predicate(code_dir, name, arity + narity);
+ self.try_execute_predicate(code_dir, name, arity + narity - 1);
} else {
self.fail = true;
}
},
Addr::Con(Constant::Atom(name)) =>
- self.try_execute_predicate(code_dir, name, arity),
+ self.try_execute_predicate(code_dir, name, arity - 1),
_ => self.fail = true
};
},
},
"call" "(" <a:Atom> <ts: ("," <BoxedTerm>)*> ")" =>
QueryTerm::Term(Term::Clause(Cell::default(), a, ts)),
- "call" "(" <v:Var> <ts: ("," <BoxedTerm>)*> ")" =>
- QueryTerm::CallN(Cell::default(), v, ts)
+ "call" "(" <v:Var> <ts: ("," <BoxedTerm>)*> ")" => {
+ let mut ts = ts;
+ let bv = Box::new(Term::Var(Cell::default(), v));
+
+ ts.push(bv);
+ QueryTerm::CallN(ts)
+ }
};
Clause : Term = {
QueryTerm : QueryTerm = {
<Call> => <>,
"!" => QueryTerm::Cut,
- <Var> => QueryTerm::CallN(Cell::default(), <>, Vec::new()),
+ <Var> => QueryTerm::CallN(vec![Box::new(Term::Var(Cell::default(), <>))]),
<Clause> => QueryTerm::Term(<>),
<Atom> => QueryTerm::Term(Term::Constant(Cell::default(), Constant::Atom(<>)))
};
Var : Var = {
r"[A-Z][A-Za-z0-9_]*" => <>.trim().to_string()
-};
\ No newline at end of file
+};
(_, _, _): (usize, &'input str, usize),
) -> QueryTerm
{
- QueryTerm::CallN(Cell::default(), v, ts)
+ {
+ let mut ts = ts;
+ let bv = Box::new(Term::Var(Cell::default(), v));
+
+ ts.push(bv);
+ QueryTerm::CallN(ts)
+ }
}
#[allow(unused_variables)]
(_, __0, _): (usize, Var, usize),
) -> QueryTerm
{
- QueryTerm::CallN(Cell::default(), __0, Vec::new())
+ QueryTerm::CallN(vec![Box::new(Term::Var(Cell::default(), __0))])
}
#[allow(unused_variables)]