From: Mark Thom Date: Sat, 7 Apr 2018 06:15:34 +0000 (-0600) Subject: incomplete cut corrections. X-Git-Tag: v0.8.110~501 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=5d0674a667880f0bd9f7af1e96662f57e243a4f8;p=scryer-prolog.git incomplete cut corrections. --- diff --git a/src/prolog/allocator.rs b/src/prolog/allocator.rs index 5fbe9fac..b075b5c1 100644 --- a/src/prolog/allocator.rs +++ b/src/prolog/allocator.rs @@ -8,19 +8,22 @@ use std::rc::Rc; pub trait Allocator<'a> { fn new() -> Self; - + fn mark_anon_var(&mut self, Level, &mut Vec) where Target: CompilationTarget<'a>; fn mark_non_var(&mut self, Level, GenContext, &'a Cell, &mut Vec) where Target: CompilationTarget<'a>; + fn mark_reserved_var(&mut self, Rc, Level, &'a Cell, GenContext, + &mut Vec, RegType, bool) + where Target: CompilationTarget<'a>; fn mark_var(&mut self, Rc, Level, &'a Cell, GenContext, &mut Vec) - 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>); - + fn advance_arg(&mut self); fn bindings(&self) -> &AllocVarDict; @@ -46,15 +49,15 @@ pub trait Allocator<'a> perm_vs } - + fn get(&self, var: Rc) -> RegType { self.bindings().get(&var).map_or(temp_v!(0), |v| v.as_reg_type()) } fn is_unbound(&self, var: Rc) -> bool { - self.get(var) == temp_v!(0) + self.get(var).reg_num() == 0 } - + fn record_register(&mut self, var: Rc, r: RegType) { match self.bindings_mut().get_mut(&var).unwrap() { &mut VarData::Temp(_, ref mut s, _) => *s = r.reg_num(), diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index d2c8d4d6..f3064465 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -668,7 +668,8 @@ pub type JumpStub = Vec; pub enum QueryTerm { Clause(Cell, ClauseType, Vec>), - 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() } } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index e10d9fd9..05b9bf2a 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -161,6 +161,17 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator } 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 }; 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 { // add a proceed to bookend any trailing cuts. match toc { - &QueryTerm::Cut => code.push(proceed!()), + &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut => code.push(proceed!()), _ => {} }; diff --git a/src/prolog/debray_allocator.rs b/src/prolog/debray_allocator.rs index 00aa1ed2..2ded88f8 100644 --- a/src/prolog/debray_allocator.rs +++ b/src/prolog/debray_allocator.rs @@ -249,7 +249,7 @@ impl<'a> Allocator<'a> for DebrayAllocator } } - fn mark_var(&mut self, var: Rc, lvl: Level, cell: &Cell, + fn mark_var(&mut self, var: Rc, lvl: Level, cell: &'a Cell, term_loc: GenContext, target: &mut Vec) 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(&mut self, var: Rc, lvl: Level, cell: &'a Cell, + term_loc: GenContext, target: &mut Vec, r: RegType, + is_new_var: bool) + where Target: CompilationTarget<'a> + { match lvl { Level::Root | Level::Shallow => { let k = self.arg_c; diff --git a/src/prolog/io.rs b/src/prolog/io.rs index 293d5484..89440174 100644 --- a/src/prolog/io.rs +++ b/src/prolog/io.rs @@ -540,6 +540,8 @@ fn compile_query(terms: Vec, queue: Vec, 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) -> 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 { diff --git a/src/prolog/iterators.rs b/src/prolog/iterators.rs index e8bee429..8ed518e6 100644 --- a/src/prolog/iterators.rs +++ b/src/prolog/iterators.rs @@ -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>(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> + 'a>, - deep_cut_encountered: bool + deep_cut_encountered: bool, + cut_var_in_head: bool } type ChunkedIteratorItem<'a> = (usize, usize, Vec>); @@ -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)) => { diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index b1d35baa..c06ecc3a 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -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(); diff --git a/src/prolog/parser b/src/prolog/parser index ad4f9e57..737d6ba0 160000 --- a/src/prolog/parser +++ b/src/prolog/parser @@ -1 +1 @@ -Subproject commit ad4f9e573069ab5932c060d0ed093432f3d31c58 +Subproject commit 737d6ba091bb5909b0af31c221f290debc95bf2d