]> Repositorios git - scryer-prolog.git/commitdiff
backtrack attributed variable bindings after failure (#242)
authorMark Thom <[email protected]>
Fri, 29 Nov 2019 17:47:22 +0000 (13:47 -0400)
committerMark Thom <[email protected]>
Fri, 29 Nov 2019 17:47:22 +0000 (13:47 -0400)
src/prolog/machine/attributed_variables.pl
src/prolog/machine/attributed_variables.rs
src/prolog/machine/copier.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/or_stack.rs
src/prolog/toplevel.pl

index 1323d2f5536c1582ebc1152a4e6f7d2e206e4716..8d896083496499b8bdc4e2bd2c2840886606376c 100644 (file)
@@ -28,7 +28,7 @@ call_verify_attributes(Attrs, _, _, []) :-
 call_verify_attributes([], _, _, []).
 call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
     gather_modules([Attr|Attrs], Modules0),
-    sort(Modules0, Modules),
+    sort(Modules0, Modules),    
     verify_attrs(Modules, Var, Value, ListOfGoalLists).
 
 call_goals([ListOfGoalLists | ListsCubed]) :-
index 50a101b90e82f78f3de7b6ce9a849cf926ffe9c2..8631fca79e02556afc82d9e3f82907bf7f302cc1 100644 (file)
@@ -36,19 +36,25 @@ impl AttrVarInitializer {
         self.attr_var_queue.clear();
         self.bindings.clear();
     }
+
+    #[inline]
+    pub(super) fn backtrack(&mut self, queue_b: usize, bindings_b: usize) {
+        self.attr_var_queue.truncate(queue_b);
+        self.bindings.truncate(bindings_b);
+    }
 }
 
 impl MachineState {
     pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
         if self.attr_var_init.bindings.is_empty() {
             self.attr_var_init.instigating_p = self.p.local();
-            
+
             if self.last_call {
                 self.attr_var_init.cp = self.cp;
             } else {
                 self.attr_var_init.cp = self.p.local() + 1;
             }
-            
+
             self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
         }
 
@@ -61,6 +67,7 @@ impl MachineState {
             .bindings
             .iter()
             .map(|(ref h, _)| Addr::AttrVar(*h));
+
         let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
 
         let iter = self
@@ -68,6 +75,7 @@ impl MachineState {
             .bindings
             .iter()
             .map(|(_, ref addr)| addr.clone());
+
         let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
 
         (var_list_addr, value_list_addr)
index f900ec8f6f4e44e6da9bade73a0db86caa8e62f2..2c65da694b33560fcef8df3772975fb0541cd4da 100644 (file)
@@ -58,34 +58,6 @@ impl<T: CopierTarget> CopyTermState<T> {
         }
     }
 
-    fn reinstantiate_var(&mut self, addr: Addr, threshold: usize) {
-        match addr {
-            Addr::HeapCell(h) => {
-                self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold));
-                self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
-                self.trail
-                    .push((Ref::HeapCell(h), HeapCellValue::Addr(Addr::HeapCell(h))));
-            }
-            Addr::StackCell(fr, sc) => {
-                self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold));
-                self.target.stack()[fr][sc] = Addr::HeapCell(threshold);
-                self.trail.push((
-                    Ref::StackCell(fr, sc),
-                    HeapCellValue::Addr(Addr::StackCell(fr, sc)),
-                ));
-            }
-            Addr::AttrVar(h) => {
-                let redirect_tag = self.attr_var_redirect_tag();
-
-                self.target[threshold] = HeapCellValue::Addr(redirect_tag(threshold));
-                self.target[h] = HeapCellValue::Addr(redirect_tag(threshold));
-                self.trail
-                    .push((Ref::AttrVar(h), HeapCellValue::Addr(Addr::AttrVar(h))));
-            }
-            _ => {}
-        }
-    }
-
     fn copied_list(&mut self, addr: usize) -> bool {
         if let HeapCellValue::Addr(Addr::Lis(addr)) = self.target[addr].clone() {
             if addr >= self.old_h {
@@ -113,22 +85,10 @@ impl<T: CopierTarget> CopyTermState<T> {
         let rd = self.target.store(self.target.deref(ra));
 
         match rd.clone() {
-            Addr::AttrVar(h) if h >= self.old_h => {
-                let redirect_tag = self.attr_var_redirect_tag();
-                self.target[threshold] = HeapCellValue::Addr(redirect_tag(h));
-            }
-            Addr::HeapCell(h) if h >= self.old_h => {
+            Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
                 self.target[threshold] = HeapCellValue::Addr(rd)
             }
-            Addr::AttrVar(h) => {
-                if Addr::AttrVar(h) == rd {
-                    self.reinstantiate_var(Addr::AttrVar(h), threshold);
-                } else {
-                    let redirect_tag = self.attr_var_redirect_tag();
-                    self.target[threshold] = HeapCellValue::Addr(redirect_tag(h));
-                }
-            }
-            ra @ Addr::HeapCell(..) | ra @ Addr::StackCell(..) => {
+            ra @ Addr::AttrVar(..) | ra @ Addr::HeapCell(_) | ra @ Addr::StackCell(..) => {
                 if ra == rd {
                     self.reinstantiate_var(ra, threshold);
                 } else {
@@ -148,6 +108,38 @@ impl<T: CopierTarget> CopyTermState<T> {
         self.scan += 1;
     }
 
+    fn reinstantiate_var(&mut self, addr: Addr, threshold: usize) {
+        match addr {
+            Addr::HeapCell(h) => {
+                self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold));
+                self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
+                self.trail.push((
+                    Ref::HeapCell(h),
+                    HeapCellValue::Addr(Addr::HeapCell(h)),
+                ));
+            }
+            Addr::StackCell(fr, sc) => {
+                self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold));
+                self.target.stack()[fr][sc] = Addr::HeapCell(threshold);
+                self.trail.push((
+                    Ref::StackCell(fr, sc),
+                    HeapCellValue::Addr(Addr::StackCell(fr, sc)),
+                ));
+            }
+            Addr::AttrVar(h) => {
+                let redirect_tag = self.attr_var_redirect_tag();
+
+                self.target[threshold] = HeapCellValue::Addr(redirect_tag(threshold));
+                self.target[h] = HeapCellValue::Addr(redirect_tag(threshold));
+                self.trail.push((
+                    Ref::AttrVar(h),
+                    HeapCellValue::Addr(Addr::AttrVar(h)),
+                ));
+            }
+            _ => unreachable!()
+        }
+    }
+
     fn copy_var(&mut self, addr: Addr) {
         let rd = self.target.store(self.target.deref(addr.clone()));
 
@@ -168,7 +160,7 @@ impl<T: CopierTarget> CopyTermState<T> {
                 self.target
                     .push(HeapCellValue::Addr(redirect_tag(threshold)));
 
-                if let Addr::AttrVar(_) = redirect_tag(threshold) {
+                if let AttrVarPolicy::DeepCopy = self.attr_var_policy {
                     let list_val = self.target[h + 1].clone();
                     self.target.push(list_val);
                 }
@@ -181,7 +173,9 @@ impl<T: CopierTarget> CopyTermState<T> {
                 self.reinstantiate_var(addr, scan);
                 self.scan += 1;
             }
-            _ => *self.value_at_scan() = HeapCellValue::Addr(rd),
+            _ => {
+                *self.value_at_scan() = HeapCellValue::Addr(rd);
+            }
         }
     }
 
index 3d451f7da6411f3987a5f13cb366e0070821c3b7..20162ac16891d4c21f964b4706f03b182dc326bb 100644 (file)
@@ -445,11 +445,13 @@ pub(crate) trait CallPolicy: Any {
 
         machine_st.heap.truncate(machine_st.or_stack[b].h);
 
-        let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
-        machine_st
-            .attr_var_init
-            .attr_var_queue
-            .truncate(attr_var_init_b);
+        let attr_var_init_queue_b = machine_st.or_stack[b].attr_var_init_queue_b;
+        let attr_var_init_bindings_b = machine_st.or_stack[b].attr_var_init_bindings_b;
+
+        machine_st.attr_var_init.backtrack(
+            attr_var_init_queue_b,
+            attr_var_init_bindings_b,
+        );
 
         machine_st.hb = machine_st.heap.h;
         machine_st.p += 1;
@@ -491,11 +493,13 @@ pub(crate) trait CallPolicy: Any {
 
         machine_st.heap.truncate(machine_st.or_stack[b].h);
 
-        let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
-        machine_st
-            .attr_var_init
-            .attr_var_queue
-            .truncate(attr_var_init_b);
+        let attr_var_init_queue_b = machine_st.or_stack[b].attr_var_init_queue_b;
+        let attr_var_init_bindings_b = machine_st.or_stack[b].attr_var_init_bindings_b;
+
+        machine_st.attr_var_init.backtrack(
+            attr_var_init_queue_b,
+            attr_var_init_bindings_b,
+        );
 
         machine_st.hb = machine_st.heap.h;
         machine_st.p += offset;
@@ -533,11 +537,13 @@ pub(crate) trait CallPolicy: Any {
 
         machine_st.heap.truncate(machine_st.or_stack[b].h);
 
-        let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
-        machine_st
-            .attr_var_init
-            .attr_var_queue
-            .truncate(attr_var_init_b);
+        let attr_var_init_queue_b = machine_st.or_stack[b].attr_var_init_queue_b;
+        let attr_var_init_bindings_b = machine_st.or_stack[b].attr_var_init_bindings_b;
+
+        machine_st.attr_var_init.backtrack(
+            attr_var_init_queue_b,
+            attr_var_init_bindings_b,
+        );
 
         machine_st.b = machine_st.or_stack[b].b;
         machine_st.or_stack.truncate(machine_st.b);
@@ -580,12 +586,14 @@ pub(crate) trait CallPolicy: Any {
 
         machine_st.heap.truncate(machine_st.or_stack[b].h);
 
-        let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
-        machine_st
-            .attr_var_init
-            .attr_var_queue
-            .truncate(attr_var_init_b);
+        let attr_var_init_queue_b = machine_st.or_stack[b].attr_var_init_queue_b;
+        let attr_var_init_bindings_b = machine_st.or_stack[b].attr_var_init_bindings_b;
 
+        machine_st.attr_var_init.backtrack(
+            attr_var_init_queue_b,
+            attr_var_init_bindings_b,
+        );
+        
         machine_st.b = machine_st.or_stack[b].b;
         machine_st.or_stack.truncate(machine_st.b);
 
index 9b913e83907660e9dcaefe422efe31c6b5f1fa45..f28eb077f3697d4ee7a66addfa28b8d38c40cfcc 100644 (file)
@@ -3300,6 +3300,7 @@ impl MachineState {
                     self.e,
                     self.cp.clone(),
                     self.attr_var_init.attr_var_queue.len(),
+                    self.attr_var_init.bindings.len(),
                     self.b,
                     self.p.clone() + 1,
                     self.tr,
@@ -3339,6 +3340,7 @@ impl MachineState {
                     self.e,
                     self.cp.clone(),
                     self.attr_var_init.attr_var_queue.len(),
+                    self.attr_var_init.bindings.len(),
                     self.b,
                     self.p.clone() + offset,
                     self.tr,
index edde5722a967211c147cea6d4c370922916e753d..8cf0f884afcc2cdd4ef6706f23174cea55310820 100644 (file)
@@ -8,7 +8,8 @@ pub struct Frame {
     pub global_index: usize,
     pub e: usize,
     pub cp: LocalCodePtr,
-    pub attr_var_init_b: usize,
+    pub attr_var_init_queue_b: usize,
+    pub attr_var_init_bindings_b: usize,
     pub b: usize,
     pub bp: CodePtr,
     pub tr: usize,
@@ -23,7 +24,8 @@ impl Frame {
         global_index: usize,
         e: usize,
         cp: LocalCodePtr,
-        attr_var_init_b: usize,
+        attr_var_init_queue_b: usize,
+        attr_var_init_bindings_b: usize,
         b: usize,
         bp: CodePtr,
         tr: usize,
@@ -36,7 +38,8 @@ impl Frame {
             global_index,
             e,
             cp,
-            attr_var_init_b,
+            attr_var_init_queue_b,
+            attr_var_init_bindings_b,
             b,
             bp,
             tr,
@@ -64,7 +67,8 @@ impl OrStack {
         global_index: usize,
         e: usize,
         cp: LocalCodePtr,
-        attr_var_init_b: usize,
+        attr_var_init_queue_b: usize,
+        attr_var_init_bindings_b: usize,
         b: usize,
         bp: CodePtr,
         tr: usize,
@@ -77,7 +81,8 @@ impl OrStack {
             global_index,
             e,
             cp,
-            attr_var_init_b,
+            attr_var_init_queue_b,
+            attr_var_init_bindings_b,
             b,
             bp,
             tr,
index 51eb93faefab620ebf5f420688051d6b76907d97..634335544b4fbbc245deb383015e215d1250eafc 100644 (file)
@@ -44,8 +44,7 @@
     ),
     (  '$get_b_value'(B), call(Term), '$write_eqs_and_read_input'(B, VarList), !
     ;  write('false.'), nl
-    ),
-    '$reset_attr_var_state'.
+    ).
 
 '$needs_bracketing'(Value, Op) :-
     catch((functor(Value, F, _),