detect cyclic bindings in attr_vars_of_term (#1666)

This commit is contained in:
Mark Thom
2022-12-15 23:26:36 -07:00
parent b4b72a3166
commit 0a8fc70ba9
3 changed files with 88 additions and 79 deletions

View File

@@ -1,6 +1,5 @@
:- module('$atts', []). :- module('$atts', []).
driver(Vars, Values) :- driver(Vars, Values) :-
iterate(Vars, Values, ListOfListsOfGoalLists), iterate(Vars, Values, ListOfListsOfGoalLists),
!, !,

View File

@@ -147,6 +147,16 @@ impl MachineState {
let value = unmark_cell_bits!(value); 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_vars.push(value);
seen_set.insert(h); seen_set.insert(h);

View 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)] #[inline(always)]
pub(crate) fn dynamic_module_resolution( pub(crate) fn dynamic_module_resolution(
&mut self, &mut self,
@@ -3473,19 +3408,6 @@ impl Machine {
Ok((module_name, key)) 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)] #[inline(always)]
pub(crate) fn get_next_db_ref(&mut self) { pub(crate) fn get_next_db_ref(&mut self) {
let a1 = self.deref_register(1); 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)] #[inline(always)]
pub(crate) fn get_continuation_chunk(&mut self) { pub(crate) fn get_continuation_chunk(&mut self) {
let e = self.deref_register(1); let e = self.deref_register(1);