further improvements to cyclic partial list printing (#2635)
This commit is contained in:
@@ -175,7 +175,7 @@ impl IterStackLoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mark_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self {
|
pub fn marked_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self {
|
||||||
IterStackLoc::new()
|
IterStackLoc::new()
|
||||||
.with_tag(IterStackLocTag::Marked)
|
.with_tag(IterStackLocTag::Marked)
|
||||||
.with_heap_or_stack(heap_or_stack)
|
.with_heap_or_stack(heap_or_stack)
|
||||||
@@ -183,7 +183,7 @@ impl IterStackLoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pending_mark_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self {
|
fn pending_marked_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self {
|
||||||
IterStackLoc::new()
|
IterStackLoc::new()
|
||||||
.with_tag(IterStackLocTag::PendingMark)
|
.with_tag(IterStackLocTag::PendingMark)
|
||||||
.with_heap_or_stack(heap_or_stack)
|
.with_heap_or_stack(heap_or_stack)
|
||||||
@@ -386,7 +386,7 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
|||||||
while let Some(h) = self.stack.pop() {
|
while let Some(h) = self.stack.pop() {
|
||||||
if h.is_pending_mark() {
|
if h.is_pending_mark() {
|
||||||
self.push_if_unmarked(h);
|
self.push_if_unmarked(h);
|
||||||
self.stack.push(IterStackLoc::mark_loc(
|
self.stack.push(IterStackLoc::marked_loc(
|
||||||
h.value() as usize,
|
h.value() as usize,
|
||||||
h.heap_or_stack(),
|
h.heap_or_stack(),
|
||||||
));
|
));
|
||||||
@@ -414,7 +414,7 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
|||||||
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
||||||
|
|
||||||
self.push_if_unmarked(loc);
|
self.push_if_unmarked(loc);
|
||||||
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::marked_loc(vh, HeapOrStackTag::Heap));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Lis, vh) => {
|
(HeapCellValueTag::Lis, vh) => {
|
||||||
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
|
||||||
@@ -428,8 +428,8 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
|||||||
|
|
||||||
self.push_if_unmarked(loc);
|
self.push_if_unmarked(loc);
|
||||||
|
|
||||||
self.stack.push(IterStackLoc::pending_mark_loc(vh + 1, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::pending_marked_loc(vh + 1, HeapOrStackTag::Heap));
|
||||||
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::marked_loc(vh, HeapOrStackTag::Heap));
|
||||||
|
|
||||||
return Some(self.read_cell(h));
|
return Some(self.read_cell(h));
|
||||||
}
|
}
|
||||||
@@ -438,14 +438,14 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
|||||||
|
|
||||||
self.forward_if_referent_marked(loc);
|
self.forward_if_referent_marked(loc);
|
||||||
self.push_if_unmarked(loc);
|
self.push_if_unmarked(loc);
|
||||||
self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::marked_loc(vh, HeapOrStackTag::Heap));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::StackVar, vs) => {
|
(HeapCellValueTag::StackVar, vs) => {
|
||||||
let loc = IterStackLoc::iterable_loc(vs, HeapOrStackTag::Stack);
|
let loc = IterStackLoc::iterable_loc(vs, HeapOrStackTag::Stack);
|
||||||
|
|
||||||
self.forward_if_referent_marked(loc);
|
self.forward_if_referent_marked(loc);
|
||||||
self.push_if_unmarked(loc);
|
self.push_if_unmarked(loc);
|
||||||
self.stack.push(IterStackLoc::mark_loc(vs, HeapOrStackTag::Stack));
|
self.stack.push(IterStackLoc::marked_loc(vs, HeapOrStackTag::Stack));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::PStrLoc, vh) => {
|
(HeapCellValueTag::PStrLoc, vh) => {
|
||||||
let cell = *cell;
|
let cell = *cell;
|
||||||
@@ -461,7 +461,7 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.stack.push(IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::iterable_loc(tail_idx - 1, HeapOrStackTag::Heap));
|
||||||
self.stack.push(IterStackLoc::pending_mark_loc(tail_idx, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::pending_marked_loc(tail_idx, HeapOrStackTag::Heap));
|
||||||
|
|
||||||
return Some(cell);
|
return Some(cell);
|
||||||
}
|
}
|
||||||
@@ -469,14 +469,14 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
|
|||||||
let l = h.value() as usize;
|
let l = h.value() as usize;
|
||||||
|
|
||||||
for l in (l + 2 .. l + arity + 1).rev() {
|
for l in (l + 2 .. l + arity + 1).rev() {
|
||||||
self.stack.push(IterStackLoc::pending_mark_loc(l, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::pending_marked_loc(l, HeapOrStackTag::Heap));
|
||||||
}
|
}
|
||||||
|
|
||||||
if arity > 0 {
|
if arity > 0 {
|
||||||
let first_arg_loc = IterStackLoc::iterable_loc(l+1, HeapOrStackTag::Heap);
|
let first_arg_loc = IterStackLoc::iterable_loc(l+1, HeapOrStackTag::Heap);
|
||||||
|
|
||||||
self.push_if_unmarked(first_arg_loc);
|
self.push_if_unmarked(first_arg_loc);
|
||||||
self.stack.push(IterStackLoc::mark_loc(l+1, HeapOrStackTag::Heap));
|
self.stack.push(IterStackLoc::marked_loc(l+1, HeapOrStackTag::Heap));
|
||||||
self.forward_if_referent_marked(first_arg_loc);
|
self.forward_if_referent_marked(first_arg_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -849,10 +849,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
if let Some(mut orig_cell) = self.iter.next() {
|
if let Some(mut orig_cell) = self.iter.next() {
|
||||||
loop {
|
loop {
|
||||||
let is_cyclic = orig_cell.get_forwarding_bit();
|
let is_cyclic = orig_cell.get_forwarding_bit();
|
||||||
|
let derefed_cell = heap_bound_deref(self.iter.heap, orig_cell);
|
||||||
let cell =
|
let cell = unmark_cell_bits!(heap_bound_store(self.iter.heap, derefed_cell));
|
||||||
heap_bound_store(self.iter.heap, heap_bound_deref(self.iter.heap, orig_cell));
|
|
||||||
let cell = unmark_cell_bits!(cell);
|
|
||||||
|
|
||||||
match self.var_names.get(&cell).cloned() {
|
match self.var_names.get(&cell).cloned() {
|
||||||
Some(var) if cell.is_var() => {
|
Some(var) if cell.is_var() => {
|
||||||
@@ -860,8 +858,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
// a name via heap_locs, append the name to
|
// a name via heap_locs, append the name to
|
||||||
// the current output, and return None. None
|
// the current output, and return None. None
|
||||||
// short-circuits handle_heap_term.
|
// short-circuits handle_heap_term.
|
||||||
// self.iter.pop_stack();
|
|
||||||
|
|
||||||
let var_str = var.borrow().to_string();
|
let var_str = var.borrow().to_string();
|
||||||
|
|
||||||
push_space_if_amb!(self, &var_str, {
|
push_space_if_amb!(self, &var_str, {
|
||||||
@@ -872,8 +868,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
var_opt => {
|
var_opt => {
|
||||||
if is_cyclic && cell.is_compound(self.iter.heap) {
|
if is_cyclic && cell.is_compound(self.iter.heap) {
|
||||||
// self-referential variables are marked "cyclic".
|
// self-referential variables are marked "cyclic"
|
||||||
|
|
||||||
match var_opt {
|
match var_opt {
|
||||||
Some(var) => {
|
Some(var) => {
|
||||||
// If the term is bound to a named variable,
|
// If the term is bound to a named variable,
|
||||||
@@ -889,34 +884,61 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
// otherwise, contract it to an ellipsis.
|
// otherwise, contract it to an ellipsis.
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(cell.is_ref());
|
let h = read_heap_cell!(derefed_cell,
|
||||||
|
(HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
|
||||||
let h = match cell.get_tag() {
|
self.iter.heap[h].set_forwarding_bit(false);
|
||||||
HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc => {
|
h
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
|
||||||
self.iter.focus().value() as usize
|
self.iter.focus().value() as usize
|
||||||
}
|
}
|
||||||
_ => cell.get_value() as usize,
|
_ => {
|
||||||
};
|
cell.get_value() as usize
|
||||||
|
|
||||||
match cell.get_tag() {
|
|
||||||
HeapCellValueTag::Lis => {
|
|
||||||
self.state_stack
|
|
||||||
.push(TokenOrRedirect::Atom(atom!("...")));
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
HeapCellValueTag::PStrLoc => {
|
);
|
||||||
*max_depth -= 1;
|
|
||||||
|
let h = IterStackLoc::marked_loc(h, HeapOrStackTag::Heap);
|
||||||
|
self.iter.push_stack(h);
|
||||||
|
|
||||||
|
if let Some(next_cell) = self.iter.next() {
|
||||||
|
if next_cell.get_forwarding_bit() {
|
||||||
|
debug_assert_eq!(
|
||||||
|
cell.get_value(),
|
||||||
|
next_cell.get_value()
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* next_cell is forwarded here only if, for lists,
|
||||||
|
* X = [X|T]. in this case, self.iter has *not*
|
||||||
|
* pushed X's arguments to its stack, but T is
|
||||||
|
* at its top from the previous expansion of X.
|
||||||
|
*
|
||||||
|
* in this case, expand the iter stack rep to X =
|
||||||
|
* [[X|T]|T] and continue, terminating recursion
|
||||||
|
* when max_depth == 0.
|
||||||
|
*
|
||||||
|
* similar logic here for PStrLoc, which can only
|
||||||
|
* recurse from its tail.
|
||||||
|
*/
|
||||||
|
|
||||||
|
read_heap_cell!(next_cell,
|
||||||
|
(HeapCellValueTag::Lis, l) => {
|
||||||
|
let tail_h = IterStackLoc::marked_loc(l+1, HeapOrStackTag::Heap);
|
||||||
|
|
||||||
|
self.iter.push_stack(tail_h);
|
||||||
|
self.iter.push_stack(h);
|
||||||
|
|
||||||
|
return Some(unmark_cell_bits!(next_cell));
|
||||||
|
}
|
||||||
|
(HeapCellValueTag::PStrLoc) => {
|
||||||
|
self.iter.push_stack(h);
|
||||||
|
return Some(unmark_cell_bits!(next_cell));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.iter.push_stack(IterStackLoc::iterable_loc(
|
orig_cell = next_cell;
|
||||||
h,
|
|
||||||
HeapOrStackTag::Heap,
|
|
||||||
));
|
|
||||||
|
|
||||||
if let Some(cell) = self.iter.next() {
|
|
||||||
orig_cell = cell;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,7 +955,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while self.iter.pop_stack().is_none() {}
|
while self.iter.pop_stack().is_some() {}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1414,7 +1436,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
|
||||||
self.state_stack
|
self.state_stack
|
||||||
.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
|
.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
|
|
||||||
self.open_list(switch);
|
self.open_list(switch);
|
||||||
}
|
}
|
||||||
@@ -1603,15 +1625,19 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Char(c));
|
self.state_stack.push(TokenOrRedirect::Char(c));
|
||||||
} else {
|
} else {
|
||||||
|
self.iter.pop_stack();
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
||||||
}
|
}
|
||||||
} else if self.max_depth_exhausted(max_depth) {
|
} else if self.max_depth_exhausted(max_depth) {
|
||||||
|
self.iter.pop_stack();
|
||||||
|
|
||||||
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
|
||||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
||||||
} else {
|
} else {
|
||||||
self.state_stack
|
self.state_stack
|
||||||
.push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
|
.push(TokenOrRedirect::FunctorRedirect(max_depth));
|
||||||
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user