evacuate arguments on overwrite.

This commit is contained in:
Mark Thom
2017-05-25 16:41:36 -06:00
parent cf470e48c2
commit 4d6897509d
9 changed files with 80 additions and 54 deletions

View File

@@ -611,7 +611,11 @@ mod tests {
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);
}
}

View File

@@ -13,6 +13,15 @@ pub enum GenContext {
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)
@@ -115,7 +124,7 @@ pub enum Term {
}
pub enum QueryTerm {
CallN(Cell<VarReg>, Var, Vec<Box<Term>>),
CallN(Vec<Box<Term>>),
Cut,
Term(Term)
}
@@ -124,15 +133,15 @@ impl QueryTerm {
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) =>
@@ -148,7 +157,7 @@ pub struct Rule {
#[derive(Clone, Copy)]
pub enum ClauseType<'a> {
CallN(&'a Cell<VarReg>, &'a Var),
CallN,
Deep(Level, &'a Cell<RegType>, &'a Atom),
Root
}
@@ -156,7 +165,7 @@ pub enum ClauseType<'a> {
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
}
@@ -181,14 +190,14 @@ 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
}
}
}
#[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)
}
@@ -197,7 +206,7 @@ impl<'a> QueryTermRef<'a> {
pub fn arity(self) -> usize {
match self {
QueryTermRef::Term(term) => term.arity(),
QueryTermRef::CallN(_, _, terms) => terms.len() + 1,
QueryTermRef::CallN(terms) => terms.len(),
_ => 0
}
}
@@ -206,8 +215,7 @@ impl<'a> QueryTermRef<'a> {
match self {
QueryTermRef::Term(&Term::Clause(_, _, _))
| QueryTermRef::Term(&Term::Constant(_, Constant::Atom(_)))
| QueryTermRef::CallN(_, _, _) =>
true,
| QueryTermRef::CallN(_) => true,
_ => false
}
}

View File

@@ -97,10 +97,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
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()));
@@ -182,7 +178,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
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));
},
@@ -209,7 +205,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
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());
},

View File

@@ -14,7 +14,14 @@ pub struct DebrayAllocator<'a> {
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() {
@@ -142,6 +149,7 @@ impl<'a> DebrayAllocator<'a> {
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)
@@ -262,14 +270,22 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
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));
@@ -295,14 +311,14 @@ impl<'a> Allocator<'a> for DebrayAllocator<'a>
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) {

View File

@@ -285,7 +285,7 @@ Each predicate must have the same name and arity.";
let compiled_fact = cg.compile_fact(fact);
wam.add_fact(fact, compiled_fact);
EvalSession::EntrySuccess
},
&TopLevel::Rule(ref rule) => {

View File

@@ -69,9 +69,8 @@ impl<'a> QueryIterator<'a> {
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),
@@ -97,14 +96,10 @@ impl<'a> Iterator for QueryIterator<'a> {
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);
@@ -172,15 +167,11 @@ impl<'a> Iterator for FactIterator<'a> {
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) => {
@@ -249,8 +240,8 @@ impl<'a> ChunkedIterator<'a>
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())
@@ -288,7 +279,7 @@ impl<'a> ChunkedIterator<'a>
break;
}
},
QueryTermRef::CallN(_, _, child_terms) => {
QueryTermRef::CallN(child_terms) => {
result.push(term);
arity = child_terms.len() + 1;
break;

View File

@@ -994,7 +994,7 @@ impl MachineState {
&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) => {
@@ -1006,13 +1006,13 @@ impl MachineState {
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
};
},
@@ -1027,7 +1027,7 @@ impl MachineState {
&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) => {
@@ -1039,13 +1039,13 @@ impl MachineState {
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
};
},

View File

@@ -32,8 +32,13 @@ Call : QueryTerm = {
},
"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 = {
@@ -93,7 +98,7 @@ Rule : Rule = {
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(<>)))
};
@@ -108,4 +113,4 @@ Term : Term = {
Var : Var = {
r"[A-Z][A-Za-z0-9_]*" => <>.trim().to_string()
};
};

View File

@@ -2901,7 +2901,13 @@ pub fn __action9<
(_, _, _): (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)]
@@ -3105,7 +3111,7 @@ pub fn __action24<
(_, __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)]