fix is_cyclic_term (#864)
This commit is contained in:
@@ -1750,28 +1750,57 @@ impl MachineState {
|
|||||||
let mut seen = IndexSet::new();
|
let mut seen = IndexSet::new();
|
||||||
let mut fail = false;
|
let mut fail = false;
|
||||||
let mut iter = self.pre_order_iter(addr);
|
let mut iter = self.pre_order_iter(addr);
|
||||||
|
let mut parent_stack = vec![];
|
||||||
|
|
||||||
let is_composite = |addr: &Addr| match *addr {
|
let is_composite = |addr: Addr| match addr {
|
||||||
Addr::Str(_) | Addr::Lis(_) | Addr::PStrLocation(..) => true,
|
Addr::Str(_) | Addr::Lis(_) | Addr::PStrLocation(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
'outer: loop {
|
||||||
if let Some(addr) = iter.stack().last() {
|
if let Some(addr) = iter.stack().last().cloned() {
|
||||||
|
let addr = self.store(self.deref(addr));
|
||||||
|
|
||||||
if is_composite(addr) {
|
if is_composite(addr) {
|
||||||
if !seen.contains(addr) {
|
if !seen.contains(&addr) {
|
||||||
seen.insert(*addr);
|
seen.insert(addr);
|
||||||
} else {
|
} else {
|
||||||
|
// when we again encounter a seen composite
|
||||||
|
// term, check that it precedes itself as a
|
||||||
|
// parent in the post-order traversal. in the
|
||||||
|
// future, when value cells have mark bits,
|
||||||
|
// use them to designate parenthood instead of
|
||||||
|
// this linear search.
|
||||||
|
|
||||||
|
for (_, prec_addr) in parent_stack.iter().rev().cloned() {
|
||||||
|
if prec_addr == addr {
|
||||||
fail = true;
|
fail = true;
|
||||||
break;
|
break 'outer;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
iter.stack().pop();
|
}
|
||||||
|
|
||||||
|
let arity = match addr {
|
||||||
|
Addr::Str(h) => match &self.heap[h] {
|
||||||
|
&HeapCellValue::NamedStr(arity, ..) => arity,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
_ => 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
parent_stack.push((arity, addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if iter.next().is_none() {
|
if iter.next().is_none() {
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
while let Some((rem_children, addr)) = parent_stack.pop() {
|
||||||
|
if rem_children > 0 {
|
||||||
|
parent_stack.push((rem_children - 1, addr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user