detect cyclic bindings in attr_vars_of_term (#1666)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
:- module('$atts', []).
|
||||
|
||||
|
||||
driver(Vars, Values) :-
|
||||
iterate(Vars, Values, ListOfListsOfGoalLists),
|
||||
!,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user