incomplete cut corrections.

This commit is contained in:
Mark Thom
2018-04-07 00:15:34 -06:00
parent 2e65f7243c
commit 5d0674a667
8 changed files with 81 additions and 24 deletions

View File

@@ -8,19 +8,22 @@ use std::rc::Rc;
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;
@@ -46,15 +49,15 @@ pub trait Allocator<'a>
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(),

View File

@@ -668,7 +668,8 @@ pub type JumpStub = Vec<Term>;
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)
}
@@ -676,7 +677,7 @@ impl QueryTerm {
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()
}
}

View File

@@ -161,6 +161,17 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
} 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),
_ => {}
@@ -397,7 +408,9 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
};
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 {
@@ -469,7 +482,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
{
// add a proceed to bookend any trailing cuts.
match toc {
&QueryTerm::Cut => code.push(proceed!()),
&QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => code.push(proceed!()),
_ => {}
};

View File

@@ -249,7 +249,7 @@ impl<'a> Allocator<'a> for DebrayAllocator
}
}
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>
{
@@ -271,6 +271,14 @@ impl<'a> Allocator<'a> for DebrayAllocator
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;

View File

@@ -540,6 +540,8 @@ fn compile_query(terms: Vec<QueryTerm>, queue: Vec<TopLevel>, code_size: usize,
let query_info = QueryInfo {};
query_info.label_clauses(code_size, code_dir, &mut code);
print_code(&code);
Ok((code, cg.take_vars()))
}
@@ -571,6 +573,8 @@ fn compile_decl(wam: &mut Machine, tl: TopLevel, queue: Vec<TopLevel>) -> EvalSe
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 {

View File

@@ -50,7 +50,8 @@ impl<'a> QueryIterator<'a> {
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)
@@ -213,11 +214,24 @@ impl<'a> ChunkedTerm<'a> {
}
}
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>>);
@@ -248,7 +262,8 @@ impl<'a> ChunkedIterator<'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
}
}
@@ -260,7 +275,8 @@ impl<'a> ChunkedIterator<'a>
ChunkedIterator {
chunk_num: 0,
iter: Box::new(iter),
deep_cut_encountered: false
deep_cut_encountered: false,
cut_var_in_head: false
}
}
@@ -276,6 +292,7 @@ impl<'a> ChunkedIterator<'a>
chunk_num: 0,
iter: Box::new(iter),
deep_cut_encountered: false,
cut_var_in_head: false
}
}
@@ -291,20 +308,32 @@ impl<'a> ChunkedIterator<'a>
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)) => {

View File

@@ -306,13 +306,12 @@ impl Machine {
{
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();