]> Repositorios git - scryer-prolog.git/commitdiff
detect cyclic bindings in attr_vars_of_term (#1666)
authorMark Thom <[email protected]>
Fri, 16 Dec 2022 06:26:36 +0000 (23:26 -0700)
committerMark Thom <[email protected]>
Fri, 16 Dec 2022 07:42:38 +0000 (00:42 -0700)
src/machine/attributed_variables.pl
src/machine/attributed_variables.rs
src/machine/system_calls.rs

index 8c656e310917b7b4bc749b335bd7ba1916df9510..982ec49566970e34619949c036d92c22fc97a6c9 100644 (file)
@@ -1,6 +1,5 @@
 :- module('$atts', []).
 
-
 driver(Vars, Values) :-
     iterate(Vars, Values, ListOfListsOfGoalLists),
     !,
index f74d398128490b3e998183571582b970cc295acc..b11cf34cff2a4c5d714b7d16740edc40470d0999 100644 (file)
@@ -147,6 +147,16 @@ impl MachineState {
 
                     let value = unmark_cell_bits!(value);
 
+                    if h != iter.focus() {
+                        let deref_value = heap_bound_store(iter.heap, heap_bound_deref(iter.heap, value));
+
+                        if deref_value.is_compound(iter.heap) {
+                            // a cyclic structure is bound to the attributed variable at h.
+                            // it mustn't be included in seen_vars.
+                            continue;
+                        }
+                    }
+
                     seen_vars.push(value);
                     seen_set.insert(h);
 
index be24526e866321d74c3c50f631a94390cf6f2231..c70c4decc98c433eb2896bfbb4fc734d4435e21a 100644 (file)
@@ -3354,71 +3354,6 @@ impl Machine {
         }
     }
 
-    #[inline(always)]
-    pub(crate) fn delete_attribute(&mut self) {
-        let ls0 = self.deref_register(1);
-
-        if let HeapCellValueTag::Lis = ls0.get_tag() {
-            let l1 = ls0.get_value();
-            let ls1 = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l1 + 1)));
-
-            if let HeapCellValueTag::Lis = ls1.get_tag() {
-                let l2 = ls1.get_value();
-
-                let old_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.heap[l1+1]));
-                let tail = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l2 + 1)));
-
-                let tail = if tail.is_var() {
-                    heap_loc_as_cell!(l1 + 1)
-                } else {
-                    tail
-                };
-
-                let trail_ref = read_heap_cell!(old_addr,
-                    (HeapCellValueTag::Var, h) => {
-                        TrailRef::AttrVarHeapLink(h)
-                    }
-                    (HeapCellValueTag::Lis, l) => {
-                        TrailRef::AttrVarListLink(l1 + 1, l)
-                    }
-                    _ => {
-                        unreachable!()
-                    }
-                );
-
-                self.machine_st.heap[l1 + 1] = tail;
-                self.machine_st.trail(trail_ref);
-            }
-        }
-    }
-
-    #[inline(always)]
-     pub(crate) fn delete_head_attribute(&mut self) {
-        let addr = self.deref_register(1);
-
-        debug_assert_eq!(addr.get_tag(), HeapCellValueTag::AttrVar);
-
-        let h = addr.get_value();
-        let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.heap[h + 1]));
-
-        debug_assert_eq!(addr.get_tag(), HeapCellValueTag::Lis);
-
-        let l = addr.get_value();
-        let tail = self.machine_st.store(self.machine_st.deref(self.machine_st.heap[l + 1]));
-
-        let tail = if tail.is_var() {
-            self.machine_st.heap[h] = heap_loc_as_cell!(h);
-            self.machine_st.trail(TrailRef::Ref(Ref::attr_var(h)));
-
-            heap_loc_as_cell!(h + 1)
-        } else {
-            tail
-        };
-
-        self.machine_st.heap[h + 1] = tail;
-        self.machine_st.trail(TrailRef::AttrVarListLink(h + 1, l));
-    }
-
     #[inline(always)]
     pub(crate) fn dynamic_module_resolution(
         &mut self,
@@ -3473,19 +3408,6 @@ impl Machine {
         Ok((module_name, key))
     }
 
-    #[inline(always)]
-    pub(crate) fn enqueue_attributed_var(&mut self) {
-        let addr = self.deref_register(1);
-
-        read_heap_cell!(addr,
-            (HeapCellValueTag::AttrVar, h) => {
-                self.machine_st.attr_var_init.attr_var_queue.push(h);
-            }
-            _ => {
-            }
-        );
-    }
-
     #[inline(always)]
     pub(crate) fn get_next_db_ref(&mut self) {
         let a1 = self.deref_register(1);
@@ -4308,6 +4230,84 @@ impl Machine {
         }
     }
 
+    #[inline(always)]
+    pub(crate) fn enqueue_attributed_var(&mut self) {
+        let addr = self.deref_register(1);
+
+        read_heap_cell!(addr,
+            (HeapCellValueTag::AttrVar, h) => {
+                self.machine_st.attr_var_init.attr_var_queue.push(h);
+            }
+            _ => {
+            }
+        );
+    }
+
+    #[inline(always)]
+    pub(crate) fn delete_attribute(&mut self) {
+        let ls0 = self.deref_register(1);
+
+        if let HeapCellValueTag::Lis = ls0.get_tag() {
+            let l1 = ls0.get_value();
+            let ls1 = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l1 + 1)));
+
+            if let HeapCellValueTag::Lis = ls1.get_tag() {
+                let l2 = ls1.get_value();
+
+                let old_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.heap[l1+1]));
+                let tail = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l2 + 1)));
+
+                let tail = if tail.is_var() {
+                    heap_loc_as_cell!(l1 + 1)
+                } else {
+                    tail
+                };
+
+                let trail_ref = read_heap_cell!(old_addr,
+                    (HeapCellValueTag::Var, h) => {
+                        TrailRef::AttrVarHeapLink(h)
+                    }
+                    (HeapCellValueTag::Lis, l) => {
+                        TrailRef::AttrVarListLink(l1 + 1, l)
+                    }
+                    _ => {
+                        unreachable!()
+                    }
+                );
+
+                self.machine_st.heap[l1 + 1] = tail;
+                self.machine_st.trail(trail_ref);
+            }
+        }
+    }
+
+    #[inline(always)]
+     pub(crate) fn delete_head_attribute(&mut self) {
+        let addr = self.deref_register(1);
+
+        debug_assert_eq!(addr.get_tag(), HeapCellValueTag::AttrVar);
+
+        let h = addr.get_value();
+        let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.heap[h + 1]));
+
+        debug_assert_eq!(addr.get_tag(), HeapCellValueTag::Lis);
+
+        let l = addr.get_value();
+        let tail = self.machine_st.store(self.machine_st.deref(self.machine_st.heap[l + 1]));
+
+        let tail = if tail.is_var() {
+            self.machine_st.heap[h] = heap_loc_as_cell!(h);
+            self.machine_st.trail(TrailRef::Ref(Ref::attr_var(h)));
+
+            heap_loc_as_cell!(h + 1)
+        } else {
+            tail
+        };
+
+        self.machine_st.heap[h + 1] = tail;
+        self.machine_st.trail(TrailRef::AttrVarListLink(h + 1, l));
+    }
+
     #[inline(always)]
     pub(crate) fn get_continuation_chunk(&mut self) {
         let e = self.deref_register(1);