0.8.20.1: fun-name fun, debugger debugged
[sbcl.git] / src / code / pprint.lisp
index baf4088..bc26510 100644 (file)
@@ -44,7 +44,7 @@
               :type column)
   ;; A simple string holding all the text that has been output but not yet
   ;; printed.
-  (buffer (make-string initial-buffer-size) :type simple-string)
+  (buffer (make-string initial-buffer-size) :type (simple-array character (*)))
   ;; The index into BUFFER where more text should be put.
   (buffer-fill-pointer 0 :type index)
   ;; Whenever we output stuff from the buffer, we shift the remaining noise
   ;; Buffer holding the per-line prefix active at the buffer start.
   ;; Indentation is included in this. The length of this is stored
   ;; in the logical block stack.
-  (prefix (make-string initial-buffer-size) :type simple-string)
+  (prefix (make-string initial-buffer-size) :type (simple-array character (*)))
   ;; Buffer holding the total remaining suffix active at the buffer start.
   ;; The characters are right-justified in the buffer to make it easier
   ;; to output the buffer. The length is stored in the logical block
   ;; stack.
-  (suffix (make-string initial-buffer-size) :type simple-string)
+  (suffix (make-string initial-buffer-size) :type (simple-array character (*)))
   ;; Queue of pending operations. When empty, HEAD=TAIL=NIL. Otherwise,
   ;; TAIL holds the first (oldest) cons and HEAD holds the last (newest)
   ;; cons. Adding things to the queue is basically (setf (cdr head) (list
 
 (defun pretty-out (stream char)
   (declare (type pretty-stream stream)
-          (type base-char char))
+          (type character char))
   (cond ((char= char #\newline)
         (enqueue-newline stream :literal))
        (t
           (type simple-string string)
           (type index start)
           (type (or index null) end))
-  (let ((end (or end (length string))))
+  (let* ((string (if (typep string '(simple-array character (*)))
+                    string
+                    (coerce string '(simple-array character (*)))))
+        (end (or end (length string))))
     (unless (= start end)
       (let ((newline (position #\newline string :start start :end end)))
        (cond
 (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)))
+  (prefix nil :type (or null (simple-array character (*))))
+  (suffix nil :type (or null (simple-array character (*)))))
 
 (defun start-logical-block (stream prefix per-line-p suffix)
   ;; (In the PPRINT-LOGICAL-BLOCK form which calls us,
   ;; :PREFIX and :PER-LINE-PREFIX have hairy defaulting behavior,
   ;; and might end up being NIL.)
-  (declare (type (or null string prefix)))
+  (declare (type (or null string) prefix))
   ;; (But the defaulting behavior of PPRINT-LOGICAL-BLOCK :SUFFIX is
   ;; trivial, so it should always be a string.)
   (declare (type string suffix))
   (when prefix
+    (setq prefix (coerce prefix '(simple-array character (*))))
     (pretty-sout stream prefix 0 (length prefix)))
   (let* ((pending-blocks (pretty-stream-pending-blocks stream))
         (start (enqueue stream block-start
                         :prefix (and per-line-p prefix)
-                        :suffix suffix
+                        :suffix (coerce suffix '(simple-array character (*)))
                         :depth (length pending-blocks))))
     (setf (pretty-stream-pending-blocks stream)
          (cons start pending-blocks))))
 
 (defstruct (block-end (:include queued-op)
                      (:copier nil))
-  (suffix nil :type (or null simple-string)))
+  (suffix nil :type (or null (simple-array character (*)))))
 
 (defun end-logical-block (stream)
   (let* ((start (pop (pretty-stream-pending-blocks stream)))
 ;;;; tab support
 
 (defun compute-tab-size (tab section-start column)
-  (let ((origin (if (tab-sectionp tab) section-start 0))
-       (colnum (tab-colnum tab))
-       (colinc (tab-colinc tab)))
+  (let* ((origin (if (tab-sectionp tab) section-start 0))
+         (colnum (tab-colnum tab))
+         (colinc (tab-colinc tab))
+         (position (- column origin)))
     (cond ((tab-relativep tab)
           (unless (<= colinc 1)
-            (let ((newposn (+ column colnum)))
+            (let ((newposn (+ position colnum)))
               (let ((rem (rem newposn colinc)))
                 (unless (zerop rem)
                   (incf colnum (- colinc rem))))))
           colnum)
-         ((<= column (+ colnum origin))
-          (- (+ colnum origin) column))
-         (t
+         ((< position colnum)
+           (- colnum position))
+         ((zerop colinc) 0)
+          (t
           (- colinc
-             (rem (- column origin) colinc))))))
+             (rem (- position colnum) colinc))))))
 
 (defun index-column (index stream)
   (let ((column (pretty-stream-buffer-start-column stream))
    *STANDARD-OUTPUT*) if it is a pretty-printing stream, and do
    nothing if not. KIND can be one of:
      :LINEAR - A line break is inserted if and only if the immediatly
-       containing section cannot be printed on one line.
+        containing section cannot be printed on one line.
      :MISER - Same as LINEAR, but only if ``miser-style'' is in effect.
-       (See *PRINT-MISER-WIDTH*.)
+        (See *PRINT-MISER-WIDTH*.)
      :FILL - A line break is inserted if and only if either:
        (a) the following section cannot be printed on the end of the
-          current line,
+           current line,
        (b) the preceding section was not printed on a single line, or
        (c) the immediately containing section cannot be printed on one
-          line and miser-style is in effect.
+           line and miser-style is in effect.
      :MANDATORY - A line break is always inserted.
    When a line break is inserted by any type of conditional newline, any
    blanks that immediately precede the conditional newline are ommitted
   #!+sb-doc
   "Specify the indentation to use in the current logical block if STREAM
    (which defaults to *STANDARD-OUTPUT*) is it is a pretty-printing stream
-   and do nothing if not. (See PPRINT-LOGICAL-BLOCK.)  N is the indention
+   and do nothing if not. (See PPRINT-LOGICAL-BLOCK.)  N is the indentation
    to use (in ems, the width of an ``m'') and RELATIVE-TO can be either:
      :BLOCK - Indent relative to the column the current logical block
-       started on.
+        started on.
      :CURRENT - Indent relative to the current column.
-   The new indention value does not take effect until the following line
+   The new indentation value does not take effect until the following line
    break."
   (declare (type (member :block :current) relative-to)
-          (type integer n)
+          (type real n)
           (type (or stream (member t nil)) stream)
           (values null))
   (let ((stream (case stream
                  ((nil) *standard-output*)
                  (t stream))))
     (when (print-pretty-on-stream-p stream)
-      (enqueue-indent stream relative-to n)))
+      (enqueue-indent stream relative-to (truncate n))))
   nil)
 
 (defun pprint-tab (kind colnum colinc &optional stream)
   ;; T iff one of the original entries.
   (initial-p *building-initial-table* :type (member t nil))
   ;; and the associated function
-  (fun (missing-arg) :type function))
+  (fun (missing-arg) :type callable))
 (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 (:copier nil))
-  ;; A list of all the entries (except for CONS entries below) in highest
-  ;; to lowest priority.
-  (entries nil :type list)
-  ;; A hash table mapping things to entries for type specifiers of the
-  ;; form (CONS (MEMBER <thing>)). If the type specifier is of this form,
-  ;; we put it in this hash table instead of the regular entries table.
-  (cons-entries (make-hash-table :test 'eql)))
-(def!method print-object ((table pprint-dispatch-table) stream)
-  (print-unreadable-object (table stream :type t :identity t)))
-
 (defun cons-type-specifier-p (spec)
   (and (consp spec)
        (eq (car spec) 'cons)
 
 (defun set-pprint-dispatch (type function &optional
                            (priority 0) (table *print-pprint-dispatch*))
-  (declare (type (or null function) function)
+  (declare (type (or null callable) function)
           (type real priority)
           (type pprint-dispatch-table table))
   (/show0 "entering SET-PPRINT-DISPATCH, TYPE=...")
                              :test #'equal))
                (entry (make-pprint-dispatch-entry
                        :type type
-                       :test-fn (compute-test-fn type)
-                       :priority priority
-                       :fun function)))
+                        :test-fn (compute-test-fn type)
+                        :priority priority
+                        :fun function)))
            (do ((prev nil next)
                 (next list (cdr next)))
                ((null next)
                 (if prev
-                    (setf (cdr prev) (list entry))
-                    (setf list (list entry))))
-             (when (entry< (car next) entry)
-               (if prev
-                   (setf (cdr prev) (cons entry next))
-                   (setf list (cons entry next)))
-               (return)))
+                     (setf (cdr prev) (list entry))
+                     (setf list (list entry))))
+              (when (entry< (car next) entry)
+                (if prev
+                    (setf (cdr prev) (cons entry next))
+                    (setf list (cons entry next)))
+                (return)))
            (setf (pprint-dispatch-table-entries table) list)))
       (if (cons-type-specifier-p type)
          (remhash (second (second type))
             (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 (array-readably-printable-p array)))
         (let ((*print-readably* nil))
           (error 'print-not-readable :object array)))
        ((vectorp array)
                                (index index)
                                (step (reduce #'* dims))
                                (count 0))
-                          (loop                                
+                          (loop
                             (pprint-pop)
                             (output-guts stream index dims)
                             (when (= (incf count) dim)
 
 (defun pprint-lambda-list (stream lambda-list &rest noise)
   (declare (ignore noise))
+  (when (and (consp lambda-list)
+            (member (car lambda-list) *backq-tokens*))
+    ;; if this thing looks like a backquoty thing, then we don't want
+    ;; to destructure it, we want to output it straight away.  [ this
+    ;; is the exception to the normal processing: if we did this
+    ;; generally we would find lambda lists such as (FUNCTION FOO)
+    ;; being printed as #'FOO ]  -- CSR, 2003-12-07
+    (output-object lambda-list stream)
+    (return-from pprint-lambda-list nil))
   (pprint-logical-block (stream lambda-list :prefix "(" :suffix ")")
     (let ((state :required)
          (first t))
 
 (defun pprint-flet (stream list &rest noise)
   (declare (ignore noise))
-  (funcall (formatter
-           "~:<~^~W~^ ~@_~:<~@{~:<~^~W~^~3I ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~:@_~@{~W~^ ~_~}~:>~^ ~_~}~:>~1I~@:_~@{~W~^ ~_~}~:>")
-          stream
-          list))
+  (if (cddr list)
+      (funcall (formatter
+                "~:<~^~W~^ ~@_~:<~@{~:<~^~W~^~3I ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~:@_~@{~W~^ ~_~}~:>~^ ~_~}~:>~1I~@:_~@{~W~^ ~_~}~:>")
+               stream
+               list)
+      ;; for printing function names like (flet foo)
+      (pprint-logical-block (stream list :prefix "(" :suffix ")")
+        (pprint-exit-if-list-exhausted)
+        (write (pprint-pop) :stream stream)
+        (loop
+           (pprint-exit-if-list-exhausted)
+           (write-char #\space stream)
+           (write (pprint-pop) :stream stream)))))
 
 (defun pprint-let (stream list &rest noise)
   (declare (ignore noise))
     (/show0 "leaving !PPRINT-COLD-INIT"))
 
   (setf *print-pprint-dispatch* (copy-pprint-dispatch nil))
-  (setf *pretty-printer* #'output-pretty-object)
   (setf *print-pretty* t))