Remove some test noise. A drop in the ocean unfortunately.
[sbcl.git] / src / code / pprint.lisp
blob903351cee20b5f109a78d5195217187c941977b0
1 ;;;; Common Lisp pretty printer
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!PRETTY")
14 ;;;; pretty streams
16 ;;; There are three different units for measuring character positions:
17 ;;; COLUMN - offset (if characters) from the start of the current line
18 ;;; INDEX - index into the output buffer
19 ;;; POSN - some position in the stream of characters cycling through
20 ;;; the output buffer
21 (deftype column ()
22 '(and fixnum unsigned-byte))
23 ;;; The INDEX type is picked up from the kernel package.
24 (deftype posn ()
25 'fixnum)
27 (defconstant initial-buffer-size 128)
29 (defconstant default-line-length 80)
31 ;; We're allowed to DXify the pretty-stream used by PPRINT-LOGICAL-BLOCK.
32 ;; "pprint-logical-block and the pretty printing stream it creates have
33 ;; dynamic extent. The consequences are undefined if, outside of this
34 ;; extent, output is attempted to the pretty printing stream it creates."
35 ;; However doing that is slightly dangerous since there are a zillion ways
36 ;; for users to get a hold of the stream and stash it somewhere.
37 ;; Anyway, just a thought...
38 (declaim (maybe-inline make-pretty-stream))
39 (defstruct (pretty-stream (:include ansi-stream
40 (out #'pretty-out)
41 (sout #'pretty-sout)
42 (misc #'pretty-misc))
43 (:constructor make-pretty-stream (target))
44 (:copier nil))
45 ;; Where the output is going to finally go.
46 (target (missing-arg) :type stream :read-only t)
47 ;; Line length we should format to. Cached here so we don't have to keep
48 ;; extracting it from the target stream.
49 (line-length (or *print-right-margin*
50 (sb!impl::line-length target)
51 default-line-length)
52 :type column
53 :read-only t)
54 ;; If non-nil, a function to call before performing OUT or SOUT
55 (char-out-oneshot-hook nil :type (or null function))
56 ;; A simple string holding all the text that has been output but not yet
57 ;; printed.
58 (buffer (make-string initial-buffer-size) :type (simple-array character (*)))
59 ;; The index into BUFFER where more text should be put.
60 (buffer-fill-pointer 0 :type index)
61 ;; Whenever we output stuff from the buffer, we shift the remaining noise
62 ;; over. This makes it difficult to keep references to locations in
63 ;; the buffer. Therefore, we have to keep track of the total amount of
64 ;; stuff that has been shifted out of the buffer.
65 (buffer-offset 0 :type posn)
66 ;; The column the first character in the buffer will appear in. Normally
67 ;; zero, but if we end up with a very long line with no breaks in it we
68 ;; might have to output part of it. Then this will no longer be zero.
69 (buffer-start-column (or (sb!impl::charpos target) 0) :type column)
70 ;; The line number we are currently on. Used for *PRINT-LINES*
71 ;; abbreviations and to tell when sections have been split across
72 ;; multiple lines.
73 (line-number 0 :type index)
74 ;; the value of *PRINT-LINES* captured at object creation time. We
75 ;; use this, instead of the dynamic *PRINT-LINES*, to avoid
76 ;; weirdness like
77 ;; (let ((*print-lines* 50))
78 ;; (pprint-logical-block ..
79 ;; (dotimes (i 10)
80 ;; (let ((*print-lines* 8))
81 ;; (print (aref possiblybigthings i) prettystream)))))
82 ;; terminating the output of the entire logical blockafter 8 lines.
83 (print-lines *print-lines* :type (or index null) :read-only t)
84 ;; Stack of logical blocks in effect at the buffer start.
85 (blocks (list (make-logical-block)) :type list)
86 ;; Buffer holding the per-line prefix active at the buffer start.
87 ;; Indentation is included in this. The length of this is stored
88 ;; in the logical block stack.
89 (prefix (make-string initial-buffer-size) :type (simple-array character (*)))
90 ;; Buffer holding the total remaining suffix active at the buffer start.
91 ;; The characters are right-justified in the buffer to make it easier
92 ;; to output the buffer. The length is stored in the logical block
93 ;; stack.
94 (suffix (make-string initial-buffer-size) :type (simple-array character (*)))
95 ;; Queue of pending operations. When empty, HEAD=TAIL=NIL. Otherwise,
96 ;; TAIL holds the first (oldest) cons and HEAD holds the last (newest)
97 ;; cons. Adding things to the queue is basically (setf (cdr head) (list
98 ;; new)) and removing them is basically (pop tail) [except that care must
99 ;; be taken to handle the empty queue case correctly.]
100 (queue-tail nil :type list)
101 (queue-head nil :type list)
102 ;; Block-start queue entries in effect at the queue head.
103 (pending-blocks nil :type list))
104 (def!method print-object ((pstream pretty-stream) stream)
105 ;; FIXME: CMU CL had #+NIL'ed out this code and done a hand-written
106 ;; FORMAT hack instead. Make sure that this code actually works instead
107 ;; of falling into infinite regress or something.
108 (print-unreadable-object (pstream stream :type t :identity t)))
110 #!-sb-fluid (declaim (inline index-posn posn-index posn-column))
111 (defun index-posn (index stream)
112 (declare (type index index) (type pretty-stream stream)
113 (values posn))
114 (+ index (pretty-stream-buffer-offset stream)))
115 (defun posn-index (posn stream)
116 (declare (type posn posn) (type pretty-stream stream)
117 (values index))
118 (- posn (pretty-stream-buffer-offset stream)))
119 (defun posn-column (posn stream)
120 (declare (type posn posn) (type pretty-stream stream)
121 (values posn))
122 (index-column (posn-index posn stream) stream))
124 ;;; Is it OK to do pretty printing on this stream at this time?
125 (defun print-pretty-on-stream-p (stream)
126 (and (pretty-stream-p stream)
127 *print-pretty*))
129 ;;;; stream interface routines
131 (defun pretty-out (stream char)
132 (declare (type pretty-stream stream)
133 (type character char))
134 (let ((f (pretty-stream-char-out-oneshot-hook stream)))
135 (when f
136 (setf (pretty-stream-char-out-oneshot-hook stream) nil)
137 (funcall f stream char)))
138 (cond ((char= char #\newline)
139 (enqueue-newline stream :literal))
141 (ensure-space-in-buffer stream 1)
142 (let ((fill-pointer (pretty-stream-buffer-fill-pointer stream)))
143 (setf (schar (pretty-stream-buffer stream) fill-pointer) char)
144 (setf (pretty-stream-buffer-fill-pointer stream)
145 (1+ fill-pointer))))))
147 (defun pretty-sout (stream string start end)
148 (declare (type pretty-stream stream)
149 (type simple-string string)
150 (type index start)
151 (type (or index null) end))
152 (let* ((end (or end (length string))))
153 (unless (= start end)
154 (sb!impl::string-dispatch (simple-base-string
155 #!+sb-unicode
156 (simple-array character (*)))
157 string
158 ;; For POSITION transform
159 (declare (optimize (speed 2)))
160 (let ((f (pretty-stream-char-out-oneshot-hook stream)))
161 (when f
162 (setf (pretty-stream-char-out-oneshot-hook stream) nil)
163 (funcall f stream (aref string start))))
164 (let ((newline (position #\newline string :start start :end end)))
165 (cond
166 (newline
167 (pretty-sout stream string start newline)
168 (enqueue-newline stream :literal)
169 (pretty-sout stream string (1+ newline) end))
171 (let ((chars (- end start)))
172 (loop
173 (let* ((available (ensure-space-in-buffer stream chars))
174 (count (min available chars))
175 (fill-pointer (pretty-stream-buffer-fill-pointer
176 stream))
177 (new-fill-ptr (+ fill-pointer count)))
178 (declare (fixnum available count))
179 (if (typep string 'simple-base-string)
180 ;; FIXME: Reimplementing REPLACE, since it
181 ;; can't be inlined and we don't have a
182 ;; generic "simple-array -> simple-array"
183 ;; transform for it.
184 (loop for i from fill-pointer below new-fill-ptr
185 for j from start
186 with target = (pretty-stream-buffer stream)
187 do (setf (aref target i)
188 (aref string j)))
189 (replace (pretty-stream-buffer stream)
190 string
191 :start1 fill-pointer :end1 new-fill-ptr
192 :start2 start))
193 (setf (pretty-stream-buffer-fill-pointer stream)
194 new-fill-ptr)
195 (decf chars count)
196 (when (zerop count)
197 (return))
198 (incf start count)))))))))))
200 (defun pretty-misc (stream op &optional arg1 arg2)
201 (declare (ignore stream op arg1 arg2)))
203 ;;;; logical blocks
205 (defstruct (logical-block (:copier nil))
206 ;; The column this logical block started in.
207 (start-column 0 :type column)
208 ;; The column the current section started in.
209 (section-column 0 :type column)
210 ;; The length of the per-line prefix. We can't move the indentation
211 ;; left of this.
212 (per-line-prefix-end 0 :type index)
213 ;; The overall length of the prefix, including any indentation.
214 (prefix-length 0 :type index)
215 ;; The overall length of the suffix.
216 (suffix-length 0 :type index)
217 ;; The line number
218 (section-start-line 0 :type index))
220 (defun really-start-logical-block (stream column prefix suffix)
221 (let* ((blocks (pretty-stream-blocks stream))
222 (prev-block (car blocks))
223 (per-line-end (logical-block-per-line-prefix-end prev-block))
224 (prefix-length (logical-block-prefix-length prev-block))
225 (suffix-length (logical-block-suffix-length prev-block))
226 (block (make-logical-block
227 :start-column column
228 :section-column column
229 :per-line-prefix-end per-line-end
230 :prefix-length prefix-length
231 :suffix-length suffix-length
232 :section-start-line (pretty-stream-line-number stream))))
233 (setf (pretty-stream-blocks stream) (cons block blocks))
234 (set-indentation stream column)
235 (when prefix
236 (setf (logical-block-per-line-prefix-end block) column)
237 (replace (pretty-stream-prefix stream) prefix
238 :start1 (- column (length prefix)) :end1 column))
239 (when suffix
240 (let* ((total-suffix (pretty-stream-suffix stream))
241 (total-suffix-len (length total-suffix))
242 (additional (length suffix))
243 (new-suffix-len (+ suffix-length additional)))
244 (when (> new-suffix-len total-suffix-len)
245 (let ((new-total-suffix-len
246 (max (* total-suffix-len 2)
247 (+ suffix-length
248 (floor (* additional 5) 4)))))
249 (setf total-suffix
250 (replace (make-string new-total-suffix-len) total-suffix
251 :start1 (- new-total-suffix-len suffix-length)
252 :start2 (- total-suffix-len suffix-length)))
253 (setf total-suffix-len new-total-suffix-len)
254 (setf (pretty-stream-suffix stream) total-suffix)))
255 (replace total-suffix suffix
256 :start1 (- total-suffix-len new-suffix-len)
257 :end1 (- total-suffix-len suffix-length))
258 (setf (logical-block-suffix-length block) new-suffix-len))))
259 nil)
261 (defun set-indentation (stream column)
262 (let* ((prefix (pretty-stream-prefix stream))
263 (prefix-len (length prefix))
264 (block (car (pretty-stream-blocks stream)))
265 (current (logical-block-prefix-length block))
266 (minimum (logical-block-per-line-prefix-end block))
267 (column (max minimum column)))
268 (when (> column prefix-len)
269 (setf prefix
270 (replace (make-string (max (* prefix-len 2)
271 (+ prefix-len
272 (floor (* (- column prefix-len) 5)
273 4))))
274 prefix
275 :end1 current))
276 (setf (pretty-stream-prefix stream) prefix))
277 (when (> column current)
278 (fill prefix #\space :start current :end column))
279 (setf (logical-block-prefix-length block) column)))
281 (defun really-end-logical-block (stream)
282 (let* ((old (pop (pretty-stream-blocks stream)))
283 (old-indent (logical-block-prefix-length old))
284 (new (car (pretty-stream-blocks stream)))
285 (new-indent (logical-block-prefix-length new)))
286 (when (> new-indent old-indent)
287 (fill (pretty-stream-prefix stream) #\space
288 :start old-indent :end new-indent)))
289 nil)
291 ;;;; the pending operation queue
293 (defstruct (queued-op (:constructor nil)
294 (:copier nil))
295 (posn 0 :type posn))
297 (defmacro enqueue (stream type &rest args)
298 (let ((constructor (symbolicate "MAKE-" type)))
299 (once-only ((stream stream)
300 (entry `(,constructor :posn
301 (index-posn
302 (pretty-stream-buffer-fill-pointer
303 ,stream)
304 ,stream)
305 ,@args))
306 (op `(list ,entry))
307 (head `(pretty-stream-queue-head ,stream)))
308 `(progn
309 (if ,head
310 (setf (cdr ,head) ,op)
311 (setf (pretty-stream-queue-tail ,stream) ,op))
312 (setf (pretty-stream-queue-head ,stream) ,op)
313 ,entry))))
315 (defstruct (section-start (:include queued-op)
316 (:constructor nil)
317 (:copier nil))
318 (depth 0 :type index)
319 (section-end nil :type (or null newline block-end)))
321 (defstruct (newline (:include section-start)
322 (:copier nil))
323 (kind (missing-arg)
324 :type (member :linear :fill :miser :literal :mandatory)))
326 (defun enqueue-newline (stream kind)
327 (let* ((depth (length (pretty-stream-pending-blocks stream)))
328 (newline (enqueue stream newline :kind kind :depth depth)))
329 (dolist (entry (pretty-stream-queue-tail stream))
330 (when (and (not (eq newline entry))
331 (section-start-p entry)
332 (null (section-start-section-end entry))
333 (<= depth (section-start-depth entry)))
334 (setf (section-start-section-end entry) newline))))
335 (maybe-output stream (or (eq kind :literal) (eq kind :mandatory))))
337 (defstruct (indentation (:include queued-op)
338 (:copier nil))
339 (kind (missing-arg) :type (member :block :current))
340 (amount 0 :type fixnum))
342 (defun enqueue-indent (stream kind amount)
343 (enqueue stream indentation :kind kind :amount amount))
345 (defstruct (block-start (:include section-start)
346 (:copier nil))
347 (block-end nil :type (or null block-end))
348 (prefix nil :type (or null simple-string))
349 (suffix nil :type (or null simple-string)))
351 (defun start-logical-block (stream prefix per-line-p suffix)
352 ;; (In the PPRINT-LOGICAL-BLOCK form which calls us,
353 ;; :PREFIX and :PER-LINE-PREFIX have hairy defaulting behavior,
354 ;; and might end up being NIL.)
355 (declare (type (or null string) prefix))
356 ;; (But the defaulting behavior of PPRINT-LOGICAL-BLOCK :SUFFIX is
357 ;; trivial, so it should always be a string.)
358 (declare (type string suffix))
359 (when prefix
360 (unless (typep prefix 'simple-string)
361 (setq prefix (coerce prefix '(simple-array character (*)))))
362 (pretty-sout stream prefix 0 (length prefix)))
363 (unless (typep suffix 'simple-string)
364 (setq suffix (coerce suffix '(simple-array character (*)))))
365 (let* ((pending-blocks (pretty-stream-pending-blocks stream))
366 (start (enqueue stream block-start
367 :prefix (and per-line-p prefix)
368 :suffix suffix
369 :depth (length pending-blocks))))
370 (setf (pretty-stream-pending-blocks stream)
371 (cons start pending-blocks))))
373 (defstruct (block-end (:include queued-op)
374 (:copier nil))
375 (suffix nil :type (or null simple-string)))
377 (defun end-logical-block (stream)
378 (let* ((start (pop (pretty-stream-pending-blocks stream)))
379 (suffix (block-start-suffix start))
380 (end (enqueue stream block-end :suffix suffix)))
381 (when suffix
382 (pretty-sout stream suffix 0 (length suffix)))
383 (setf (block-start-block-end start) end)))
385 (defstruct (tab (:include queued-op)
386 (:copier nil))
387 (sectionp nil :type (member t nil))
388 (relativep nil :type (member t nil))
389 (colnum 0 :type column)
390 (colinc 0 :type column))
392 (defun enqueue-tab (stream kind colnum colinc)
393 (multiple-value-bind (sectionp relativep)
394 (ecase kind
395 (:line (values nil nil))
396 (:line-relative (values nil t))
397 (:section (values t nil))
398 (:section-relative (values t t)))
399 (enqueue stream tab :sectionp sectionp :relativep relativep
400 :colnum colnum :colinc colinc)))
402 ;;;; tab support
404 (defun compute-tab-size (tab section-start column)
405 (let* ((origin (if (tab-sectionp tab) section-start 0))
406 (colnum (tab-colnum tab))
407 (colinc (tab-colinc tab))
408 (position (- column origin)))
409 (cond ((tab-relativep tab)
410 (unless (<= colinc 1)
411 (let ((newposn (+ position colnum)))
412 (let ((rem (rem newposn colinc)))
413 (unless (zerop rem)
414 (incf colnum (- colinc rem))))))
415 colnum)
416 ((< position colnum)
417 (- colnum position))
418 ((zerop colinc) 0)
420 (- colinc
421 (rem (- position colnum) colinc))))))
423 (defun index-column (index stream)
424 (let ((column (pretty-stream-buffer-start-column stream))
425 (section-start (logical-block-section-column
426 (first (pretty-stream-blocks stream))))
427 (end-posn (index-posn index stream)))
428 (dolist (op (pretty-stream-queue-tail stream))
429 (when (>= (queued-op-posn op) end-posn)
430 (return))
431 (typecase op
432 (tab
433 (incf column
434 (compute-tab-size op
435 section-start
436 (+ column
437 (posn-index (tab-posn op)
438 stream)))))
439 ((or newline block-start)
440 (setf section-start
441 (+ column (posn-index (queued-op-posn op)
442 stream))))))
443 (+ column index)))
445 (defun expand-tabs (stream through)
446 (let ((insertions nil)
447 (additional 0)
448 (column (pretty-stream-buffer-start-column stream))
449 (section-start (logical-block-section-column
450 (first (pretty-stream-blocks stream)))))
451 (dolist (op (pretty-stream-queue-tail stream))
452 (typecase op
453 (tab
454 (let* ((index (posn-index (tab-posn op) stream))
455 (tabsize (compute-tab-size op
456 section-start
457 (+ column index))))
458 (unless (zerop tabsize)
459 (push (cons index tabsize) insertions)
460 (incf additional tabsize)
461 (incf column tabsize))))
462 ((or newline block-start)
463 (setf section-start
464 (+ column (posn-index (queued-op-posn op) stream)))))
465 (when (eq op through)
466 (return)))
467 (when insertions
468 (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
469 (new-fill-ptr (+ fill-ptr additional))
470 (buffer (pretty-stream-buffer stream))
471 (new-buffer buffer)
472 (length (length buffer))
473 (end fill-ptr))
474 (when (> new-fill-ptr length)
475 (let ((new-length (max (* length 2)
476 (+ fill-ptr
477 (floor (* additional 5) 4)))))
478 (setf new-buffer (make-string new-length))
479 (setf (pretty-stream-buffer stream) new-buffer)))
480 (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
481 (decf (pretty-stream-buffer-offset stream) additional)
482 (dolist (insertion insertions)
483 (let* ((srcpos (car insertion))
484 (amount (cdr insertion))
485 (dstpos (+ srcpos additional)))
486 (replace new-buffer buffer :start1 dstpos :start2 srcpos :end2 end)
487 (fill new-buffer #\space :start (- dstpos amount) :end dstpos)
488 (decf additional amount)
489 (setf end srcpos)))
490 (unless (eq new-buffer buffer)
491 (replace new-buffer buffer :end1 end :end2 end))))))
493 ;;;; stuff to do the actual outputting
495 (defun ensure-space-in-buffer (stream want)
496 (declare (type pretty-stream stream)
497 (type index want))
498 (let* ((buffer (pretty-stream-buffer stream))
499 (length (length buffer))
500 (fill-ptr (pretty-stream-buffer-fill-pointer stream))
501 (available (- length fill-ptr)))
502 (cond ((plusp available)
503 available)
504 ((> fill-ptr (pretty-stream-line-length stream))
505 (unless (maybe-output stream nil)
506 (output-partial-line stream))
507 (ensure-space-in-buffer stream want))
509 (let* ((new-length (max (* length 2)
510 (+ length
511 (floor (* want 5) 4))))
512 (new-buffer (make-string new-length)))
513 (setf (pretty-stream-buffer stream) new-buffer)
514 (replace new-buffer buffer :end1 fill-ptr)
515 (- new-length fill-ptr))))))
517 (defun maybe-output (stream force-newlines-p)
518 (declare (type pretty-stream stream))
519 (let ((tail (pretty-stream-queue-tail stream))
520 (output-anything nil))
521 (loop
522 (unless tail
523 (setf (pretty-stream-queue-head stream) nil)
524 (return))
525 (let ((next (pop tail)))
526 (etypecase next
527 (newline
528 (when (ecase (newline-kind next)
529 ((:literal :mandatory :linear) t)
530 (:miser (misering-p stream))
531 (:fill
532 (or (misering-p stream)
533 (> (pretty-stream-line-number stream)
534 (logical-block-section-start-line
535 (first (pretty-stream-blocks stream))))
536 (ecase (fits-on-line-p stream
537 (newline-section-end next)
538 force-newlines-p)
539 ((t) nil)
540 ((nil) t)
541 (:dont-know
542 (return))))))
543 (setf output-anything t)
544 (output-line stream next)))
545 (indentation
546 (unless (misering-p stream)
547 (set-indentation stream
548 (+ (ecase (indentation-kind next)
549 (:block
550 (logical-block-start-column
551 (car (pretty-stream-blocks stream))))
552 (:current
553 (posn-column
554 (indentation-posn next)
555 stream)))
556 (indentation-amount next)))))
557 (block-start
558 (ecase (fits-on-line-p stream (block-start-section-end next)
559 force-newlines-p)
560 ((t)
561 ;; Just nuke the whole logical block and make it look
562 ;; like one nice long literal.
563 (let ((end (block-start-block-end next)))
564 (expand-tabs stream end)
565 (setf tail (cdr (member end tail)))))
566 ((nil)
567 (really-start-logical-block
568 stream
569 (posn-column (block-start-posn next) stream)
570 (block-start-prefix next)
571 (block-start-suffix next)))
572 (:dont-know
573 (return))))
574 (block-end
575 (really-end-logical-block stream))
576 (tab
577 (expand-tabs stream next))))
578 (setf (pretty-stream-queue-tail stream) tail))
579 output-anything))
581 (defun misering-p (stream)
582 (declare (type pretty-stream stream))
583 (and *print-miser-width*
584 (<= (- (pretty-stream-line-length stream)
585 (logical-block-start-column (car (pretty-stream-blocks stream))))
586 *print-miser-width*)))
588 (defun fits-on-line-p (stream until force-newlines-p)
589 (let ((available (pretty-stream-line-length stream)))
590 (when (and (not *print-readably*)
591 (pretty-stream-print-lines stream)
592 (= (pretty-stream-print-lines stream)
593 (pretty-stream-line-number stream)))
594 (decf available 3) ; for the `` ..''
595 (decf available (logical-block-suffix-length
596 (car (pretty-stream-blocks stream)))))
597 (cond (until
598 (<= (posn-column (queued-op-posn until) stream) available))
599 (force-newlines-p nil)
600 ((> (index-column (pretty-stream-buffer-fill-pointer stream) stream)
601 available)
602 nil)
604 :dont-know))))
606 (defun output-line (stream until)
607 (declare (type pretty-stream stream)
608 (type newline until))
609 (let* ((target (pretty-stream-target stream))
610 (buffer (pretty-stream-buffer stream))
611 (kind (newline-kind until))
612 (literal-p (eq kind :literal))
613 (amount-to-consume (posn-index (newline-posn until) stream))
614 (amount-to-print
615 (if literal-p
616 amount-to-consume
617 (let ((last-non-blank
618 (position #\space buffer :end amount-to-consume
619 :from-end t :test #'char/=)))
620 (if last-non-blank
621 (1+ last-non-blank)
622 0)))))
623 (write-string buffer target :end amount-to-print)
624 (let ((line-number (pretty-stream-line-number stream)))
625 (incf line-number)
626 (when (and (not *print-readably*)
627 (pretty-stream-print-lines stream)
628 (>= line-number (pretty-stream-print-lines stream)))
629 (write-string " .." target)
630 (let ((suffix-length (logical-block-suffix-length
631 (car (pretty-stream-blocks stream)))))
632 (unless (zerop suffix-length)
633 (let* ((suffix (pretty-stream-suffix stream))
634 (len (length suffix)))
635 (write-string suffix target
636 :start (- len suffix-length)
637 :end len))))
638 (throw 'line-limit-abbreviation-happened t))
639 (setf (pretty-stream-line-number stream) line-number)
640 (write-char #\newline target)
641 (setf (pretty-stream-buffer-start-column stream) 0)
642 (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
643 (block (first (pretty-stream-blocks stream)))
644 (prefix-len
645 (if literal-p
646 (logical-block-per-line-prefix-end block)
647 (logical-block-prefix-length block)))
648 (shift (- amount-to-consume prefix-len))
649 (new-fill-ptr (- fill-ptr shift))
650 (new-buffer buffer)
651 (buffer-length (length buffer)))
652 (when (> new-fill-ptr buffer-length)
653 (setf new-buffer
654 (make-string (max (* buffer-length 2)
655 (+ buffer-length
656 (floor (* (- new-fill-ptr buffer-length)
658 4)))))
659 (setf (pretty-stream-buffer stream) new-buffer))
660 (replace new-buffer buffer
661 :start1 prefix-len :start2 amount-to-consume :end2 fill-ptr)
662 (replace new-buffer (pretty-stream-prefix stream)
663 :end1 prefix-len)
664 (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
665 (incf (pretty-stream-buffer-offset stream) shift)
666 (unless literal-p
667 (setf (logical-block-section-column block) prefix-len)
668 (setf (logical-block-section-start-line block) line-number))))))
670 (defun output-partial-line (stream)
671 (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
672 (tail (pretty-stream-queue-tail stream))
673 (count
674 (if tail
675 (posn-index (queued-op-posn (car tail)) stream)
676 fill-ptr))
677 (new-fill-ptr (- fill-ptr count))
678 (buffer (pretty-stream-buffer stream)))
679 (when (zerop count)
680 (error "Output-partial-line called when nothing can be output."))
681 (write-string buffer (pretty-stream-target stream)
682 :start 0 :end count)
683 (incf (pretty-stream-buffer-start-column stream) count)
684 (replace buffer buffer :end1 new-fill-ptr :start2 count :end2 fill-ptr)
685 (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
686 (incf (pretty-stream-buffer-offset stream) count)))
688 (defun force-pretty-output (stream)
689 (maybe-output stream nil)
690 (expand-tabs stream nil)
691 (write-string (pretty-stream-buffer stream)
692 (pretty-stream-target stream)
693 :end (pretty-stream-buffer-fill-pointer stream)))
695 ;;;; user interface to the pretty printer
697 (defun pprint-newline (kind &optional stream)
698 #!+sb-doc
699 "Output a conditional newline to STREAM (which defaults to
700 *STANDARD-OUTPUT*) if it is a pretty-printing stream, and do
701 nothing if not. KIND can be one of:
702 :LINEAR - A line break is inserted if and only if the immediately
703 containing section cannot be printed on one line.
704 :MISER - Same as LINEAR, but only if ``miser-style'' is in effect.
705 (See *PRINT-MISER-WIDTH*.)
706 :FILL - A line break is inserted if and only if either:
707 (a) the following section cannot be printed on the end of the
708 current line,
709 (b) the preceding section was not printed on a single line, or
710 (c) the immediately containing section cannot be printed on one
711 line and miser-style is in effect.
712 :MANDATORY - A line break is always inserted.
713 When a line break is inserted by any type of conditional newline, any
714 blanks that immediately precede the conditional newline are omitted
715 from the output and indentation is introduced at the beginning of the
716 next line. (See PPRINT-INDENT.)"
717 (declare (type (member :linear :miser :fill :mandatory) kind)
718 (type stream-designator stream)
719 (values null))
720 (let ((stream (out-synonym-of stream)))
721 (when (print-pretty-on-stream-p stream)
722 (enqueue-newline stream kind)))
723 nil)
725 (defun pprint-indent (relative-to n &optional stream)
726 #!+sb-doc
727 "Specify the indentation to use in the current logical block if
728 STREAM \(which defaults to *STANDARD-OUTPUT*) is a pretty-printing
729 stream and do nothing if not. (See PPRINT-LOGICAL-BLOCK.) N is the
730 indentation to use (in ems, the width of an ``m'') and RELATIVE-TO can
731 be either:
733 :BLOCK - Indent relative to the column the current logical block
734 started on.
736 :CURRENT - Indent relative to the current column.
738 The new indentation value does not take effect until the following
739 line break."
740 (declare (type (member :block :current) relative-to)
741 (type real n)
742 (type stream-designator stream)
743 (values null))
744 (let ((stream (out-synonym-of stream)))
745 (when (print-pretty-on-stream-p stream)
746 (enqueue-indent stream relative-to (truncate n))))
747 nil)
749 (defun pprint-tab (kind colnum colinc &optional stream)
750 #!+sb-doc
751 "If STREAM (which defaults to *STANDARD-OUTPUT*) is a pretty-printing
752 stream, perform tabbing based on KIND, otherwise do nothing. KIND can
753 be one of:
754 :LINE - Tab to column COLNUM. If already past COLNUM tab to the next
755 multiple of COLINC.
756 :SECTION - Same as :LINE, but count from the start of the current
757 section, not the start of the line.
758 :LINE-RELATIVE - Output COLNUM spaces, then tab to the next multiple of
759 COLINC.
760 :SECTION-RELATIVE - Same as :LINE-RELATIVE, but count from the start
761 of the current section, not the start of the line."
762 (declare (type (member :line :section :line-relative :section-relative) kind)
763 (type unsigned-byte colnum colinc)
764 (type stream-designator stream)
765 (values null))
766 (let ((stream (out-synonym-of stream)))
767 (when (print-pretty-on-stream-p stream)
768 (enqueue-tab stream kind colnum colinc)))
769 nil)
771 (defun pprint-fill (stream list &optional (colon? t) atsign?)
772 #!+sb-doc
773 "Output LIST to STREAM putting :FILL conditional newlines between each
774 element. If COLON? is NIL (defaults to T), then no parens are printed
775 around the output. ATSIGN? is ignored (but allowed so that PPRINT-FILL
776 can be used with the ~/.../ format directive."
777 (declare (ignore atsign?))
778 (pprint-logical-block (stream list
779 :prefix (if colon? "(" "")
780 :suffix (if colon? ")" ""))
781 (pprint-exit-if-list-exhausted)
782 (loop
783 (output-object (pprint-pop) stream)
784 (pprint-exit-if-list-exhausted)
785 (write-char #\space stream)
786 (pprint-newline :fill stream))))
788 (defun pprint-linear (stream list &optional (colon? t) atsign?)
789 #!+sb-doc
790 "Output LIST to STREAM putting :LINEAR conditional newlines between each
791 element. If COLON? is NIL (defaults to T), then no parens are printed
792 around the output. ATSIGN? is ignored (but allowed so that PPRINT-LINEAR
793 can be used with the ~/.../ format directive."
794 (declare (ignore atsign?))
795 (pprint-logical-block (stream list
796 :prefix (if colon? "(" "")
797 :suffix (if colon? ")" ""))
798 (pprint-exit-if-list-exhausted)
799 (loop
800 (output-object (pprint-pop) stream)
801 (pprint-exit-if-list-exhausted)
802 (write-char #\space stream)
803 (pprint-newline :linear stream))))
805 (defun pprint-tabular (stream list &optional (colon? t) atsign? tabsize)
806 #!+sb-doc
807 "Output LIST to STREAM tabbing to the next column that is an even multiple
808 of TABSIZE (which defaults to 16) between each element. :FILL style
809 conditional newlines are also output between each element. If COLON? is
810 NIL (defaults to T), then no parens are printed around the output.
811 ATSIGN? is ignored (but allowed so that PPRINT-TABULAR can be used with
812 the ~/.../ format directive."
813 (declare (ignore atsign?))
814 (pprint-logical-block (stream list
815 :prefix (if colon? "(" "")
816 :suffix (if colon? ")" ""))
817 (pprint-exit-if-list-exhausted)
818 (loop
819 (output-object (pprint-pop) stream)
820 (pprint-exit-if-list-exhausted)
821 (write-char #\space stream)
822 (pprint-tab :section-relative 0 (or tabsize 16) stream)
823 (pprint-newline :fill stream))))
825 ;;;; pprint-dispatch tables
827 (defvar *standard-pprint-dispatch-table*)
828 (defvar *initial-pprint-dispatch-table*)
830 (defstruct (pprint-dispatch-entry (:copier nil) (:predicate nil))
831 ;; the type specifier for this entry
832 (type (missing-arg) :type t :read-only t)
833 ;; a function to test to see whether an object is of this type,
834 ;; either (LAMBDA (OBJ) (TYPEP OBJECT TYPE)) or a builtin predicate.
835 ;; We don't bother computing this for entries in the CONS
836 ;; hash table, because we don't need it.
837 (test-fn nil :type (or function null))
838 ;; the priority for this guy
839 (priority 0 :type real :read-only t)
840 ;; T iff one of the original entries.
841 (initial-p (eq *initial-pprint-dispatch-table* nil)
842 :type (member t nil) :read-only t)
843 ;; and the associated function
844 (fun (missing-arg) :type callable :read-only t))
845 (def!method print-object ((entry pprint-dispatch-entry) stream)
846 (print-unreadable-object (entry stream :type t)
847 (format stream "type=~S, priority=~S~@[ [initial]~]"
848 (pprint-dispatch-entry-type entry)
849 (pprint-dispatch-entry-priority entry)
850 (pprint-dispatch-entry-initial-p entry))))
852 ;; Return T iff E1 is strictly less preferable than E2.
853 (defun entry< (e1 e2)
854 (declare (type pprint-dispatch-entry e1 e2))
855 (if (pprint-dispatch-entry-initial-p e1)
856 (if (pprint-dispatch-entry-initial-p e2)
857 (< (pprint-dispatch-entry-priority e1)
858 (pprint-dispatch-entry-priority e2))
860 (if (pprint-dispatch-entry-initial-p e2)
862 (< (pprint-dispatch-entry-priority e1)
863 (pprint-dispatch-entry-priority e2)))))
865 ;; Return the predicate for CTYPE, equivalently TYPE-SPEC.
866 ;; This used to involve rewriting into a sexpr if CONS was involved,
867 ;; since it was not an official specifier. But now it is.
868 (defun compute-test-fn (ctype type-spec function)
869 (declare (special sb!c::*backend-type-predicates*))
870 ;; Avoid compiling code for an existing structure predicate
871 (or (and (eq (info :type :kind type-spec) :instance)
872 (let ((layout (info :type :compiler-layout type-spec)))
873 (and layout
874 (let ((info (layout-info layout)))
875 (and info
876 (let ((pred (dd-predicate-name info)))
877 (and pred (fboundp pred)
878 (symbol-function pred))))))))
879 ;; avoid compiling code for CONS, ARRAY, VECTOR, etc
880 (awhen (assoc ctype sb!c::*backend-type-predicates* :test #'type=)
881 (symbol-function (cdr it)))
882 ;; OK, compile something
883 (let ((name
884 ;; Keep name as a string, because NAMED-LAMBDA with a symbol
885 ;; affects the global environment, when all you want
886 ;; is to give the lambda a human-readable label.
887 (format nil "~A-P"
888 (cond ((symbolp type-spec) type-spec)
889 ((symbolp function) function)
890 ((%fun-name function))
892 (write-to-string type-spec :pretty nil :escape nil
893 :readably nil))))))
894 (compile nil
895 `(named-lambda ,name (object) (typep object ',type-spec))))))
897 (defun copy-pprint-dispatch (&optional (table *print-pprint-dispatch*))
898 (declare (type (or pprint-dispatch-table null) table))
899 (let* ((orig (or table *initial-pprint-dispatch-table*))
900 (new (make-pprint-dispatch-table
901 :entries (copy-list (pprint-dispatch-table-entries orig)))))
902 (replace/eql-hash-table (pprint-dispatch-table-cons-entries new)
903 (pprint-dispatch-table-cons-entries orig))
904 new))
906 (defun pprint-dispatch (object &optional (table *print-pprint-dispatch*))
907 (declare (type (or pprint-dispatch-table null) table))
908 (let* ((table (or table *initial-pprint-dispatch-table*))
909 (cons-entry
910 (and (consp object)
911 (gethash (car object)
912 (pprint-dispatch-table-cons-entries table))))
913 (entry
914 (dolist (entry (pprint-dispatch-table-entries table) cons-entry)
915 (when (and cons-entry
916 (entry< entry cons-entry))
917 (return cons-entry))
918 (when (funcall (pprint-dispatch-entry-test-fn entry) object)
919 (return entry)))))
920 (if entry
921 (values (pprint-dispatch-entry-fun entry) t)
922 (values (lambda (stream object)
923 (output-ugly-object object stream))
924 nil))))
926 (defun assert-not-standard-pprint-dispatch-table (pprint-dispatch operation)
927 (when (eq pprint-dispatch *standard-pprint-dispatch-table*)
928 (cerror "Frob it anyway!" 'standard-pprint-dispatch-table-modified-error
929 :operation operation)))
931 ;; Similar to (NOT CONTAINS-UNKNOWN-TYPE-P), but this is for when you
932 ;; want to pre-verify that TYPEP won't outright croak, given that you're
933 ;; going to call it really soon.
934 ;; Granted, certain checks could pass or fail by short-circuiting,
935 ;; such as (TYPEP 3 '(OR NUMBER (SATISFIES NO-SUCH-FUN))
936 ;; but this has to be maximally conservative.
937 (defun testable-type-p (ctype)
938 (typecase ctype
939 (unknown-type nil) ; must precede HAIRY because an unknown is HAIRY
940 (hairy-type
941 (let ((spec (hairy-type-specifier ctype)))
942 ;; Anything other than (SATISFIES ...) is testable
943 ;; because there's no reason to suppose that it isn't.
944 (or (neq (car spec) 'satisfies) (fboundp (cadr spec)))))
945 (compound-type (every #'testable-type-p (compound-type-types ctype)))
946 (negation-type (testable-type-p (negation-type-type ctype)))
947 (cons-type (and (testable-type-p (cons-type-car-type ctype))
948 (testable-type-p (cons-type-cdr-type ctype))))
949 (array-type (testable-type-p (array-type-element-type ctype)))
950 (t t)))
952 (defun defer-type-checker (entry)
953 (let ((saved-nonce sb!c::*type-cache-nonce*))
954 (lambda (obj)
955 (let ((nonce sb!c::*type-cache-nonce*))
956 (if (eq nonce saved-nonce)
958 (let ((ctype (specifier-type (pprint-dispatch-entry-type entry))))
959 (setq saved-nonce nonce)
960 (if (testable-type-p ctype)
961 (funcall (setf (pprint-dispatch-entry-test-fn entry)
962 (compute-test-fn
963 ctype
964 (pprint-dispatch-entry-type entry)
965 (pprint-dispatch-entry-fun entry)))
966 obj)
967 nil)))))))
969 ;; The dispatch mechanism is not quite sophisticated enough to have a guard
970 ;; condition on CONS entries. One place this would impact is that you could
971 ;; write the full matcher for QUOTE as just a type-specifier. It can be done
972 ;; now, but using the non-cons table entails linear scan.
973 ;; A test-fn in the cons table would require storing multiple entries per
974 ;; key though because any might fail. Conceivably you could have
975 ;; (cons (eql foo) cons) and (cons (eql foo) bit-vector) as two FOO entries.
976 (defun set-pprint-dispatch (type function &optional
977 (priority 0) (table *print-pprint-dispatch*))
978 (declare (type (or null callable) function)
979 (type real priority)
980 (type pprint-dispatch-table table))
981 (/show0 "entering SET-PPRINT-DISPATCH, TYPE=...")
982 (/hexstr type)
983 (assert-not-standard-pprint-dispatch-table table 'set-pprint-dispatch)
984 (let* ((ctype (or (handler-bind
985 ((parse-unknown-type
986 (lambda (c)
987 (warn "~S is not a recognized type specifier"
988 (parse-unknown-type-specifier c)))))
989 (sb!c::careful-specifier-type type))
990 (error "~S is not a valid type-specifier" type)))
991 (consp (and (cons-type-p ctype)
992 (eq (cons-type-cdr-type ctype) *universal-type*)
993 (member-type-p (cons-type-car-type ctype))))
994 (disabled-p (not (testable-type-p ctype)))
995 (entry (if function
996 (make-pprint-dispatch-entry
997 :type type
998 :test-fn (unless (or consp disabled-p)
999 (compute-test-fn ctype type function))
1000 :priority priority :fun function))))
1001 (when (and function disabled-p)
1002 ;; a DISABLED-P test function has to close over the ENTRY
1003 (setf (pprint-dispatch-entry-test-fn entry) (defer-type-checker entry))
1004 (unless (unknown-type-p ctype) ; already warned in this case
1005 ;; But (OR KNOWN UNKNOWN) did not signal - actually it is indeterminate
1006 ;; - depending on whather it was cached. I think we should not cache
1007 ;; any specifier that contains any unknown anywhere within it.
1008 (warn "~S contains an unrecognized type specifier" type)))
1009 (if consp
1010 (let ((hashtable (pprint-dispatch-table-cons-entries table)))
1011 (dolist (key (member-type-members (cons-type-car-type ctype)))
1012 (if function
1013 (setf (gethash key hashtable) entry)
1014 (remhash key hashtable))))
1015 (setf (pprint-dispatch-table-entries table)
1016 (let ((list (delete type (pprint-dispatch-table-entries table)
1017 :key #'pprint-dispatch-entry-type
1018 :test #'equal)))
1019 (if function
1020 ;; ENTRY< is T if lower in priority, which should sort to
1021 ;; the end, but MERGE's predicate wants T for the (a,b) pair
1022 ;; if 'a' should go in front of 'b', so swap them.
1023 ;; (COMPLEMENT #'entry<) is unstable wrt insertion order.
1024 (merge 'list list (list entry) (lambda (a b) (entry< b a)))
1025 list)))))
1026 (/show0 "about to return NIL from SET-PPRINT-DISPATCH")
1027 nil)
1029 ;;;; standard pretty-printing routines
1031 (defun pprint-array (stream array)
1032 (cond ((and (null *print-array*) (null *print-readably*))
1033 (output-ugly-object array stream))
1034 ((and *print-readably*
1035 (not (array-readably-printable-p array)))
1036 (if *read-eval*
1037 (if (vectorp array)
1038 (sb!impl::output-unreadable-vector-readably array stream)
1039 (sb!impl::output-unreadable-array-readably array stream))
1040 (print-not-readable-error array stream)))
1041 ((vectorp array)
1042 (pprint-vector stream array))
1044 (pprint-multi-dim-array stream array))))
1046 (defun pprint-vector (stream vector)
1047 (pprint-logical-block (stream nil :prefix "#(" :suffix ")")
1048 (dotimes (i (length vector))
1049 (unless (zerop i)
1050 (format stream " ~:_"))
1051 (pprint-pop)
1052 (output-object (aref vector i) stream))))
1054 (defun pprint-multi-dim-array (stream array)
1055 (funcall (formatter "#~DA") stream (array-rank array))
1056 (with-array-data ((data array) (start) (end))
1057 (declare (ignore end))
1058 (labels ((output-guts (stream index dimensions)
1059 (if (null dimensions)
1060 (output-object (aref data index) stream)
1061 (pprint-logical-block
1062 (stream nil :prefix "(" :suffix ")")
1063 (let ((dim (car dimensions)))
1064 (unless (zerop dim)
1065 (let* ((dims (cdr dimensions))
1066 (index index)
1067 (step (reduce #'* dims))
1068 (count 0))
1069 (loop
1070 (pprint-pop)
1071 (output-guts stream index dims)
1072 (when (= (incf count) dim)
1073 (return))
1074 (write-char #\space stream)
1075 (pprint-newline (if dims :linear :fill)
1076 stream)
1077 (incf index step)))))))))
1078 (output-guts stream start (array-dimensions array)))))
1080 (defun pprint-lambda-list (stream lambda-list &rest noise)
1081 (declare (ignore noise))
1082 (pprint-logical-block (stream lambda-list :prefix "(" :suffix ")")
1083 (let ((state :required)
1084 (first t))
1085 (loop
1086 (pprint-exit-if-list-exhausted)
1087 (unless first
1088 (write-char #\space stream))
1089 (let ((arg (pprint-pop)))
1090 (unless first
1091 (case arg
1092 (&optional
1093 (setf state :optional)
1094 (pprint-newline :linear stream))
1095 ((&rest &body)
1096 (setf state :required)
1097 (pprint-newline :linear stream))
1098 (&key
1099 (setf state :key)
1100 (pprint-newline :linear stream))
1101 (&aux
1102 (setf state :optional)
1103 (pprint-newline :linear stream))
1105 (pprint-newline :fill stream))))
1106 (ecase state
1107 (:required
1108 (pprint-lambda-list stream arg))
1109 ((:optional :key)
1110 (pprint-logical-block
1111 (stream arg :prefix "(" :suffix ")")
1112 (pprint-exit-if-list-exhausted)
1113 (if (eq state :key)
1114 (pprint-logical-block
1115 (stream (pprint-pop) :prefix "(" :suffix ")")
1116 (pprint-exit-if-list-exhausted)
1117 (output-object (pprint-pop) stream)
1118 (pprint-exit-if-list-exhausted)
1119 (write-char #\space stream)
1120 (pprint-newline :fill stream)
1121 (pprint-lambda-list stream (pprint-pop))
1122 (loop
1123 (pprint-exit-if-list-exhausted)
1124 (write-char #\space stream)
1125 (pprint-newline :fill stream)
1126 (output-object (pprint-pop) stream)))
1127 (pprint-lambda-list stream (pprint-pop)))
1128 (loop
1129 (pprint-exit-if-list-exhausted)
1130 (write-char #\space stream)
1131 (pprint-newline :linear stream)
1132 (output-object (pprint-pop) stream))))))
1133 (setf first nil)))))
1135 (defun pprint-lambda (stream list &rest noise)
1136 (declare (ignore noise))
1137 (funcall (formatter
1138 ;; KLUDGE: This format string, and other format strings which also
1139 ;; refer to SB!PRETTY, rely on the current SBCL not-quite-ANSI
1140 ;; behavior of FORMATTER in order to make code which survives the
1141 ;; transition when SB!PRETTY is renamed to SB-PRETTY after cold
1142 ;; init. (ANSI says that the FORMATTER functions should be
1143 ;; equivalent to the format string, but the SBCL FORMATTER
1144 ;; functions contain references to package objects, not package
1145 ;; names, so they keep right on going if the packages are renamed.)
1146 ;; If our FORMATTER behavior is ever made more compliant, the code
1147 ;; here will have to change. -- WHN 19991207
1148 "~:<~^~W~^~3I ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
1149 stream
1150 list))
1152 (defun pprint-block (stream list &rest noise)
1153 (declare (ignore noise))
1154 (funcall (formatter "~:<~^~W~^~3I ~:_~W~1I~@{ ~_~W~}~:>") stream list))
1156 (defun pprint-flet (stream list &rest noise)
1157 (declare (ignore noise))
1158 (if (and (consp list)
1159 (consp (cdr list))
1160 (cddr list)
1161 ;; Filter out (FLET FOO :IN BAR) names.
1162 (and (consp (cddr list))
1163 (not (eq :in (third list)))))
1164 (funcall (formatter
1165 "~:<~^~W~^ ~@_~:<~@{~:<~^~W~^~3I ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~:@_~@{~W~^ ~_~}~:>~^ ~_~}~:>~1I~@:_~@{~W~^ ~_~}~:>")
1166 stream
1167 list)
1168 ;; for printing function names like (flet foo)
1169 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1170 (pprint-exit-if-list-exhausted)
1171 (write (pprint-pop) :stream stream)
1172 (loop
1173 (pprint-exit-if-list-exhausted)
1174 (write-char #\space stream)
1175 (write (pprint-pop) :stream stream)))))
1177 (defun pprint-let (stream list &rest noise)
1178 (declare (ignore noise))
1179 (funcall (formatter "~:<~^~W~^ ~@_~:<~@{~:<~^~W~@{ ~_~W~}~:>~^ ~_~}~:>~1I~:@_~@{~W~^ ~_~}~:>")
1180 stream
1181 list))
1183 (defun pprint-progn (stream list &rest noise)
1184 (declare (ignore noise))
1185 (pprint-linear stream list))
1187 (defun pprint-progv (stream list &rest noise)
1188 (declare (ignore noise))
1189 (funcall (formatter "~:<~^~W~^~3I ~_~W~^ ~_~W~^~1I~@{ ~_~W~}~:>")
1190 stream list))
1192 (defun pprint-prog2 (stream list &rest noise)
1193 (declare (ignore noise))
1194 (funcall (formatter "~:<~^~W~^~3I ~:_~W~^ ~_~W~^~1I~@{ ~_~W~}~:>")
1195 stream list))
1197 (defun pprint-unquoting-comma (stream obj &rest noise)
1198 (declare (ignore noise))
1199 (write-string (svref #("," ",." ",@") (comma-kind obj)) stream)
1200 (when (eql (comma-kind obj) 0)
1201 ;; Ensure a space is written before any output that would change the meaning
1202 ;; of the preceding the comma to ",." or ",@" such as a symbol named "@BAR".
1203 (setf (pretty-stream-char-out-oneshot-hook stream)
1204 (lambda (stream char)
1205 (when (member char '(#\. #\@))
1206 (write-char #\Space stream)))))
1207 (output-object (comma-expr obj) stream))
1209 (defvar *pprint-quote-with-syntactic-sugar* t)
1211 (defun pprint-quote (stream list &rest noise)
1212 (declare (ignore noise))
1213 (when (and (listp list) (singleton-p (cdr list)))
1214 (let* ((pretty-p nil)
1215 (sigil (case (car list)
1216 (function "#'")
1217 ;; QUASIQUOTE can't choose not to print prettily.
1218 ;; Wrongly nested commas beget unreadable sexprs.
1219 (quasiquote (setq pretty-p t) "`")
1220 (t "'")))) ; ordinary QUOTE
1221 (when (or pretty-p *pprint-quote-with-syntactic-sugar*)
1222 (write-string sigil stream)
1223 (return-from pprint-quote (output-object (cadr list) stream)))))
1224 (pprint-fill stream list))
1226 (defun pprint-declare (stream list &rest noise)
1227 (declare (ignore noise))
1228 ;; Make sure to print (DECLARE (FUNCTION F)) not (DECLARE #'A).
1229 (let ((*pprint-quote-with-syntactic-sugar* nil))
1230 (pprint-spread-fun-call stream list)))
1232 ;;; Try to print every variable-value pair on one line; if that doesn't
1233 ;;; work print the value indented by 2 spaces:
1235 ;;; (setq foo bar
1236 ;;; quux xoo)
1237 ;;; vs.
1238 ;;; (setf foo
1239 ;;; (long form ...)
1240 ;;; quux xoo)
1241 (defun pprint-setq (stream list &rest noise)
1242 (declare (ignore noise))
1243 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1244 (pprint-exit-if-list-exhausted)
1245 (output-object (pprint-pop) stream)
1246 (pprint-exit-if-list-exhausted)
1247 (write-char #\space stream)
1248 (unless (listp (cdr list))
1249 (write-string ". " stream))
1250 (pprint-newline :miser stream)
1251 (pprint-logical-block (stream (cdr list) :prefix "" :suffix "")
1252 (loop
1253 (pprint-indent :block 2 stream)
1254 (output-object (pprint-pop) stream)
1255 (pprint-exit-if-list-exhausted)
1256 (write-char #\space stream)
1257 (pprint-newline :fill stream)
1258 (pprint-indent :block 0 stream)
1259 (output-object (pprint-pop) stream)
1260 (pprint-exit-if-list-exhausted)
1261 (write-char #\space stream)
1262 (pprint-newline :mandatory stream)))))
1264 (eval-when (:compile-toplevel :execute)
1265 (sb!xc:defmacro pprint-tagbody-guts (stream)
1266 `(loop
1267 (pprint-exit-if-list-exhausted)
1268 (write-char #\space ,stream)
1269 (let ((form-or-tag (pprint-pop)))
1270 (pprint-indent :block
1271 (if (atom form-or-tag) 0 1)
1272 ,stream)
1273 (pprint-newline :linear ,stream)
1274 (output-object form-or-tag ,stream)))))
1276 (defun pprint-tagbody (stream list &rest noise)
1277 (declare (ignore noise))
1278 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1279 (pprint-exit-if-list-exhausted)
1280 (output-object (pprint-pop) stream)
1281 (pprint-tagbody-guts stream)))
1283 (defun pprint-case (stream list &rest noise)
1284 (declare (ignore noise))
1285 (funcall (formatter
1286 "~:<~^~W~^ ~3I~:_~W~1I~@{ ~_~:<~^~:/SB!PRETTY:PPRINT-FILL/~^~@{ ~_~W~}~:>~}~:>")
1287 stream
1288 list))
1290 (defun pprint-defun (stream list &rest noise)
1291 (declare (ignore noise))
1292 (funcall (formatter
1293 "~:<~^~W~^ ~@_~:I~W~^ ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
1294 stream
1295 list))
1297 (defun pprint-defmethod (stream list &rest noise)
1298 (declare (ignore noise))
1299 (if (and (consp (cdr list))
1300 (consp (cddr list))
1301 (consp (third list)))
1302 (pprint-defun stream list)
1303 (funcall (formatter
1304 "~:<~^~W~^ ~@_~:I~W~^ ~W~^ ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
1305 stream
1306 list)))
1308 (defun pprint-defpackage (stream list &rest noise)
1309 (declare (ignore noise))
1310 (funcall (formatter
1311 "~:<~W~^ ~3I~:_~W~^~1I~@{~:@_~:<~^~W~^ ~:I~@_~@{~W~^ ~_~}~:>~}~:>")
1312 stream
1313 list))
1315 (defun pprint-destructuring-bind (stream list &rest noise)
1316 (declare (ignore noise))
1317 (funcall (formatter
1318 "~:<~^~W~^~3I ~_~:/SB!PRETTY:PPRINT-LAMBDA-LIST/~^ ~_~W~^~1I~@{ ~_~W~}~:>")
1319 stream list))
1321 (defun pprint-do (stream list &rest noise)
1322 (declare (ignore noise))
1323 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1324 (pprint-exit-if-list-exhausted)
1325 (output-object (pprint-pop) stream)
1326 (pprint-exit-if-list-exhausted)
1327 (write-char #\space stream)
1328 (pprint-indent :current 0 stream)
1329 (funcall (formatter "~:<~@{~:<~^~W~^ ~@_~:I~W~@{ ~_~W~}~:>~^~:@_~}~:>")
1330 stream
1331 (pprint-pop))
1332 (pprint-exit-if-list-exhausted)
1333 (write-char #\space stream)
1334 (pprint-newline :linear stream)
1335 (pprint-linear stream (pprint-pop))
1336 (pprint-tagbody-guts stream)))
1338 (defun pprint-dolist (stream list &rest noise)
1339 (declare (ignore noise))
1340 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1341 (pprint-exit-if-list-exhausted)
1342 (output-object (pprint-pop) stream)
1343 (pprint-exit-if-list-exhausted)
1344 (pprint-indent :block 3 stream)
1345 (write-char #\space stream)
1346 (pprint-newline :fill stream)
1347 (funcall (formatter "~:<~^~W~^ ~:_~:I~W~@{ ~_~W~}~:>")
1348 stream
1349 (pprint-pop))
1350 (pprint-tagbody-guts stream)))
1352 (defun pprint-typecase (stream list &rest noise)
1353 (declare (ignore noise))
1354 (funcall (formatter
1355 "~:<~^~W~^ ~3I~:_~W~1I~@{ ~_~:<~^~W~^~@{ ~_~W~}~:>~}~:>")
1356 stream
1357 list))
1359 (defun pprint-prog (stream list &rest noise)
1360 (declare (ignore noise))
1361 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1362 (pprint-exit-if-list-exhausted)
1363 (output-object (pprint-pop) stream)
1364 (pprint-exit-if-list-exhausted)
1365 (write-char #\space stream)
1366 (pprint-newline :miser stream)
1367 (pprint-fill stream (pprint-pop))
1368 (pprint-tagbody-guts stream)))
1370 ;;; Each clause in this list will get its own line.
1371 ;;; FIXME: (LOOP for x in list summing (f x) into count finally ...)
1372 ;;; puts a newline in between INTO and COUNT.
1373 ;;; It would be awesome to have code in common with the macro
1374 ;;; the properly represents each clauses.
1375 (defvar *loop-seperating-clauses*
1376 '(:and
1377 :with :for
1378 :initially :finally
1379 :do :doing
1380 :collect :collecting
1381 :append :appending
1382 :nconc :nconcing
1383 :count :counting
1384 :sum :summing
1385 :maximize :maximizing
1386 :minimize :minimizing
1387 :if :when :unless :end
1388 :for :while :until :repeat :always :never :thereis
1391 (defun pprint-extended-loop (stream list)
1392 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1393 (output-object (pprint-pop) stream)
1394 (pprint-exit-if-list-exhausted)
1395 (write-char #\space stream)
1396 (pprint-indent :current 0 stream)
1397 (output-object (pprint-pop) stream)
1398 (pprint-exit-if-list-exhausted)
1399 (write-char #\space stream)
1400 (loop for thing = (pprint-pop)
1401 when (and (symbolp thing)
1402 (member thing *loop-seperating-clauses* :test #'string=))
1403 do (pprint-newline :mandatory stream)
1404 do (output-object thing stream)
1405 do (pprint-exit-if-list-exhausted)
1406 do (write-char #\space stream))))
1408 (defun pprint-loop (stream list &rest noise)
1409 (declare (ignore noise))
1410 (destructuring-bind (loop-symbol . clauses) list
1411 (declare (ignore loop-symbol))
1412 (if (or (atom clauses) (consp (car clauses)))
1413 (pprint-spread-fun-call stream list)
1414 (pprint-extended-loop stream list))))
1416 (defun pprint-if (stream list &rest noise)
1417 (declare (ignore noise))
1418 ;; Indent after the ``predicate'' form, and the ``then'' form.
1419 (funcall (formatter "~:<~^~W~^ ~:I~W~^ ~:@_~@{~W~^ ~:@_~}~:>")
1420 stream
1421 list))
1423 (defun pprint-fun-call (stream list &rest noise)
1424 (declare (ignore noise))
1425 (funcall (formatter "~:<~^~W~^ ~:_~:I~@{~W~^ ~:_~}~:>")
1426 stream
1427 list))
1429 (defun pprint-spread-fun-call (stream list &rest noise)
1430 (declare (ignore noise))
1431 ;; Similiar to PPRINT-FUN-CALL but emit a mandatory newline after
1432 ;; each parameter. I.e. spread out each parameter on its own line.
1433 (funcall (formatter "~:<~^~W~^ ~:_~:I~@{~W~^ ~:@_~}~:>")
1434 stream
1435 list))
1437 (defun pprint-data-list (stream list &rest noise)
1438 (declare (ignore noise))
1439 (pprint-fill stream list))
1441 ;;; Returns an Emacs-style indent spec: an integer N, meaning indent
1442 ;;; the first N arguments specially then indent any further arguments
1443 ;;; like a body.
1444 (defun macro-indentation (name)
1445 (labels ((clean-arglist (arglist)
1446 ;; FIXME: for purposes of introspection, we should never "leak"
1447 ;; that a macro uses an &AUX variable, that it takes &WHOLE,
1448 ;; or that it cares about its lexenv (though that's debatable).
1449 ;; Certainly the first two aspects are not part of the macro's
1450 ;; interface, and as such, should not be stored at all.
1451 "Remove &whole, &enviroment, and &aux elements from ARGLIST."
1452 (cond ((null arglist) '())
1453 ((member (car arglist) '(&whole &environment))
1454 (clean-arglist (cddr arglist)))
1455 ((eq (car arglist) '&aux)
1456 '())
1457 (t (cons (car arglist) (clean-arglist (cdr arglist)))))))
1458 (let ((arglist (%fun-lambda-list (macro-function name))))
1459 (if (proper-list-p arglist) ; guard against dotted arglists
1460 (position '&body (remove '&optional (clean-arglist arglist)))
1461 nil))))
1463 ;;; Pretty-Print macros by looking where &BODY appears in a macro's
1464 ;;; lambda-list.
1465 (defun pprint-macro-call (stream list &rest noise)
1466 (declare (ignore noise))
1467 (let ((indentation (and (car list) (macro-indentation (car list)))))
1468 (unless indentation
1469 (return-from pprint-macro-call
1470 (pprint-fun-call stream list)))
1471 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1472 (output-object (pprint-pop) stream)
1473 (pprint-exit-if-list-exhausted)
1474 (write-char #\space stream)
1475 (loop for indent from 0 below indentation do
1476 (cond
1477 ;; Place the very first argument next to the macro name
1478 ((zerop indent)
1479 (output-object (pprint-pop) stream)
1480 (pprint-exit-if-list-exhausted))
1481 ;; Indent any other non-body argument by the same
1482 ;; amount. It's what Emacs seems to do, too.
1484 (pprint-indent :block 3 stream)
1485 (pprint-newline :mandatory stream)
1486 (output-object (pprint-pop) stream)
1487 (pprint-exit-if-list-exhausted))))
1488 ;; Indent back for the body.
1489 (pprint-indent :block 1 stream)
1490 (pprint-newline :mandatory stream)
1491 (loop
1492 (output-object (pprint-pop) stream)
1493 (pprint-exit-if-list-exhausted)
1494 (pprint-newline :mandatory stream)))))
1496 ;;;; the interface seen by regular (ugly) printer and initialization routines
1498 (eval-when (:compile-toplevel :execute)
1499 (sb!xc:defmacro with-pretty-stream ((stream-var
1500 &optional (stream-expression stream-var))
1501 &body body)
1502 (let ((flet-name (sb!xc:gensym "WITH-PRETTY-STREAM")))
1503 `(flet ((,flet-name (,stream-var)
1504 ,@body))
1505 (let ((stream ,stream-expression))
1506 (if (pretty-stream-p stream)
1507 (,flet-name stream)
1508 (catch 'line-limit-abbreviation-happened
1509 (let ((stream (make-pretty-stream stream)))
1510 (,flet-name stream)
1511 (force-pretty-output stream)))))
1512 nil))))
1514 ;;; OUTPUT-PRETTY-OBJECT is called by OUTPUT-OBJECT when
1515 ;;; *PRINT-PRETTY* is true.
1516 (defun output-pretty-object (object stream)
1517 (multiple-value-bind (fun pretty) (pprint-dispatch object)
1518 (if pretty
1519 (with-pretty-stream (stream)
1520 (funcall fun stream object))
1521 ;; No point in consing up a pretty stream if we are not using pretty
1522 ;; printing the object after all.
1523 (output-ugly-object object stream))))
1525 (defun call-logical-block-printer (proc stream prefix per-line-p suffix
1526 &optional (object nil obj-supplied-p))
1527 ;; PREFIX and SUFFIX will be checked for stringness by START-LOGICAL-BLOCK.
1528 ;; Doing it here would be more strict, but I really don't think it's worth
1529 ;; an extra check. The only observable difference would occur when you have
1530 ;; a non-list object which bypasses START-LOGICAL-BLOCK.
1531 ;; Also, START-LOGICAL-BLOCK could become an FLET inside here.
1532 (declare (function proc))
1533 (with-pretty-stream (stream (out-synonym-of stream))
1534 (if (or (not (listp object)) ; implies obj-supplied-p
1535 (and (eq (car object) 'quasiquote)
1536 ;; We can only bail out from printing this logical block
1537 ;; if the quasiquote printer would *NOT* punt.
1538 ;; If it would punt, then we have to forge ahead.
1539 (singleton-p (cdr object))))
1540 ;; the spec says "If object is not a list, it is printed using WRITE"
1541 ;; but I guess this is close enough.
1542 (output-object object stream)
1543 (dx-let ((state (cons 0 stream)))
1544 (if obj-supplied-p
1545 (with-circularity-detection (object stream)
1546 (descend-into (stream)
1547 (start-logical-block stream prefix per-line-p suffix)
1548 (funcall proc object state stream)
1549 ;; Comment preserved for posterity:
1550 ;; FIXME: Don't we need UNWIND-PROTECT to ensure this
1551 ;; always gets executed?
1552 ;; I think not because I wouldn't characterize this as
1553 ;; "cleanup" code. If and only if you follow the accepted
1554 ;; protocol for defining and using print functions should
1555 ;; the behavior be expected to be reasonable and predictable.
1556 ;; Throwing to LINE-LIMIT-ABBREVIATION-HAPPENED is designed
1557 ;; to do the right thing, and printing should not generally
1558 ;; continue to have side-effects if the user felt it necessary
1559 ;; to nonlocally exit in an unexpected way for other reasons.
1560 (end-logical-block stream)))
1561 (descend-into (stream)
1562 (start-logical-block stream prefix per-line-p suffix)
1563 (funcall proc state stream)
1564 (end-logical-block stream)))))))
1566 ;; Return non-nil if we should keep printing within the logical-block,
1567 ;; or NIL to stop printing due to non-list, length cutoff, or circularity.
1568 (defun pprint-length-check (obj state)
1569 (let ((stream (cdr state)))
1570 (cond ((or (not (listp obj))
1571 ;; Consider (A . `(,B C)) = (A QUASIQUOTE ,B C)
1572 ;; We have to detect this and print as the form on the left,
1573 ;; since pretty commas with no containing #\` will be unreadable
1574 ;; due to a nesting error.
1575 (and (eq (car obj) 'quasiquote) (singleton-p (cdr obj))))
1576 (write-string ". " stream)
1577 (output-object obj stream)
1578 nil)
1579 ((and (not *print-readably*) (eql (car state) *print-length*))
1580 (write-string "..." stream)
1581 nil)
1582 ((and obj
1583 (plusp (car state))
1584 (check-for-circularity obj nil :logical-block))
1585 (write-string ". " stream)
1586 (output-object obj stream)
1587 nil)
1589 (incf (car state))))))
1591 ;; As above, but for logical blocks with an unspecific object.
1592 (defun pprint-length-check* (state)
1593 (let ((stream (cdr state)))
1594 (cond ((and (not *print-readably*) (eql (car state) *print-length*))
1595 (write-string "..." stream)
1596 nil)
1598 (incf (car state))))))
1600 (defun !pprint-cold-init ()
1601 (/show0 "entering !PPRINT-COLD-INIT")
1602 ;; Kludge: We set *STANDARD-PP-D-TABLE* to a new table even though
1603 ;; it's going to be set to a copy of *INITIAL-PP-D-T* below because
1604 ;; it's used in WITH-STANDARD-IO-SYNTAX, and condition reportery
1605 ;; possibly performed in the following extent may use W-S-IO-SYNTAX.
1606 (setf *standard-pprint-dispatch-table* (make-pprint-dispatch-table))
1607 (setf *initial-pprint-dispatch-table* nil)
1608 (let ((*print-pprint-dispatch* (make-pprint-dispatch-table)))
1609 (/show0 "doing SET-PPRINT-DISPATCH for regular types")
1610 (set-pprint-dispatch '(and array (not (or string bit-vector))) #'pprint-array)
1611 ;; MACRO-FUNCTION must have effectively higher priority than FBOUNDP.
1612 ;; The implementation happens to check identical priorities in the order added,
1613 ;; but that's unspecified behavior. Both must be _strictly_ lower than the
1614 ;; default cons entries though.
1615 (set-pprint-dispatch '(cons (and symbol (satisfies macro-function)))
1616 #'pprint-macro-call -1)
1617 (set-pprint-dispatch '(cons (and symbol (satisfies fboundp)))
1618 #'pprint-fun-call -1)
1619 (set-pprint-dispatch '(cons symbol)
1620 #'pprint-data-list -2)
1621 (set-pprint-dispatch 'cons #'pprint-fill -2)
1622 (set-pprint-dispatch 'sb!impl::comma #'pprint-unquoting-comma -3)
1623 ;; cons cells with interesting things for the car
1624 (/show0 "doing SET-PPRINT-DISPATCH for CONS with interesting CAR")
1626 (dolist (magic-form '((lambda pprint-lambda)
1627 (declare pprint-declare)
1629 ;; special forms
1630 (block pprint-block)
1631 (catch pprint-block)
1632 (eval-when pprint-block)
1633 (flet pprint-flet)
1634 (function pprint-quote)
1635 (if pprint-if)
1636 (labels pprint-flet)
1637 ((let let*) pprint-let)
1638 (locally pprint-progn)
1639 (macrolet pprint-flet)
1640 (multiple-value-call pprint-block)
1641 (multiple-value-prog1 pprint-block)
1642 (progn pprint-progn)
1643 (progv pprint-progv)
1644 ((quasiquote quote) pprint-quote)
1645 (return-from pprint-block)
1646 ((setq psetq setf psetf) pprint-setq)
1647 (symbol-macrolet pprint-let)
1648 (tagbody pprint-tagbody)
1649 (throw pprint-block)
1650 (unwind-protect pprint-block)
1652 ;; macros
1653 ((case ccase ecase) pprint-case)
1654 ((ctypecase etypecase typecase) pprint-typecase)
1655 (declaim pprint-declare)
1656 (defconstant pprint-block)
1657 (define-modify-macro pprint-defun)
1658 (define-setf-expander pprint-defun)
1659 (defmacro pprint-defun)
1660 (defmethod pprint-defmethod)
1661 (defpackage pprint-defpackage)
1662 (defparameter pprint-block)
1663 (defsetf pprint-defun)
1664 (defstruct pprint-block)
1665 (deftype pprint-defun)
1666 (defun pprint-defun)
1667 (defvar pprint-block)
1668 (destructuring-bind pprint-destructuring-bind)
1669 ((do do*) pprint-do)
1670 ((do-all-symbols do-external-symbols do-symbols
1671 dolist dotimes) pprint-dolist)
1672 #+nil (handler-bind ...)
1673 #+nil (handler-case ...)
1674 (loop pprint-loop)
1675 (multiple-value-bind pprint-prog2)
1676 (multiple-value-setq pprint-block)
1677 (pprint-logical-block pprint-block)
1678 (print-unreadable-object pprint-block)
1679 ((prog prog*) pprint-prog)
1680 (prog1 pprint-block)
1681 (prog2 pprint-prog2)
1682 #+nil (restart-bind ...)
1683 #+nil (restart-case ...)
1684 (step pprint-progn)
1685 (time pprint-progn)
1686 ((unless when) pprint-block)
1687 (with-compilation-unit pprint-block)
1688 #+nil (with-condition-restarts ...)
1689 (with-hash-table-iterator pprint-block)
1690 (with-input-from-string pprint-block)
1691 (with-open-file pprint-block)
1692 (with-open-stream pprint-block)
1693 (with-output-to-string pprint-block)
1694 (with-package-iterator pprint-block)
1695 (with-simple-restart pprint-block)
1696 (with-standard-io-syntax pprint-progn)
1698 ;; sbcl specific
1699 (sb!int:dx-flet pprint-flet)
1702 ;; Grouping some symbols together in the above list looks pretty.
1703 ;; The sharing of dispatch entries is inconsequential.
1704 (set-pprint-dispatch (let ((thing (first magic-form)))
1705 `(cons (member
1706 ,@(if (consp thing) thing (list thing)))))
1707 (symbol-function (second magic-form))))
1708 (setf *initial-pprint-dispatch-table* *print-pprint-dispatch*))
1710 (setf *standard-pprint-dispatch-table*
1711 (copy-pprint-dispatch *initial-pprint-dispatch-table*))
1712 (setf *print-pprint-dispatch*
1713 (copy-pprint-dispatch *initial-pprint-dispatch-table*))
1714 (setf *print-pretty* t))