pub trait Allocator<'a>
{
fn new() -> Self;
-
+
fn mark_anon_var<Target>(&mut self, Level, &mut Vec<Target>)
where Target: CompilationTarget<'a>;
fn mark_non_var<Target>(&mut self, Level, GenContext, &'a Cell<RegType>, &mut Vec<Target>)
where Target: CompilationTarget<'a>;
+ fn mark_reserved_var<Target>(&mut self, Rc<Var>, Level, &'a Cell<VarReg>, GenContext,
+ &mut Vec<Target>, RegType, bool)
+ where Target: CompilationTarget<'a>;
fn mark_var<Target>(&mut self, Rc<Var>, Level, &'a Cell<VarReg>, GenContext, &mut Vec<Target>)
- where Target: CompilationTarget<'a>;
-
+ where Target: CompilationTarget<'a>;
+
fn reset(&mut self);
fn reset_contents(&mut self) {}
fn reset_arg(&mut self, usize);
fn reset_at_head(&mut self, &Vec<Box<Term>>);
-
+
fn advance_arg(&mut self);
fn bindings(&self) -> &AllocVarDict;
perm_vs
}
-
+
fn get(&self, var: Rc<Var>) -> RegType {
self.bindings().get(&var).map_or(temp_v!(0), |v| v.as_reg_type())
}
fn is_unbound(&self, var: Rc<Var>) -> bool {
- self.get(var) == temp_v!(0)
+ self.get(var).reg_num() == 0
}
-
+
fn record_register(&mut self, var: Rc<Var>, r: RegType) {
match self.bindings_mut().get_mut(&var).unwrap() {
&mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(),
pub enum QueryTerm {
Clause(Cell<RegType>, ClauseType, Vec<Box<Term>>),
- Cut,
+ BlockedCut, // a cut which is 'blocked by letters', like the P term in P -> Q.
+ UnblockedCut,
Jump(JumpStub)
}
pub fn arity(&self) -> usize {
match self {
&QueryTerm::Clause(_, _, ref subterms) => subterms.len(),
- &QueryTerm::Cut => 0,
+ &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => 0,
&QueryTerm::Jump(ref vars) => vars.len()
}
}
} else {
self.marker.mark_anon_var(lvl, &mut target);
},
+ TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
+ if self.marker.is_unbound(var.clone()) {
+ if term_loc != GenContext::Head {
+ self.marker.mark_reserved_var(var.clone(), lvl, cell, term_loc,
+ &mut target, perm_v!(1), false);
+ continue;
+ }
+ }
+
+ self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target);
+ },
TermRef::Var(lvl @ Level::Shallow, cell, var) =>
self.marker.mark_var(var.clone(), lvl, cell, term_loc, &mut target),
_ => {}
};
match *term {
- &QueryTerm::Cut =>
+ &QueryTerm::UnblockedCut =>
+ code.push(set_cp!(self.marker.get(rc_atom!("!")))),
+ &QueryTerm::BlockedCut =>
code.push(if chunk_num == 0 {
Line::Cut(CutInstruction::NeckCut)
} else {
{
// add a proceed to bookend any trailing cuts.
match toc {
- &QueryTerm::Cut => code.push(proceed!()),
+ &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => code.push(proceed!()),
_ => {}
};
}
}
- fn mark_var<Target>(&mut self, var: Rc<Var>, lvl: Level, cell: &Cell<VarReg>,
+ fn mark_var<Target>(&mut self, var: Rc<Var>, lvl: Level, cell: &'a Cell<VarReg>,
term_loc: GenContext, target: &mut Vec<Target>)
where Target: CompilationTarget<'a>
{
r => (r, false)
};
+ self.mark_reserved_var(var, lvl, cell, term_loc, target, r, is_new_var);
+ }
+
+ fn mark_reserved_var<Target>(&mut self, var: Rc<Var>, lvl: Level, cell: &'a Cell<VarReg>,
+ term_loc: GenContext, target: &mut Vec<Target>, r: RegType,
+ is_new_var: bool)
+ where Target: CompilationTarget<'a>
+ {
match lvl {
Level::Root | Level::Shallow => {
let k = self.arg_c;
let query_info = QueryInfo {};
query_info.label_clauses(code_size, code_dir, &mut code);
+ print_code(&code);
+
Ok((code, cg.take_vars()))
}
decl_info.label_clauses(wam.code_size(), &mut wam.code_dir, &mut code);
+ print_code(&code);
+
if !code.is_empty() {
wam.add_user_code(name, tl.arity(), code, tl.as_predicate().unwrap())
} else {
let state = TermIterState::Clause(Level::Root, 0, cell, ct.clone(), terms);
QueryIterator { state_stack: vec![state] }
},
- &QueryTerm::Cut => QueryIterator { state_stack: vec![] },
+ &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut =>
+ QueryIterator { state_stack: vec![] },
&QueryTerm::Jump(ref vars) => {
let state_stack = vars.iter().rev().map(|t| {
TermIterState::subterm_to_state(Level::Shallow, t)
}
}
+fn contains_cut_var<'a, Iter: Iterator<Item=&'a Term>>(terms: Iter) -> bool {
+ for term in terms {
+ if let &Term::Var(_, ref var) = term {
+ if var.as_str() == "!" {
+ return true;
+ }
+ }
+ }
+
+ false
+}
+
pub struct ChunkedIterator<'a>
{
pub chunk_num: usize,
iter: Box<Iterator<Item=ChunkedTerm<'a>> + 'a>,
- deep_cut_encountered: bool
+ deep_cut_encountered: bool,
+ cut_var_in_head: bool
}
type ChunkedIteratorItem<'a> = (usize, usize, Vec<ChunkedTerm<'a>>);
ChunkedIterator {
chunk_num: 0,
iter: Box::new(terms.iter().map(|t| ChunkedTerm::BodyTerm(t))),
- deep_cut_encountered: false
+ deep_cut_encountered: false,
+ cut_var_in_head: false
}
}
ChunkedIterator {
chunk_num: 0,
iter: Box::new(iter),
- deep_cut_encountered: false
+ deep_cut_encountered: false,
+ cut_var_in_head: false
}
}
chunk_num: 0,
iter: Box::new(iter),
deep_cut_encountered: false,
+ cut_var_in_head: false
}
}
while let Some(term) = item {
match term {
- ChunkedTerm::HeadClause(..) =>
- result.push(term),
+ ChunkedTerm::HeadClause(_, terms) => {
+ if contains_cut_var(terms.iter().map(|t| t.as_ref())) {
+ self.cut_var_in_head = true;
+ }
+
+ result.push(term);
+ },
ChunkedTerm::BodyTerm(&QueryTerm::Jump(ref vars)) => {
result.push(term);
arity = vars.len();
+
+ if contains_cut_var(vars.iter()) && !self.cut_var_in_head {
+ self.deep_cut_encountered = true;
+ }
+
break;
},
- ChunkedTerm::BodyTerm(&QueryTerm::Cut) => {
+ ChunkedTerm::BodyTerm(&QueryTerm::BlockedCut) => {
result.push(term);
if self.chunk_num > 0 {
self.deep_cut_encountered = true;
}
},
+ ChunkedTerm::BodyTerm(&QueryTerm::UnblockedCut) =>
+ result.push(term),
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), _)) =>
result.push(term),
ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::CallN, ref subterms)) => {
{
for (var, var_data) in alloc_locs {
match var_data {
- &VarData::Perm(_) => {
+ &VarData::Perm(p) if p > 0 => {
let e = self.ms.e;
-
let r = var_data.as_reg_type().reg_num();
let addr = self.ms.and_stack[e][r].clone();
-
- heap_locs.insert(var.clone(), addr);
+
+ heap_locs.insert(var.clone(), addr);
},
&VarData::Temp(cn, _, _) if cn == chunk_num => {
let r = var_data.as_reg_type();
-Subproject commit ad4f9e573069ab5932c060d0ed093432f3d31c58
+Subproject commit 737d6ba091bb5909b0af31c221f290debc95bf2d