From: Mark Thom Date: Fri, 16 Dec 2022 06:26:36 +0000 (-0700) Subject: detect cyclic bindings in attr_vars_of_term (#1666) X-Git-Tag: v0.9.2~250 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=0a8fc70ba9c70d8f4617182c92c5d232ef0f648f;p=scryer-prolog.git detect cyclic bindings in attr_vars_of_term (#1666) --- diff --git a/src/machine/attributed_variables.pl b/src/machine/attributed_variables.pl index 8c656e31..982ec495 100644 --- a/src/machine/attributed_variables.pl +++ b/src/machine/attributed_variables.pl @@ -1,6 +1,5 @@ :- module('$atts', []). - driver(Vars, Values) :- iterate(Vars, Values, ListOfListsOfGoalLists), !, diff --git a/src/machine/attributed_variables.rs b/src/machine/attributed_variables.rs index f74d3981..b11cf34c 100644 --- a/src/machine/attributed_variables.rs +++ b/src/machine/attributed_variables.rs @@ -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); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index be24526e..c70c4dec 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -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);