0.pre7.86.flaky7.2:
[sbcl.git] / src / code / pprint.lisp
index 66b5d60..2067b07 100644 (file)
 ;;;; pretty streams
 
 ;;; There are three different units for measuring character positions:
-;;;  COLUMN - offset (if characters) from the start of the current line.
-;;;  INDEX - index into the output buffer.
-;;;  POSN - some position in the stream of characters cycling through
-;;;         the output buffer.
+;;;  COLUMN - offset (if characters) from the start of the current line
+;;;  INDEX  - index into the output buffer
+;;;  POSN   - some position in the stream of characters cycling through
+;;;          the output buffer
 (deftype column ()
   '(and fixnum unsigned-byte))
 ;;; The INDEX type is picked up from the kernel package.
 
 (defconstant default-line-length 80)
 
-(defstruct (pretty-stream (:include sb!kernel:lisp-stream
+(defstruct (pretty-stream (:include sb!kernel:ansi-stream
                                    (:out #'pretty-out)
                                    (:sout #'pretty-sout)
                                    (:misc #'pretty-misc))
-                         (:constructor make-pretty-stream (target)))
+                         (:constructor make-pretty-stream (target))
+                         (:copier nil))
   ;; Where the output is going to finally go.
-  (target (required-argument) :type stream)
+  (target (missing-arg) :type stream)
   ;; Line length we should format to. Cached here so we don't have to keep
   ;; extracting it from the target stream.
   (line-length (or *print-right-margin*
   ;; zero, but if we end up with a very long line with no breaks in it we
   ;; might have to output part of it. Then this will no longer be zero.
   (buffer-start-column (or (sb!impl::charpos target) 0) :type column)
-  ;; The line number we are currently on. Used for *print-lines* abrevs and
-  ;; to tell when sections have been split across multiple lines.
+  ;; The line number we are currently on. Used for *PRINT-LINES*
+  ;; abbreviations and to tell when sections have been split across
+  ;; multiple lines.
   (line-number 0 :type index)
+  ;; the value of *PRINT-LINES* captured at object creation time. We
+  ;; use this, instead of the dynamic *PRINT-LINES*, to avoid
+  ;; weirdness like
+  ;;   (let ((*print-lines* 50))
+  ;;     (pprint-logical-block ..
+  ;;       (dotimes (i 10)
+  ;;         (let ((*print-lines* 8))
+  ;;           (print (aref possiblybigthings i) prettystream)))))
+  ;; terminating the output of the entire logical blockafter 8 lines.
+  (print-lines *print-lines* :type (or index null) :read-only t)
   ;; Stack of logical blocks in effect at the buffer start.
   (blocks (list (make-logical-block)) :type list)
   ;; Buffer holding the per-line prefix active at the buffer start.
   (declare (type posn posn) (type pretty-stream stream)
           (values posn))
   (index-column (posn-index posn stream) stream))
+
+;;; Is it OK to do pretty printing on this stream at this time?
+(defun print-pretty-on-stream-p (stream)
+  (and (pretty-stream-p stream)
+       *print-pretty*))
 \f
 ;;;; stream interface routines
 
 \f
 ;;;; logical blocks
 
-(defstruct logical-block
+(defstruct (logical-block (:copier nil))
   ;; The column this logical block started in.
   (start-column 0 :type column)
   ;; The column the current section started in.
 \f
 ;;;; the pending operation queue
 
-(defstruct (queued-op (:constructor nil))
+(defstruct (queued-op (:constructor nil)
+                     (:copier nil))
   (posn 0 :type posn))
 
 (defmacro enqueue (stream type &rest args)
-  (let ((constructor (intern (concatenate 'string
-                                         "MAKE-"
-                                         (symbol-name type)))))
+  (let ((constructor (symbolicate "MAKE-" type)))
     (once-only ((stream stream)
                (entry `(,constructor :posn
                                      (index-posn
         ,entry))))
 
 (defstruct (section-start (:include queued-op)
-                         (:constructor nil))
+                         (:constructor nil)
+                         (:copier nil))
   (depth 0 :type index)
   (section-end nil :type (or null newline block-end)))
 
-(defstruct (newline
-           (:include section-start))
-  (kind (required-argument)
+(defstruct (newline (:include section-start)
+                   (:copier nil))
+  (kind (missing-arg)
        :type (member :linear :fill :miser :literal :mandatory)))
 
 (defun enqueue-newline (stream kind)
        (setf (section-start-section-end entry) newline))))
   (maybe-output stream (or (eq kind :literal) (eq kind :mandatory))))
 
-(defstruct (indentation
-           (:include queued-op))
-  (kind (required-argument) :type (member :block :current))
+(defstruct (indentation (:include queued-op)
+                       (:copier nil))
+  (kind (missing-arg) :type (member :block :current))
   (amount 0 :type fixnum))
 
 (defun enqueue-indent (stream kind amount)
   (enqueue stream indentation :kind kind :amount amount))
 
-(defstruct (block-start
-           (:include section-start))
+(defstruct (block-start (:include section-start)
+                       (:copier nil))
   (block-end nil :type (or null block-end))
   (prefix nil :type (or null simple-string))
   (suffix nil :type (or null simple-string)))
     (setf (pretty-stream-pending-blocks stream)
          (cons start pending-blocks))))
 
-(defstruct (block-end
-           (:include queued-op))
+(defstruct (block-end (:include queued-op)
+                     (:copier nil))
   (suffix nil :type (or null simple-string)))
 
 (defun end-logical-block (stream)
       (pretty-sout stream suffix 0 (length suffix)))
     (setf (block-start-block-end start) end)))
 
-(defstruct (tab
-           (:include queued-op))
+(defstruct (tab (:include queued-op)
+               (:copier nil))
   (sectionp nil :type (member t nil))
   (relativep nil :type (member t nil))
   (colnum 0 :type column)
 
 (defun fits-on-line-p (stream until force-newlines-p)
   (let ((available (pretty-stream-line-length stream)))
-    (when (and (not *print-readably*) *print-lines*
-              (= *print-lines* (pretty-stream-line-number stream)))
+    (when (and (not *print-readably*)
+              (pretty-stream-print-lines stream)
+              (= (pretty-stream-print-lines stream)
+                 (pretty-stream-line-number stream)))
       (decf available 3) ; for the `` ..''
       (decf available (logical-block-suffix-length
                       (car (pretty-stream-blocks stream)))))
     (let ((line-number (pretty-stream-line-number stream)))
       (incf line-number)
       (when (and (not *print-readably*)
-                *print-lines* (>= line-number *print-lines*))
+                (pretty-stream-print-lines stream)
+                (>= line-number (pretty-stream-print-lines stream)))
        (write-string " .." target)
        (let ((suffix-length (logical-block-suffix-length
                              (car (pretty-stream-blocks stream)))))
                  ((t) *terminal-io*)
                  ((nil) *standard-output*)
                  (t stream))))
-    (when (pretty-stream-p stream)
+    (when (print-pretty-on-stream-p stream)
       (enqueue-newline stream kind)))
   nil)
 
                  ((t) *terminal-io*)
                  ((nil) *standard-output*)
                  (t stream))))
-    (when (pretty-stream-p stream)
+    (when (print-pretty-on-stream-p stream)
       (enqueue-indent stream relative-to n)))
   nil)
 
                  ((t) *terminal-io*)
                  ((nil) *standard-output*)
                  (t stream))))
-    (when (pretty-stream-p stream)
+    (when (print-pretty-on-stream-p stream)
       (enqueue-tab stream kind colnum colinc)))
   nil)
 
 (defvar *initial-pprint-dispatch*)
 (defvar *building-initial-table* nil)
 
-(defstruct pprint-dispatch-entry
-  ;; The type specifier for this entry.
-  (type (required-argument) :type t)
-  ;; A function to test to see whether an object is of this time. Pretty must
-  ;; just (lambda (obj) (typep object type)) except that we handle the
-  ;; CONS type specially so that (cons (member foo)) works. We don't
-  ;; bother computing this for entries in the CONS hash table, because
-  ;; we don't need it.
+(defstruct (pprint-dispatch-entry (:copier nil))
+  ;; the type specifier for this entry
+  (type (missing-arg) :type t)
+  ;; a function to test to see whether an object is of this time.
+  ;; Pretty must just (LAMBDA (OBJ) (TYPEP OBJECT TYPE)) except that
+  ;; we handle the CONS type specially so that (CONS (MEMBER FOO))
+  ;; works. We don't bother computing this for entries in the CONS
+  ;; hash table, because we don't need it.
   (test-fn nil :type (or function null))
-  ;; The priority for this guy.
+  ;; the priority for this guy
   (priority 0 :type real)
   ;; T iff one of the original entries.
   (initial-p *building-initial-table* :type (member t nil))
-  ;; And the associated function.
-  (function (required-argument) :type function))
+  ;; and the associated function
+  (function (missing-arg) :type function))
 (def!method print-object ((entry pprint-dispatch-entry) stream)
   (print-unreadable-object (entry stream :type t)
     (format stream "type=~S, priority=~S~@[ [initial]~]"
            (pprint-dispatch-entry-priority entry)
            (pprint-dispatch-entry-initial-p entry))))
 
-(defstruct pprint-dispatch-table
+(defstruct (pprint-dispatch-table (:copier nil))
   ;; A list of all the entries (except for CONS entries below) in highest
   ;; to lowest priority.
   (entries nil :type list)
       (let ((expr (compute-test-expr type 'object)))
        (cond ((cdr (assoc expr *precompiled-pprint-dispatch-funs*
                           :test #'equal)))
-             ((fboundp 'compile)
-              (compile nil `(lambda (object) ,expr)))
-             (was-cons
-              (warn "CONS PPRINT dispatch ignored w/o compiler loaded:~%  ~S"
-                    type)
-              #'(lambda (object) (declare (ignore object)) nil))
              (t
-              (let ((ttype (sb!kernel:specifier-type type)))
-                #'(lambda (object) (sb!kernel:%typep object ttype)))))))))
+              (compile nil `(lambda (object) ,expr))))))))
 
 (defun copy-pprint-dispatch (&optional (table *print-pprint-dispatch*))
   (declare (type (or pprint-dispatch-table null) table))
            (when (funcall (pprint-dispatch-entry-test-fn entry) object)
              (return entry)))))
     (if entry
-       (values (pprint-dispatch-entry-function entry) t)
+       (values (pprint-dispatch-entry-fun entry) t)
        (values #'(lambda (stream object)
                    (output-ugly-object object stream))
                nil))))
             (stringp array)
             (bit-vector-p array))
         (output-ugly-object array stream))
-       ((and *print-readably* (not (eq (array-element-type array) 't)))
+       ((and *print-readably* (not (eq (array-element-type array) t)))
         (let ((*print-readably* nil))
           (error 'print-not-readable :object array)))
        ((vectorp array)