From: Mark Thom Date: Fri, 26 May 2017 18:59:03 +0000 (-0600) Subject: evacuate arg at shallow level when necessary X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=8402f7a608156cc3dd24ed8bcbc8d17884e02df1;p=scryer-prolog.git evacuate arg at shallow level when necessary --- diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index f49a7baa..f8005d2f 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -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) diff --git a/src/prolog/debray_allocator.rs b/src/prolog/debray_allocator.rs index 29c5f1c7..6c7a0d08 100644 --- a/src/prolog/debray_allocator.rs +++ b/src/prolog/debray_allocator.rs @@ -14,7 +14,14 @@ pub struct DebrayAllocator<'a> { in_use: BTreeSet, } -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) {