]> Repositorios git - scryer-prolog.git/commitdiff
further improvements to cyclic partial list printing (#2635)
authorMark Thom <[email protected]>
Sat, 23 Aug 2025 18:51:56 +0000 (11:51 -0700)
committerMark Thom <[email protected]>
Sat, 23 Aug 2025 20:23:39 +0000 (13:23 -0700)
13 files changed:
build/instructions_template.rs
src/functor_macro.rs
src/heap_iter.rs
src/heap_print.rs
src/machine/code_walker.rs
src/machine/cycle_detection.rs
src/machine/disjuncts.rs
src/machine/loader.rs
src/machine/machine_indices.rs
src/machine/preprocessor.rs
src/macros.rs
src/parser/char_reader.rs
src/types.rs

index 91144ea9be31e8a4f3ce805427ca344024cb0da4..65fc971e94e182b3e8513ac7ec54fb11e5d5bde7 100644 (file)
@@ -16,7 +16,7 @@ use to_syn_value_derive::ToDeriveInput;
  * of Instruction. They mimick most of the structure of the previous
  * Line instruction type. The strum crate is used to provide reflection
  * on each of the node types to the tree walker.
- */
+*/
 
 use std::any::*;
 use std::rc::Rc;
index 591fa1856eadc21fd9d070b8a3eb0ca322a0f004..88e5a5a2910248de1e3ddfcb86bf74c4b2d8d24f 100644 (file)
@@ -30,7 +30,7 @@ macro_rules! count {
  * in round parentheses for rustc to parse them. See the tests module
  * below for examples, especially those involving atom!
  * subexpressions.
- */
+*/
 
 macro_rules! functor {
     ($name:expr) => ({
index 7726b49b7798f2d397553766039b9f09f269a2f6..a57101b93aae6ed0739b0b85538337d7ca9059f9 100644 (file)
@@ -28,7 +28,7 @@ pub fn eager_stackful_preorder_iter(
  * cyclic terms for the sake of skipping them at the second visit but
  * leaves them marked until it is dropped. This makes for, e.g., more
  * efficient ground/1 and term_variables/2 definitions.
- */
+*/
 
 pub struct EagerStackfulPreOrderHeapIter<'a> {
     start_value: HeapCellValue,
@@ -175,7 +175,7 @@ impl IterStackLoc {
     }
 
     #[inline]
-    fn mark_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self {
+    pub fn marked_loc(h: usize, heap_or_stack: HeapOrStackTag) -> Self {
         IterStackLoc::new()
             .with_tag(IterStackLocTag::Marked)
             .with_heap_or_stack(heap_or_stack)
@@ -183,7 +183,7 @@ impl IterStackLoc {
     }
 
     #[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()
             .with_tag(IterStackLocTag::PendingMark)
             .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() {
             if h.is_pending_mark() {
                 self.push_if_unmarked(h);
-                self.stack.push(IterStackLoc::mark_loc(
+                self.stack.push(IterStackLoc::marked_loc(
                     h.value() as usize,
                     h.heap_or_stack(),
                 ));
@@ -414,7 +414,7 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
                    let loc = IterStackLoc::iterable_loc(vh, HeapOrStackTag::Heap);
 
                    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) => {
                    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.stack.push(IterStackLoc::pending_mark_loc(vh + 1, HeapOrStackTag::Heap));
-                   self.stack.push(IterStackLoc::mark_loc(vh, HeapOrStackTag::Heap));
+                   self.stack.push(IterStackLoc::pending_marked_loc(vh + 1, HeapOrStackTag::Heap));
+                   self.stack.push(IterStackLoc::marked_loc(vh, HeapOrStackTag::Heap));
 
                    return Some(self.read_cell(h));
                }
@@ -438,14 +438,14 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
 
                    self.forward_if_referent_marked(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) => {
                    let loc = IterStackLoc::iterable_loc(vs, HeapOrStackTag::Stack);
 
                    self.forward_if_referent_marked(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) => {
                    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::pending_mark_loc(tail_idx, HeapOrStackTag::Heap));
+                   self.stack.push(IterStackLoc::pending_marked_loc(tail_idx, HeapOrStackTag::Heap));
 
                    return Some(cell);
                }
@@ -469,14 +469,14 @@ impl<'a, ElideLists: ListElisionPolicy> StackfulPreOrderHeapIter<'a, ElideLists>
                    let l = h.value() as usize;
 
                    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 {
                        let first_arg_loc = IterStackLoc::iterable_loc(l+1, HeapOrStackTag::Heap);
 
                        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);
                    }
 
index d1d7bdb4e6b25b258fb57f49658cb0773e98562c..9e2ffb405aee5636f037e1dfdb2655c921ab3ef2 100644 (file)
@@ -849,10 +849,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         if let Some(mut orig_cell) = self.iter.next() {
             loop {
                 let is_cyclic = orig_cell.get_forwarding_bit();
-
-                let cell =
-                    heap_bound_store(self.iter.heap, heap_bound_deref(self.iter.heap, orig_cell));
-                let cell = unmark_cell_bits!(cell);
+                let derefed_cell = heap_bound_deref(self.iter.heap, orig_cell);
+                let cell = unmark_cell_bits!(heap_bound_store(self.iter.heap, derefed_cell));
 
                 match self.var_names.get(&cell).cloned() {
                     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
                         // the current output, and return None. None
                         // short-circuits handle_heap_term.
-                        // self.iter.pop_stack();
-
                         let var_str = var.borrow().to_string();
 
                         push_space_if_amb!(self, &var_str, {
@@ -872,8 +868,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     }
                     var_opt => {
                         if is_cyclic && cell.is_compound(self.iter.heap) {
-                            // self-referential variables are marked "cyclic".
-
+                            // self-referential variables are marked "cyclic"
                             match var_opt {
                                 Some(var) => {
                                     // 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.
                                         self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
                                     } else {
-                                        debug_assert!(cell.is_ref());
-
-                                        let h = match cell.get_tag() {
-                                            HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc => {
+                                        let h = read_heap_cell!(derefed_cell,
+                                            (HeapCellValueTag::AttrVar | HeapCellValueTag::Var, h) => {
+                                                self.iter.heap[h].set_forwarding_bit(false);
+                                                h
+                                            }
+                                            (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
                                                 self.iter.focus().value() as usize
                                             }
-                                            _ => cell.get_value() as usize,
-                                        };
-
-                                        match cell.get_tag() {
-                                            HeapCellValueTag::Lis => {
-                                                self.state_stack
-                                                    .push(TokenOrRedirect::Atom(atom!("...")));
-                                                return None;
+                                            _ => {
+                                                cell.get_value() as usize
                                             }
-                                            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(
-                                            h,
-                                            HeapOrStackTag::Heap,
-                                        ));
-
-                                        if let Some(cell) = self.iter.next() {
-                                            orig_cell = cell;
+                                            orig_cell = next_cell;
                                             continue;
                                         }
 
@@ -933,7 +955,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                 }
             }
         } else {
-            while self.iter.pop_stack().is_none() {}
+            while self.iter.pop_stack().is_some() {}
             None
         }
     }
@@ -1414,7 +1436,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
             .push(TokenOrRedirect::FunctorRedirect(max_depth));
         self.state_stack.push(TokenOrRedirect::HeadTailSeparator); // bar
         self.state_stack
-            .push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
+            .push(TokenOrRedirect::FunctorRedirect(max_depth));
 
         self.open_list(switch);
     }
@@ -1603,15 +1625,19 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
 
                 self.state_stack.push(TokenOrRedirect::Char(c));
             } else {
+                self.iter.pop_stack();
+
                 self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
                 self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
             }
         } else if self.max_depth_exhausted(max_depth) {
+            self.iter.pop_stack();
+
             self.state_stack.push(TokenOrRedirect::Atom(atom!("...")));
             self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
         } else {
             self.state_stack
-                .push(TokenOrRedirect::FunctorRedirect(max_depth + 1));
+                .push(TokenOrRedirect::FunctorRedirect(max_depth));
             self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
         }
     }
index 84f4cc935db6e24384fff32fbe740bff26670d15..1cbfde8b8757f64159c83fd1dd99f38e8f8b741f 100644 (file)
@@ -41,7 +41,7 @@ fn capture_offset(line: &Instruction, index: usize, stack: &mut Vec<usize>) -> b
 /* This function walks the code of a single predicate, supposed to
  * begin in code at the offset p. Each instruction is passed to the
  * walker function.
- */
+*/
 pub(crate) fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Instruction)) {
     let mut stack = vec![p];
     let mut visited_indices = IndexSet::with_hasher(FxBuildHasher::default());
index a800a9b6c6db80046ef50929ad0c1cd23e94793f..25c24ea28fd220985644777efa7d782c1e51bb34 100644 (file)
@@ -19,7 +19,7 @@ use crate::types::*;
  * Commonalities with the GC marking algorithm:
  * - The contents of forwarded cells are modified only when they are unforwarded
  * - Marked (but unforwarded!) cells immediately shift to the backward phase
- */
+*/
 
 #[derive(Debug)]
 pub(crate) struct CycleDetectingIter<'a, const STOP_AT_CYCLES: bool> {
index 4ecac7bca2415e06f42b5f3992f1f6b3b0442f8c..49cf8c1455b93afa001b4b77561d96d8b6b8006f 100644 (file)
@@ -18,7 +18,7 @@ use std::collections::VecDeque;
 use std::hash::{Hash, Hasher};
 use std::ops::{Deref, DerefMut};
 
-#[derive(Debug, Clone)] //, PartialOrd, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone)]//, PartialOrd, PartialEq, Eq, Hash)]
 pub struct BranchNumber {
     branch_num: Rational,
     delta: Rational,
index 4906ce533aa93efbb1f7423feb08fd67234a8d3a..6efe1984dd509b0defbf0d559f17548b5943cd43 100644 (file)
@@ -46,7 +46,7 @@ use std::rc::Rc;
  * loader fail later, all changes must be rolled back, restoring the
  * WAM to its prior state. Retraction records describe individual changes
  * made by the loader, and they may be used later.
- */
+*/
 
 #[derive(Debug)]
 pub(crate) enum RetractionRecord {
@@ -108,7 +108,7 @@ pub(crate) enum RetractionRecord {
  * "extent" of a code vector is its length prior to an attempted
  * module load. The only code vector of the WAM's IndexStore, "code",
  * is shared by all modules, including the default "user" module.
- */
+*/
 
 pub(super) struct RetractionInfo {
     orig_code_extent: usize,
index 7f7bfe35eb705f55a6574229579aa8afa666a41e..8a0b6d4161e3c6e6fc0df0abddbf74a8b94d3f5c 100644 (file)
@@ -136,7 +136,7 @@ impl IndexPtr {
     }
 }
 
-#[derive(Debug, Clone, Copy)] // , Ord, Hash, PartialOrd, Eq, PartialEq)]
+#[derive(Debug, Clone, Copy)]// , Ord, Hash, PartialOrd, Eq, PartialEq)]
 pub struct CodeIndex(CodeIndexOffset);
 
 #[cfg(target_pointer_width = "32")]
index dc1ede622c7ad6f0428bf0c95ad0a3f6e1b32ad9..2968d66d4ad65b71f5b6601b523becfd4d1aafda 100644 (file)
@@ -246,7 +246,7 @@ fn setup_qualified_import(mut terms: Vec<Term>) -> Result<UseModuleExport, Compi
  * +    (mode declarations under the mode syntax, which currently have no effect)
  * -
  * ?
- */
+*/
 
 fn setup_meta_predicate<'a, LS: LoadState<'a>>(
     mut terms: Vec<Term>,
index 79470f1889c91788e640c1ce72472642f689477b..0bf7b6afc0d5b2e0fe20e0d9e3a89c2c398552f9 100644 (file)
@@ -1,6 +1,6 @@
 /* A simple macro to count the arguments in a variadic list
  * of token trees.
- */
+*/
 
 macro_rules! char_as_cell {
     ($c: expr) => {
index b1c20060dedc85864d8740a6a573e997ab58b78c..4d5d7d7477e2587c5f744497a11d28fa69ee7723 100644 (file)
@@ -8,7 +8,7 @@
  * wrapping it a Bytes struct.
  *
  * Unlike BufReader, its buffer is peekable as a char.
- */
+*/
 
 use smallvec::*;
 
index 60b3b13235055fff46c6f5cbd1f6a4444dc1b734..1564edeb55d65950b777f383605538c874affd80 100644 (file)
@@ -197,7 +197,7 @@ pub enum TrailRef {
     BlackboardOffset(Atom, HeapCellValue), // key atom, key value
 }
 
-#[allow(clippy::enum_variant_names)] // allow the common "Trailed" prefix
+#[allow(clippy::enum_variant_names)]// allow the common "Trailed" prefix
 #[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
 #[bits = 6]
 pub(crate) enum TrailEntryTag {