Don't ad-hoc reimplement DEFCONSTANT-EQX for LAMBDA-LIST-KEYWORDS.
[sbcl.git] / src / code / pprint.lisp
bloba548797d4f0babe3766dd639c28aa985c1d3fa09
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 #!-sb-fluid (declaim (inline index-posn posn-index posn-column))
15 (defun index-posn (index stream)
16 (declare (type index index) (type pretty-stream stream)
17 (values posn))
18 (+ index (pretty-stream-buffer-offset stream)))
19 (defun posn-index (posn stream)
20 (declare (type posn posn) (type pretty-stream stream)
21 (values index))
22 (- posn (pretty-stream-buffer-offset stream)))
23 (defun posn-column (posn stream)
24 (declare (type posn posn) (type pretty-stream stream)
25 (values posn))
26 (index-column (posn-index posn stream) stream))
28 ;;; Is it OK to do pretty printing on this stream at this time?
29 (defun print-pretty-on-stream-p (stream)
30 (and (pretty-stream-p stream)
31 *print-pretty*))
33 ;;;; stream interface routines
35 (defun pretty-out (stream char)
36 (declare (type pretty-stream stream)
37 (type character char))
38 (let ((f (pretty-stream-char-out-oneshot-hook stream)))
39 (when f
40 (setf (pretty-stream-char-out-oneshot-hook stream) nil)
41 (funcall f stream char)))
42 (cond ((char= char #\newline)
43 (enqueue-newline stream :literal))
45 (ensure-space-in-buffer stream 1)
46 (let ((fill-pointer (pretty-stream-buffer-fill-pointer stream)))
47 (setf (schar (pretty-stream-buffer stream) fill-pointer) char)
48 (setf (pretty-stream-buffer-fill-pointer stream)
49 (1+ fill-pointer))))))
51 (defun pretty-sout (stream string start end)
52 (declare (type pretty-stream stream)
53 (type simple-string string)
54 (type index start)
55 (type (or index null) end))
56 (let* ((end (or end (length string))))
57 (unless (= start end)
58 (sb!impl::string-dispatch (simple-base-string
59 #!+sb-unicode
60 (simple-array character (*)))
61 string
62 ;; For POSITION transform
63 (declare (optimize (speed 2)))
64 (let ((f (pretty-stream-char-out-oneshot-hook stream)))
65 (when f
66 (setf (pretty-stream-char-out-oneshot-hook stream) nil)
67 (funcall f stream (aref string start))))
68 (let ((newline (position #\newline string :start start :end end)))
69 (cond
70 (newline
71 (pretty-sout stream string start newline)
72 (enqueue-newline stream :literal)
73 (pretty-sout stream string (1+ newline) end))
75 (let ((chars (- end start)))
76 (loop
77 (let* ((available (ensure-space-in-buffer stream chars))
78 (count (min available chars))
79 (fill-pointer (pretty-stream-buffer-fill-pointer
80 stream))
81 (new-fill-ptr (+ fill-pointer count)))
82 (declare (fixnum available count))
83 (if (typep string 'simple-base-string)
84 ;; FIXME: Reimplementing REPLACE, since it
85 ;; can't be inlined and we don't have a
86 ;; generic "simple-array -> simple-array"
87 ;; transform for it.
88 (loop for i from fill-pointer below new-fill-ptr
89 for j from start
90 with target = (pretty-stream-buffer stream)
91 do (setf (aref target i)
92 (aref string j)))
93 (replace (pretty-stream-buffer stream)
94 string
95 :start1 fill-pointer :end1 new-fill-ptr
96 :start2 start))
97 (setf (pretty-stream-buffer-fill-pointer stream)
98 new-fill-ptr)
99 (decf chars count)
100 (when (zerop count)
101 (return))
102 (incf start count)))))))))))
104 (defun pretty-misc (stream op &optional arg1 arg2)
105 (declare (ignore stream op arg1 arg2)))
107 ;;;; logical blocks
109 (defstruct (logical-block (:copier nil))
110 ;; The column this logical block started in.
111 (start-column 0 :type column)
112 ;; The column the current section started in.
113 (section-column 0 :type column)
114 ;; The length of the per-line prefix. We can't move the indentation
115 ;; left of this.
116 (per-line-prefix-end 0 :type index)
117 ;; The overall length of the prefix, including any indentation.
118 (prefix-length 0 :type index)
119 ;; The overall length of the suffix.
120 (suffix-length 0 :type index)
121 ;; The line number
122 (section-start-line 0 :type index))
124 (defun really-start-logical-block (stream column prefix suffix)
125 (let* ((blocks (pretty-stream-blocks stream))
126 (prev-block (car blocks))
127 (per-line-end (logical-block-per-line-prefix-end prev-block))
128 (prefix-length (logical-block-prefix-length prev-block))
129 (suffix-length (logical-block-suffix-length prev-block))
130 (block (make-logical-block
131 :start-column column
132 :section-column column
133 :per-line-prefix-end per-line-end
134 :prefix-length prefix-length
135 :suffix-length suffix-length
136 :section-start-line (pretty-stream-line-number stream))))
137 (setf (pretty-stream-blocks stream) (cons block blocks))
138 (set-indentation stream column)
139 (when prefix
140 (setf (logical-block-per-line-prefix-end block) column)
141 (replace (pretty-stream-prefix stream) prefix
142 :start1 (- column (length prefix)) :end1 column))
143 (when suffix
144 (let* ((total-suffix (pretty-stream-suffix stream))
145 (total-suffix-len (length total-suffix))
146 (additional (length suffix))
147 (new-suffix-len (+ suffix-length additional)))
148 (when (> new-suffix-len total-suffix-len)
149 (let ((new-total-suffix-len
150 (max (* total-suffix-len 2)
151 (+ suffix-length
152 (floor (* additional 5) 4)))))
153 (setf total-suffix
154 (replace (make-string new-total-suffix-len) total-suffix
155 :start1 (- new-total-suffix-len suffix-length)
156 :start2 (- total-suffix-len suffix-length)))
157 (setf total-suffix-len new-total-suffix-len)
158 (setf (pretty-stream-suffix stream) total-suffix)))
159 (replace total-suffix suffix
160 :start1 (- total-suffix-len new-suffix-len)
161 :end1 (- total-suffix-len suffix-length))
162 (setf (logical-block-suffix-length block) new-suffix-len))))
163 nil)
165 (defun set-indentation (stream column)
166 (let* ((prefix (pretty-stream-prefix stream))
167 (prefix-len (length prefix))
168 (block (car (pretty-stream-blocks stream)))
169 (current (logical-block-prefix-length block))
170 (minimum (logical-block-per-line-prefix-end block))
171 (column (max minimum column)))
172 (when (> column prefix-len)
173 (setf prefix
174 (replace (make-string (max (* prefix-len 2)
175 (+ prefix-len
176 (floor (* (- column prefix-len) 5)
177 4))))
178 prefix
179 :end1 current))
180 (setf (pretty-stream-prefix stream) prefix))
181 (when (> column current)
182 (fill prefix #\space :start current :end column))
183 (setf (logical-block-prefix-length block) column)))
185 (defun really-end-logical-block (stream)
186 (let* ((old (pop (pretty-stream-blocks stream)))
187 (old-indent (logical-block-prefix-length old))
188 (new (car (pretty-stream-blocks stream)))
189 (new-indent (logical-block-prefix-length new)))
190 (when (> new-indent old-indent)
191 (fill (pretty-stream-prefix stream) #\space
192 :start old-indent :end new-indent)))
193 nil)
195 ;;;; the pending operation queue
197 (defmacro enqueue (stream type &rest args)
198 (let ((constructor (symbolicate "MAKE-" type)))
199 (once-only ((stream stream)
200 (entry `(,constructor :posn
201 (index-posn
202 (pretty-stream-buffer-fill-pointer
203 ,stream)
204 ,stream)
205 ,@args))
206 (op `(list ,entry))
207 (head `(pretty-stream-queue-head ,stream)))
208 `(progn
209 (if ,head
210 (setf (cdr ,head) ,op)
211 (setf (pretty-stream-queue-tail ,stream) ,op))
212 (setf (pretty-stream-queue-head ,stream) ,op)
213 ,entry))))
215 (defun enqueue-newline (stream kind)
216 (let* ((depth (length (pretty-stream-pending-blocks stream)))
217 (newline (enqueue stream newline :kind kind :depth depth)))
218 (dolist (entry (pretty-stream-queue-tail stream))
219 (when (and (not (eq newline entry))
220 (section-start-p entry)
221 (null (section-start-section-end entry))
222 (<= depth (section-start-depth entry)))
223 (setf (section-start-section-end entry) newline))))
224 (maybe-output stream (or (eq kind :literal) (eq kind :mandatory))))
226 (defstruct (indentation (:include queued-op)
227 (:copier nil))
228 (kind (missing-arg) :type (member :block :current))
229 (amount 0 :type fixnum))
231 (defun enqueue-indent (stream kind amount)
232 (enqueue stream indentation :kind kind :amount amount))
234 (defstruct (block-start (:include section-start)
235 (:copier nil))
236 (block-end nil :type (or null block-end))
237 (prefix nil :type (or null simple-string))
238 (suffix nil :type (or null simple-string)))
240 (defun start-logical-block (stream prefix per-line-p suffix)
241 ;; (In the PPRINT-LOGICAL-BLOCK form which calls us,
242 ;; :PREFIX and :PER-LINE-PREFIX have hairy defaulting behavior,
243 ;; and might end up being NIL.)
244 (declare (type (or null string) prefix))
245 ;; (But the defaulting behavior of PPRINT-LOGICAL-BLOCK :SUFFIX is
246 ;; trivial, so it should always be a string.)
247 (declare (type string suffix))
248 (when prefix
249 (unless (typep prefix 'simple-string)
250 (setq prefix (coerce prefix '(simple-array character (*)))))
251 (pretty-sout stream prefix 0 (length prefix)))
252 (unless (typep suffix 'simple-string)
253 (setq suffix (coerce suffix '(simple-array character (*)))))
254 (let* ((pending-blocks (pretty-stream-pending-blocks stream))
255 (start (enqueue stream block-start
256 :prefix (and per-line-p prefix)
257 :suffix suffix
258 :depth (length pending-blocks))))
259 (setf (pretty-stream-pending-blocks stream)
260 (cons start pending-blocks))))
262 (defun end-logical-block (stream)
263 (let* ((start (pop (pretty-stream-pending-blocks stream)))
264 (suffix (block-start-suffix start))
265 (end (enqueue stream block-end :suffix suffix)))
266 (when suffix
267 (pretty-sout stream suffix 0 (length suffix)))
268 (setf (block-start-block-end start) end)))
270 (defstruct (tab (:include queued-op)
271 (:copier nil))
272 (sectionp nil :type (member t nil))
273 (relativep nil :type (member t nil))
274 (colnum 0 :type column)
275 (colinc 0 :type column))
277 (defun enqueue-tab (stream kind colnum colinc)
278 (multiple-value-bind (sectionp relativep)
279 (ecase kind
280 (:line (values nil nil))
281 (:line-relative (values nil t))
282 (:section (values t nil))
283 (:section-relative (values t t)))
284 (enqueue stream tab :sectionp sectionp :relativep relativep
285 :colnum colnum :colinc colinc)))
287 ;;;; tab support
289 (defun compute-tab-size (tab section-start column)
290 (let* ((origin (if (tab-sectionp tab) section-start 0))
291 (colnum (tab-colnum tab))
292 (colinc (tab-colinc tab))
293 (position (- column origin)))
294 (cond ((tab-relativep tab)
295 (unless (<= colinc 1)
296 (let ((newposn (+ position colnum)))
297 (let ((rem (rem newposn colinc)))
298 (unless (zerop rem)
299 (incf colnum (- colinc rem))))))
300 colnum)
301 ((< position colnum)
302 (- colnum position))
303 ((zerop colinc) 0)
305 (- colinc
306 (rem (- position colnum) colinc))))))
308 (defun index-column (index stream)
309 (let ((column (pretty-stream-buffer-start-column stream))
310 (section-start (logical-block-section-column
311 (first (pretty-stream-blocks stream))))
312 (end-posn (index-posn index stream)))
313 (dolist (op (pretty-stream-queue-tail stream))
314 (when (>= (queued-op-posn op) end-posn)
315 (return))
316 (typecase op
317 (tab
318 (incf column
319 (compute-tab-size op
320 section-start
321 (+ column
322 (posn-index (tab-posn op)
323 stream)))))
324 ((or newline block-start)
325 (setf section-start
326 (+ column (posn-index (queued-op-posn op)
327 stream))))))
328 (+ column index)))
330 (defun expand-tabs (stream through)
331 (let ((insertions nil)
332 (additional 0)
333 (column (pretty-stream-buffer-start-column stream))
334 (section-start (logical-block-section-column
335 (first (pretty-stream-blocks stream)))))
336 (dolist (op (pretty-stream-queue-tail stream))
337 (typecase op
338 (tab
339 (let* ((index (posn-index (tab-posn op) stream))
340 (tabsize (compute-tab-size op
341 section-start
342 (+ column index))))
343 (unless (zerop tabsize)
344 (push (cons index tabsize) insertions)
345 (incf additional tabsize)
346 (incf column tabsize))))
347 ((or newline block-start)
348 (setf section-start
349 (+ column (posn-index (queued-op-posn op) stream)))))
350 (when (eq op through)
351 (return)))
352 (when insertions
353 (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
354 (new-fill-ptr (+ fill-ptr additional))
355 (buffer (pretty-stream-buffer stream))
356 (new-buffer buffer)
357 (length (length buffer))
358 (end fill-ptr))
359 (when (> new-fill-ptr length)
360 (let ((new-length (max (* length 2)
361 (+ fill-ptr
362 (floor (* additional 5) 4)))))
363 (setf new-buffer (make-string new-length))
364 (setf (pretty-stream-buffer stream) new-buffer)))
365 (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
366 (decf (pretty-stream-buffer-offset stream) additional)
367 (dolist (insertion insertions)
368 (let* ((srcpos (car insertion))
369 (amount (cdr insertion))
370 (dstpos (+ srcpos additional)))
371 (replace new-buffer buffer :start1 dstpos :start2 srcpos :end2 end)
372 (fill new-buffer #\space :start (- dstpos amount) :end dstpos)
373 (decf additional amount)
374 (setf end srcpos)))
375 (unless (eq new-buffer buffer)
376 (replace new-buffer buffer :end1 end :end2 end))))))
378 ;;;; stuff to do the actual outputting
380 (defun ensure-space-in-buffer (stream want)
381 (declare (type pretty-stream stream)
382 (type index want))
383 (let* ((buffer (pretty-stream-buffer stream))
384 (length (length buffer))
385 (fill-ptr (pretty-stream-buffer-fill-pointer stream))
386 (available (- length fill-ptr)))
387 (cond ((plusp available)
388 available)
389 ((> fill-ptr (pretty-stream-line-length stream))
390 (unless (maybe-output stream nil)
391 (output-partial-line stream))
392 (ensure-space-in-buffer stream want))
394 (let* ((new-length (max (* length 2)
395 (+ length
396 (floor (* want 5) 4))))
397 (new-buffer (make-string new-length)))
398 (setf (pretty-stream-buffer stream) new-buffer)
399 (replace new-buffer buffer :end1 fill-ptr)
400 (- new-length fill-ptr))))))
402 (defun maybe-output (stream force-newlines-p)
403 (declare (type pretty-stream stream))
404 (let ((tail (pretty-stream-queue-tail stream))
405 (output-anything nil))
406 (loop
407 (unless tail
408 (setf (pretty-stream-queue-head stream) nil)
409 (return))
410 (let ((next (pop tail)))
411 (etypecase next
412 (newline
413 (when (ecase (newline-kind next)
414 ((:literal :mandatory :linear) t)
415 (:miser (misering-p stream))
416 (:fill
417 (or (misering-p stream)
418 (> (pretty-stream-line-number stream)
419 (logical-block-section-start-line
420 (first (pretty-stream-blocks stream))))
421 (ecase (fits-on-line-p stream
422 (newline-section-end next)
423 force-newlines-p)
424 ((t) nil)
425 ((nil) t)
426 (:dont-know
427 (return))))))
428 (setf output-anything t)
429 (output-line stream next)))
430 (indentation
431 (unless (misering-p stream)
432 (set-indentation stream
433 (+ (ecase (indentation-kind next)
434 (:block
435 (logical-block-start-column
436 (car (pretty-stream-blocks stream))))
437 (:current
438 (posn-column
439 (indentation-posn next)
440 stream)))
441 (indentation-amount next)))))
442 (block-start
443 (ecase (fits-on-line-p stream (block-start-section-end next)
444 force-newlines-p)
445 ((t)
446 ;; Just nuke the whole logical block and make it look
447 ;; like one nice long literal.
448 (let ((end (block-start-block-end next)))
449 (expand-tabs stream end)
450 (setf tail (cdr (member end tail)))))
451 ((nil)
452 (really-start-logical-block
453 stream
454 (posn-column (block-start-posn next) stream)
455 (block-start-prefix next)
456 (block-start-suffix next)))
457 (:dont-know
458 (return))))
459 (block-end
460 (really-end-logical-block stream))
461 (tab
462 (expand-tabs stream next))))
463 (setf (pretty-stream-queue-tail stream) tail))
464 output-anything))
466 (defun misering-p (stream)
467 (declare (type pretty-stream stream))
468 (and *print-miser-width*
469 (<= (- (pretty-stream-line-length stream)
470 (logical-block-start-column (car (pretty-stream-blocks stream))))
471 *print-miser-width*)))
473 (defun fits-on-line-p (stream until force-newlines-p)
474 (let ((available (pretty-stream-line-length stream)))
475 (when (and (not *print-readably*)
476 (pretty-stream-print-lines stream)
477 (= (pretty-stream-print-lines stream)
478 (pretty-stream-line-number stream)))
479 (decf available 3) ; for the `` ..''
480 (decf available (logical-block-suffix-length
481 (car (pretty-stream-blocks stream)))))
482 (cond (until
483 (<= (posn-column (queued-op-posn until) stream) available))
484 (force-newlines-p nil)
485 ((> (index-column (pretty-stream-buffer-fill-pointer stream) stream)
486 available)
487 nil)
489 :dont-know))))
491 (defun output-line (stream until)
492 (declare (type pretty-stream stream)
493 (type newline until))
494 (let* ((target (pretty-stream-target stream))
495 (buffer (pretty-stream-buffer stream))
496 (kind (newline-kind until))
497 (literal-p (eq kind :literal))
498 (amount-to-consume (posn-index (newline-posn until) stream))
499 (amount-to-print
500 (if literal-p
501 amount-to-consume
502 (let ((last-non-blank
503 (position #\space buffer :end amount-to-consume
504 :from-end t :test #'char/=)))
505 (if last-non-blank
506 (1+ last-non-blank)
507 0)))))
508 (write-string buffer target :end amount-to-print)
509 (let ((line-number (pretty-stream-line-number stream)))
510 (incf line-number)
511 (when (and (not *print-readably*)
512 (pretty-stream-print-lines stream)
513 (>= line-number (pretty-stream-print-lines stream)))
514 (write-string " .." target)
515 (let ((suffix-length (logical-block-suffix-length
516 (car (pretty-stream-blocks stream)))))
517 (unless (zerop suffix-length)
518 (let* ((suffix (pretty-stream-suffix stream))
519 (len (length suffix)))
520 (write-string suffix target
521 :start (- len suffix-length)
522 :end len))))
523 (throw 'line-limit-abbreviation-happened t))
524 (setf (pretty-stream-line-number stream) line-number)
525 (write-char #\newline target)
526 (setf (pretty-stream-buffer-start-column stream) 0)
527 (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
528 (block (first (pretty-stream-blocks stream)))
529 (prefix-len
530 (if literal-p
531 (logical-block-per-line-prefix-end block)
532 (logical-block-prefix-length block)))
533 (shift (- amount-to-consume prefix-len))
534 (new-fill-ptr (- fill-ptr shift))
535 (new-buffer buffer)
536 (buffer-length (length buffer)))
537 (when (> new-fill-ptr buffer-length)
538 (setf new-buffer
539 (make-string (max (* buffer-length 2)
540 (+ buffer-length
541 (floor (* (- new-fill-ptr buffer-length)
543 4)))))
544 (setf (pretty-stream-buffer stream) new-buffer))
545 (replace new-buffer buffer
546 :start1 prefix-len :start2 amount-to-consume :end2 fill-ptr)
547 (replace new-buffer (pretty-stream-prefix stream)
548 :end1 prefix-len)
549 (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
550 (incf (pretty-stream-buffer-offset stream) shift)
551 (unless literal-p
552 (setf (logical-block-section-column block) prefix-len)
553 (setf (logical-block-section-start-line block) line-number))))))
555 (defun output-partial-line (stream)
556 (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
557 (tail (pretty-stream-queue-tail stream))
558 (count
559 (if tail
560 (posn-index (queued-op-posn (car tail)) stream)
561 fill-ptr))
562 (new-fill-ptr (- fill-ptr count))
563 (buffer (pretty-stream-buffer stream)))
564 (when (zerop count)
565 (error "Output-partial-line called when nothing can be output."))
566 (write-string buffer (pretty-stream-target stream)
567 :start 0 :end count)
568 (incf (pretty-stream-buffer-start-column stream) count)
569 (replace buffer buffer :end1 new-fill-ptr :start2 count :end2 fill-ptr)
570 (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
571 (incf (pretty-stream-buffer-offset stream) count)))
573 (defun force-pretty-output (stream)
574 (maybe-output stream nil)
575 (expand-tabs stream nil)
576 (write-string (pretty-stream-buffer stream)
577 (pretty-stream-target stream)
578 :end (pretty-stream-buffer-fill-pointer stream)))
580 ;;;; user interface to the pretty printer
582 (defun pprint-newline (kind &optional stream)
583 #!+sb-doc
584 "Output a conditional newline to STREAM (which defaults to
585 *STANDARD-OUTPUT*) if it is a pretty-printing stream, and do
586 nothing if not. KIND can be one of:
587 :LINEAR - A line break is inserted if and only if the immediately
588 containing section cannot be printed on one line.
589 :MISER - Same as LINEAR, but only if ``miser-style'' is in effect.
590 (See *PRINT-MISER-WIDTH*.)
591 :FILL - A line break is inserted if and only if either:
592 (a) the following section cannot be printed on the end of the
593 current line,
594 (b) the preceding section was not printed on a single line, or
595 (c) the immediately containing section cannot be printed on one
596 line and miser-style is in effect.
597 :MANDATORY - A line break is always inserted.
598 When a line break is inserted by any type of conditional newline, any
599 blanks that immediately precede the conditional newline are omitted
600 from the output and indentation is introduced at the beginning of the
601 next line. (See PPRINT-INDENT.)"
602 (declare (type (member :linear :miser :fill :mandatory) kind)
603 (type stream-designator stream)
604 (values null))
605 (let ((stream (out-synonym-of stream)))
606 (when (print-pretty-on-stream-p stream)
607 (enqueue-newline stream kind)))
608 nil)
610 (defun pprint-indent (relative-to n &optional stream)
611 #!+sb-doc
612 "Specify the indentation to use in the current logical block if
613 STREAM \(which defaults to *STANDARD-OUTPUT*) is a pretty-printing
614 stream and do nothing if not. (See PPRINT-LOGICAL-BLOCK.) N is the
615 indentation to use (in ems, the width of an ``m'') and RELATIVE-TO can
616 be either:
618 :BLOCK - Indent relative to the column the current logical block
619 started on.
621 :CURRENT - Indent relative to the current column.
623 The new indentation value does not take effect until the following
624 line break."
625 (declare (type (member :block :current) relative-to)
626 (type real n)
627 (type stream-designator stream)
628 (values null))
629 (let ((stream (out-synonym-of stream)))
630 (when (print-pretty-on-stream-p stream)
631 (enqueue-indent stream relative-to (truncate n))))
632 nil)
634 (defun pprint-tab (kind colnum colinc &optional stream)
635 #!+sb-doc
636 "If STREAM (which defaults to *STANDARD-OUTPUT*) is a pretty-printing
637 stream, perform tabbing based on KIND, otherwise do nothing. KIND can
638 be one of:
639 :LINE - Tab to column COLNUM. If already past COLNUM tab to the next
640 multiple of COLINC.
641 :SECTION - Same as :LINE, but count from the start of the current
642 section, not the start of the line.
643 :LINE-RELATIVE - Output COLNUM spaces, then tab to the next multiple of
644 COLINC.
645 :SECTION-RELATIVE - Same as :LINE-RELATIVE, but count from the start
646 of the current section, not the start of the line."
647 (declare (type (member :line :section :line-relative :section-relative) kind)
648 (type unsigned-byte colnum colinc)
649 (type stream-designator stream)
650 (values null))
651 (let ((stream (out-synonym-of stream)))
652 (when (print-pretty-on-stream-p stream)
653 (enqueue-tab stream kind colnum colinc)))
654 nil)
656 (defun pprint-fill (stream list &optional (colon? t) atsign?)
657 #!+sb-doc
658 "Output LIST to STREAM putting :FILL conditional newlines between each
659 element. If COLON? is NIL (defaults to T), then no parens are printed
660 around the output. ATSIGN? is ignored (but allowed so that PPRINT-FILL
661 can be used with the ~/.../ format directive."
662 (declare (ignore atsign?))
663 (pprint-logical-block (stream list
664 :prefix (if colon? "(" "")
665 :suffix (if colon? ")" ""))
666 (pprint-exit-if-list-exhausted)
667 (loop
668 (output-object (pprint-pop) stream)
669 (pprint-exit-if-list-exhausted)
670 (write-char #\space stream)
671 (pprint-newline :fill stream))))
673 (defun pprint-linear (stream list &optional (colon? t) atsign?)
674 #!+sb-doc
675 "Output LIST to STREAM putting :LINEAR conditional newlines between each
676 element. If COLON? is NIL (defaults to T), then no parens are printed
677 around the output. ATSIGN? is ignored (but allowed so that PPRINT-LINEAR
678 can be used with the ~/.../ format directive."
679 (declare (ignore atsign?))
680 (pprint-logical-block (stream list
681 :prefix (if colon? "(" "")
682 :suffix (if colon? ")" ""))
683 (pprint-exit-if-list-exhausted)
684 (loop
685 (output-object (pprint-pop) stream)
686 (pprint-exit-if-list-exhausted)
687 (write-char #\space stream)
688 (pprint-newline :linear stream))))
690 (defun pprint-tabular (stream list &optional (colon? t) atsign? tabsize)
691 #!+sb-doc
692 "Output LIST to STREAM tabbing to the next column that is an even multiple
693 of TABSIZE (which defaults to 16) between each element. :FILL style
694 conditional newlines are also output between each element. If COLON? is
695 NIL (defaults to T), then no parens are printed around the output.
696 ATSIGN? is ignored (but allowed so that PPRINT-TABULAR can be used with
697 the ~/.../ format directive."
698 (declare (ignore atsign?))
699 (pprint-logical-block (stream list
700 :prefix (if colon? "(" "")
701 :suffix (if colon? ")" ""))
702 (pprint-exit-if-list-exhausted)
703 (loop
704 (output-object (pprint-pop) stream)
705 (pprint-exit-if-list-exhausted)
706 (write-char #\space stream)
707 (pprint-tab :section-relative 0 (or tabsize 16) stream)
708 (pprint-newline :fill stream))))
710 ;;;; pprint-dispatch tables
712 (defglobal *initial-pprint-dispatch-table* nil)
714 (defstruct (pprint-dispatch-entry
715 (:constructor make-pprint-dispatch-entry (type priority fun test-fn))
716 (:copier nil) (:predicate nil))
717 ;; the type specifier for this entry
718 (type nil :type t :read-only t)
719 ;; a function to test to see whether an object is of this type,
720 ;; either (LAMBDA (OBJ) (TYPEP OBJECT TYPE)) or a builtin predicate.
721 ;; We don't bother computing this for entries in the CONS
722 ;; hash table, because we don't need it.
723 (test-fn nil :type (or function null))
724 ;; the priority for this guy
725 (priority 0 :type real :read-only t)
726 ;; T iff one of the original entries.
727 (initial-p (null *initial-pprint-dispatch-table*) :type boolean :read-only t)
728 ;; and the associated function
729 (fun nil :type callable :read-only t))
730 (def!method print-object ((entry pprint-dispatch-entry) stream)
731 (print-unreadable-object (entry stream :type t)
732 (format stream "type=~S, priority=~S~@[ [initial]~]"
733 (pprint-dispatch-entry-type entry)
734 (pprint-dispatch-entry-priority entry)
735 (pprint-dispatch-entry-initial-p entry))))
737 ;; Return T iff E1 is strictly less preferable than E2.
738 (defun entry< (e1 e2)
739 (declare (type pprint-dispatch-entry e1 e2))
740 (if (pprint-dispatch-entry-initial-p e1)
741 (if (pprint-dispatch-entry-initial-p e2)
742 (< (pprint-dispatch-entry-priority e1)
743 (pprint-dispatch-entry-priority e2))
745 (if (pprint-dispatch-entry-initial-p e2)
747 (< (pprint-dispatch-entry-priority e1)
748 (pprint-dispatch-entry-priority e2)))))
750 ;; Return the predicate for CTYPE, equivalently TYPE-SPEC.
751 ;; This used to involve rewriting into a sexpr if CONS was involved,
752 ;; since it was not an official specifier. But now it is.
753 (defun compute-test-fn (ctype type-spec function)
754 (declare (special sb!c::*backend-type-predicates*))
755 ;; Avoid compiling code for an existing structure predicate
756 (or (and (eq (info :type :kind type-spec) :instance)
757 (let ((layout (info :type :compiler-layout type-spec)))
758 (and layout
759 (let ((info (layout-info layout)))
760 (and info
761 (let ((pred (dd-predicate-name info)))
762 (and pred (fboundp pred)
763 (symbol-function pred))))))))
764 ;; avoid compiling code for CONS, ARRAY, VECTOR, etc
765 (awhen (assoc ctype sb!c::*backend-type-predicates* :test #'type=)
766 (symbol-function (cdr it)))
767 ;; OK, compile something
768 (let ((name
769 ;; Keep name as a string, because NAMED-LAMBDA with a symbol
770 ;; affects the global environment, when all you want
771 ;; is to give the lambda a human-readable label.
772 (format nil "~A-P"
773 (cond ((symbolp type-spec) type-spec)
774 ((symbolp function) function)
775 ((%fun-name function))
777 (write-to-string type-spec :pretty nil :escape nil
778 :readably nil))))))
779 (compile nil
780 `(named-lambda ,name (object) (typep object ',type-spec))))))
782 (defun copy-pprint-dispatch (&optional (table *print-pprint-dispatch*))
783 (declare (type (or pprint-dispatch-table null) table))
784 (let* ((orig (or table *initial-pprint-dispatch-table*))
785 (new (make-pprint-dispatch-table
786 (copy-list (pprint-dispatch-table-entries orig)))))
787 (replace/eql-hash-table (pprint-dispatch-table-cons-entries new)
788 (pprint-dispatch-table-cons-entries orig))
789 new))
791 (defun pprint-dispatch (object &optional (table *print-pprint-dispatch*))
792 (declare (type (or pprint-dispatch-table null) table))
793 (let* ((table (or table *initial-pprint-dispatch-table*))
794 (cons-entry
795 (and (consp object)
796 (gethash (car object)
797 (pprint-dispatch-table-cons-entries table))))
798 (entry
799 (dolist (entry (pprint-dispatch-table-entries table) cons-entry)
800 (when (and cons-entry
801 (entry< entry cons-entry))
802 (return cons-entry))
803 (when (funcall (pprint-dispatch-entry-test-fn entry) object)
804 (return entry)))))
805 (if entry
806 (values (pprint-dispatch-entry-fun entry) t)
807 (values (lambda (stream object)
808 (output-ugly-object object stream))
809 nil))))
811 (defun assert-not-standard-pprint-dispatch-table (pprint-dispatch operation)
812 (when (eq pprint-dispatch *standard-pprint-dispatch-table*)
813 (cerror "Frob it anyway!" 'standard-pprint-dispatch-table-modified-error
814 :operation operation)))
816 (defun defer-type-checker (entry)
817 (let ((saved-nonce sb!c::*type-cache-nonce*))
818 (lambda (obj)
819 (let ((nonce sb!c::*type-cache-nonce*))
820 (if (eq nonce saved-nonce)
822 (let ((ctype (specifier-type (pprint-dispatch-entry-type entry))))
823 (setq saved-nonce nonce)
824 (if (testable-type-p ctype)
825 (funcall (setf (pprint-dispatch-entry-test-fn entry)
826 (compute-test-fn
827 ctype
828 (pprint-dispatch-entry-type entry)
829 (pprint-dispatch-entry-fun entry)))
830 obj)
831 nil)))))))
833 ;; The dispatch mechanism is not quite sophisticated enough to have a guard
834 ;; condition on CONS entries. One place this would impact is that you could
835 ;; write the full matcher for QUOTE as just a type-specifier. It can be done
836 ;; now, but using the non-cons table entails linear scan.
837 ;; A test-fn in the cons table would require storing multiple entries per
838 ;; key though because any might fail. Conceivably you could have
839 ;; (cons (eql foo) cons) and (cons (eql foo) bit-vector) as two FOO entries.
840 (defun set-pprint-dispatch (type function &optional
841 (priority 0) (table *print-pprint-dispatch*))
842 (declare (type (or null callable) function)
843 (type real priority)
844 (type pprint-dispatch-table table))
845 (declare (explicit-check))
846 (/show0 "entering SET-PPRINT-DISPATCH, TYPE=...")
847 (/hexstr type)
848 (assert-not-standard-pprint-dispatch-table table 'set-pprint-dispatch)
849 (let* ((ctype (or (handler-bind
850 ((parse-unknown-type
851 (lambda (c)
852 (warn "~S is not a recognized type specifier"
853 (parse-unknown-type-specifier c)))))
854 (sb!c::careful-specifier-type type))
855 (error "~S is not a valid type-specifier" type)))
856 (consp (and (cons-type-p ctype)
857 (eq (cons-type-cdr-type ctype) *universal-type*)
858 (member-type-p (cons-type-car-type ctype))))
859 (disabled-p (not (testable-type-p ctype)))
860 (entry (if function
861 (make-pprint-dispatch-entry
862 type priority function
863 (unless (or consp disabled-p)
864 (compute-test-fn ctype type function))))))
865 (when (and function disabled-p)
866 ;; a DISABLED-P test function has to close over the ENTRY
867 (setf (pprint-dispatch-entry-test-fn entry) (defer-type-checker entry)))
868 (if consp
869 (let ((hashtable (pprint-dispatch-table-cons-entries table)))
870 (dolist (key (member-type-members (cons-type-car-type ctype)))
871 (if function
872 (setf (gethash key hashtable) entry)
873 (remhash key hashtable))))
874 (setf (pprint-dispatch-table-entries table)
875 (let ((list (delete type (pprint-dispatch-table-entries table)
876 :key #'pprint-dispatch-entry-type
877 :test #'equal)))
878 (if function
879 ;; ENTRY< is T if lower in priority, which should sort to
880 ;; the end, but MERGE's predicate wants T for the (a,b) pair
881 ;; if 'a' should go in front of 'b', so swap them.
882 ;; (COMPLEMENT #'entry<) is unstable wrt insertion order.
883 (merge 'list list (list entry) (lambda (a b) (entry< b a)))
884 list)))))
885 (/show0 "about to return NIL from SET-PPRINT-DISPATCH")
886 nil)
888 ;;;; standard pretty-printing routines
890 (defun pprint-array (stream array)
891 (cond ((and (null *print-array*) (null *print-readably*))
892 (output-ugly-object array stream))
893 ((and *print-readably*
894 (not (array-readably-printable-p array)))
895 (if *read-eval*
896 (if (vectorp array)
897 (sb!impl::output-unreadable-vector-readably array stream)
898 (sb!impl::output-unreadable-array-readably array stream))
899 (print-not-readable-error array stream)))
900 ((vectorp array)
901 (pprint-vector stream array))
903 (pprint-multi-dim-array stream array))))
905 (defun pprint-vector (stream vector)
906 (pprint-logical-block (stream nil :prefix "#(" :suffix ")")
907 (dotimes (i (length vector))
908 (unless (zerop i)
909 (format stream " ~:_"))
910 (pprint-pop)
911 (output-object (aref vector i) stream))))
913 (defun pprint-multi-dim-array (stream array)
914 (funcall (formatter "#~DA") stream (array-rank array))
915 (with-array-data ((data array) (start) (end))
916 (declare (ignore end))
917 (labels ((output-guts (stream index dimensions)
918 (if (null dimensions)
919 (output-object (aref data index) stream)
920 (pprint-logical-block
921 (stream nil :prefix "(" :suffix ")")
922 (let ((dim (car dimensions)))
923 (unless (zerop dim)
924 (let* ((dims (cdr dimensions))
925 (index index)
926 (step (reduce #'* dims))
927 (count 0))
928 (loop
929 (pprint-pop)
930 (output-guts stream index dims)
931 (when (= (incf count) dim)
932 (return))
933 (write-char #\space stream)
934 (pprint-newline (if dims :linear :fill)
935 stream)
936 (incf index step)))))))))
937 (output-guts stream start (array-dimensions array)))))
939 (defun pprint-lambda-list (stream lambda-list &rest noise)
940 (declare (ignore noise))
941 (pprint-logical-block (stream lambda-list :prefix "(" :suffix ")")
942 (let ((state :required)
943 (first t))
944 (loop
945 (pprint-exit-if-list-exhausted)
946 (unless first
947 (write-char #\space stream))
948 (let ((arg (pprint-pop)))
949 (case arg
950 ((&optional &aux)
951 (setf state :optional)
952 (pprint-newline :linear stream))
953 ((&rest &body)
954 (setf state :required)
955 (pprint-newline :linear stream))
956 (&key
957 (setf state :key)
958 (pprint-newline :linear stream))
960 (pprint-newline :fill stream)))
961 (ecase state
962 (:required
963 ;; Make sure method specializers like
964 ;; (function (eql #'foo)) are printed right
965 (pprint-logical-block
966 (stream arg :prefix "(" :suffix ")")
967 (pprint-exit-if-list-exhausted)
968 (loop
969 (output-object (pprint-pop) stream)
970 (pprint-exit-if-list-exhausted)
971 (write-char #\space stream)
972 (pprint-newline :linear stream))))
973 ((:optional :key)
974 (pprint-logical-block
975 (stream arg :prefix "(" :suffix ")")
976 (pprint-exit-if-list-exhausted)
977 (if (eq state :key)
978 (pprint-logical-block
979 (stream (pprint-pop) :prefix "(" :suffix ")")
980 (pprint-exit-if-list-exhausted)
981 (output-object (pprint-pop) stream)
982 (pprint-exit-if-list-exhausted)
983 (write-char #\space stream)
984 (pprint-newline :fill stream)
985 (output-object (pprint-pop) stream)
986 (loop
987 (pprint-exit-if-list-exhausted)
988 (write-char #\space stream)
989 (pprint-newline :fill stream)
990 (output-object (pprint-pop) stream)))
991 (output-object (pprint-pop) stream))
992 (loop
993 (pprint-exit-if-list-exhausted)
994 (write-char #\space stream)
995 (pprint-newline :linear stream)
996 (output-object (pprint-pop) stream))))))
997 (setf first nil)))))
999 (defun pprint-lambda (stream list &rest noise)
1000 (declare (ignore noise))
1001 (funcall (formatter
1002 ;; KLUDGE: This format string, and other format strings which also
1003 ;; refer to SB!PRETTY, rely on the current SBCL not-quite-ANSI
1004 ;; behavior of FORMATTER in order to make code which survives the
1005 ;; transition when SB!PRETTY is renamed to SB-PRETTY after cold
1006 ;; init. (ANSI says that the FORMATTER functions should be
1007 ;; equivalent to the format string, but the SBCL FORMATTER
1008 ;; functions contain references to package objects, not package
1009 ;; names, so they keep right on going if the packages are renamed.)
1010 ;; If our FORMATTER behavior is ever made more compliant, the code
1011 ;; here will have to change. -- WHN 19991207
1012 "~:<~^~W~^~3I ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
1013 stream
1014 list))
1016 (defun pprint-block (stream list &rest noise)
1017 (declare (ignore noise))
1018 (funcall (formatter "~:<~^~W~^~3I ~:_~W~1I~@{ ~_~W~}~:>") stream list))
1020 (defun pprint-flet (stream list &rest noise)
1021 (declare (ignore noise))
1022 (if (and (consp list)
1023 (consp (cdr list))
1024 (cddr list)
1025 ;; Filter out (FLET FOO :IN BAR) names.
1026 (and (consp (cddr list))
1027 (not (eq :in (third list)))))
1028 (funcall (formatter
1029 "~:<~^~W~^ ~@_~:<~@{~:<~^~W~^~3I ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~:@_~@{~W~^ ~_~}~:>~^ ~_~}~:>~1I~@:_~@{~W~^ ~_~}~:>")
1030 stream
1031 list)
1032 ;; for printing function names like (flet foo)
1033 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1034 (pprint-exit-if-list-exhausted)
1035 (write (pprint-pop) :stream stream)
1036 (loop
1037 (pprint-exit-if-list-exhausted)
1038 (write-char #\space stream)
1039 (write (pprint-pop) :stream stream)))))
1041 (defun pprint-let (stream list &rest noise)
1042 (declare (ignore noise))
1043 (funcall (formatter "~:<~^~W~^ ~@_~:<~@{~:<~^~W~@{ ~_~W~}~:>~^ ~_~}~:>~1I~:@_~@{~W~^ ~_~}~:>")
1044 stream
1045 list))
1047 (defun pprint-progn (stream list &rest noise)
1048 (declare (ignore noise))
1049 (pprint-linear stream list))
1051 (defun pprint-progv (stream list &rest noise)
1052 (declare (ignore noise))
1053 (funcall (formatter "~:<~^~W~^~3I ~_~W~^ ~_~W~^~1I~@{ ~_~W~}~:>")
1054 stream list))
1056 (defun pprint-prog2 (stream list &rest noise)
1057 (declare (ignore noise))
1058 (funcall (formatter "~:<~^~W~^~3I ~:_~W~^ ~_~W~^~1I~@{ ~_~W~}~:>")
1059 stream list))
1061 (defun pprint-unquoting-comma (stream obj &rest noise)
1062 (declare (ignore noise))
1063 (write-string (svref #("," ",." ",@") (comma-kind obj)) stream)
1064 (when (eql (comma-kind obj) 0)
1065 ;; Ensure a space is written before any output that would change the meaning
1066 ;; of the preceding the comma to ",." or ",@" such as a symbol named "@BAR".
1067 (setf (pretty-stream-char-out-oneshot-hook stream)
1068 (lambda (stream char)
1069 (when (member char '(#\. #\@))
1070 (write-char #\Space stream)))))
1071 (output-object (comma-expr obj) stream))
1073 (defvar *pprint-quote-with-syntactic-sugar* t)
1075 (defun pprint-quote (stream list &rest noise)
1076 (declare (ignore noise))
1077 (when (and (listp list) (singleton-p (cdr list)))
1078 (let* ((pretty-p nil)
1079 (sigil (case (car list)
1080 (function "#'")
1081 ;; QUASIQUOTE can't choose not to print prettily.
1082 ;; Wrongly nested commas beget unreadable sexprs.
1083 (quasiquote (setq pretty-p t) "`")
1084 (t "'")))) ; ordinary QUOTE
1085 (when (or pretty-p *pprint-quote-with-syntactic-sugar*)
1086 (write-string sigil stream)
1087 (return-from pprint-quote (output-object (cadr list) stream)))))
1088 (pprint-fill stream list))
1090 (defun pprint-declare (stream list &rest noise)
1091 (declare (ignore noise))
1092 ;; Make sure to print (DECLARE (FUNCTION F)) not (DECLARE #'A).
1093 (let ((*pprint-quote-with-syntactic-sugar* nil))
1094 (pprint-spread-fun-call stream list)))
1096 ;;; Try to print every variable-value pair on one line; if that doesn't
1097 ;;; work print the value indented by 2 spaces:
1099 ;;; (setq foo bar
1100 ;;; quux xoo)
1101 ;;; vs.
1102 ;;; (setf foo
1103 ;;; (long form ...)
1104 ;;; quux xoo)
1105 (defun pprint-setq (stream list &rest noise)
1106 (declare (ignore noise))
1107 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1108 (pprint-exit-if-list-exhausted)
1109 (output-object (pprint-pop) stream)
1110 (pprint-exit-if-list-exhausted)
1111 (write-char #\space stream)
1112 (unless (listp (cdr list))
1113 (write-string ". " stream))
1114 (pprint-newline :miser stream)
1115 (pprint-logical-block (stream (cdr list) :prefix "" :suffix "")
1116 (loop
1117 (pprint-indent :block 2 stream)
1118 (output-object (pprint-pop) stream)
1119 (pprint-exit-if-list-exhausted)
1120 (write-char #\space stream)
1121 (pprint-newline :fill stream)
1122 (pprint-indent :block 0 stream)
1123 (output-object (pprint-pop) stream)
1124 (pprint-exit-if-list-exhausted)
1125 (write-char #\space stream)
1126 (pprint-newline :mandatory stream)))))
1128 (eval-when (:compile-toplevel :execute)
1129 (sb!xc:defmacro pprint-tagbody-guts (stream)
1130 `(loop
1131 (pprint-exit-if-list-exhausted)
1132 (write-char #\space ,stream)
1133 (let ((form-or-tag (pprint-pop)))
1134 (pprint-indent :block
1135 (if (atom form-or-tag) 0 1)
1136 ,stream)
1137 (pprint-newline :linear ,stream)
1138 (output-object form-or-tag ,stream)))))
1140 (defun pprint-tagbody (stream list &rest noise)
1141 (declare (ignore noise))
1142 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1143 (pprint-exit-if-list-exhausted)
1144 (output-object (pprint-pop) stream)
1145 (pprint-tagbody-guts stream)))
1147 (defun pprint-case (stream list &rest noise)
1148 (declare (ignore noise))
1149 (funcall (formatter
1150 "~:<~^~W~^ ~3I~:_~W~1I~@{ ~_~:<~^~:/SB!PRETTY:PPRINT-FILL/~^~@{ ~_~W~}~:>~}~:>")
1151 stream
1152 list))
1154 (defun pprint-defun (stream list &rest noise)
1155 (declare (ignore noise))
1156 (funcall (formatter
1157 "~:<~^~W~^ ~@_~:I~W~^ ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
1158 stream
1159 list))
1161 (defun pprint-defmethod (stream list &rest noise)
1162 (declare (ignore noise))
1163 (if (and (consp (cdr list))
1164 (consp (cddr list))
1165 (consp (third list)))
1166 (pprint-defun stream list)
1167 (funcall (formatter
1168 "~:<~^~W~^ ~@_~:I~W~^ ~W~^ ~:_~/SB!PRETTY:PPRINT-LAMBDA-LIST/~1I~@{ ~_~W~}~:>")
1169 stream
1170 list)))
1172 (defun pprint-defpackage (stream list &rest noise)
1173 (declare (ignore noise))
1174 (funcall (formatter
1175 "~:<~W~^ ~3I~:_~W~^~1I~@{~:@_~:<~^~W~^ ~:I~@_~@{~W~^ ~_~}~:>~}~:>")
1176 stream
1177 list))
1179 (defun pprint-destructuring-bind (stream list &rest noise)
1180 (declare (ignore noise))
1181 (funcall (formatter
1182 "~:<~^~W~^~3I ~_~:/SB!PRETTY:PPRINT-LAMBDA-LIST/~^ ~_~W~^~1I~@{ ~_~W~}~:>")
1183 stream list))
1185 (defun pprint-do (stream list &rest noise)
1186 (declare (ignore noise))
1187 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1188 (pprint-exit-if-list-exhausted)
1189 (output-object (pprint-pop) stream)
1190 (pprint-exit-if-list-exhausted)
1191 (write-char #\space stream)
1192 (pprint-indent :current 0 stream)
1193 (funcall (formatter "~:<~@{~:<~^~W~^ ~@_~:I~W~@{ ~_~W~}~:>~^~:@_~}~:>")
1194 stream
1195 (pprint-pop))
1196 (pprint-exit-if-list-exhausted)
1197 (write-char #\space stream)
1198 (pprint-newline :linear stream)
1199 (pprint-linear stream (pprint-pop))
1200 (pprint-tagbody-guts stream)))
1202 (defun pprint-dolist (stream list &rest noise)
1203 (declare (ignore noise))
1204 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1205 (pprint-exit-if-list-exhausted)
1206 (output-object (pprint-pop) stream)
1207 (pprint-exit-if-list-exhausted)
1208 (pprint-indent :block 3 stream)
1209 (write-char #\space stream)
1210 (pprint-newline :fill stream)
1211 (funcall (formatter "~:<~^~W~^ ~:_~:I~W~@{ ~_~W~}~:>")
1212 stream
1213 (pprint-pop))
1214 (pprint-tagbody-guts stream)))
1216 (defun pprint-typecase (stream list &rest noise)
1217 (declare (ignore noise))
1218 (funcall (formatter
1219 "~:<~^~W~^ ~3I~:_~W~1I~@{ ~_~:<~^~W~^~@{ ~_~W~}~:>~}~:>")
1220 stream
1221 list))
1223 (defun pprint-prog (stream list &rest noise)
1224 (declare (ignore noise))
1225 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1226 (pprint-exit-if-list-exhausted)
1227 (output-object (pprint-pop) stream)
1228 (pprint-exit-if-list-exhausted)
1229 (write-char #\space stream)
1230 (pprint-newline :miser stream)
1231 (pprint-fill stream (pprint-pop))
1232 (pprint-tagbody-guts stream)))
1234 ;;; Each clause in this list will get its own line.
1235 ;;; FIXME: (LOOP for x in list summing (f x) into count finally ...)
1236 ;;; puts a newline in between INTO and COUNT.
1237 ;;; It would be awesome to have code in common with the macro
1238 ;;; the properly represents each clauses.
1239 (defvar *loop-seperating-clauses*
1240 '(:and
1241 :with :for
1242 :initially :finally
1243 :do :doing
1244 :collect :collecting
1245 :append :appending
1246 :nconc :nconcing
1247 :count :counting
1248 :sum :summing
1249 :maximize :maximizing
1250 :minimize :minimizing
1251 :if :when :unless :end
1252 :for :while :until :repeat :always :never :thereis
1255 (defun pprint-extended-loop (stream list)
1256 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1257 (output-object (pprint-pop) stream)
1258 (pprint-exit-if-list-exhausted)
1259 (write-char #\space stream)
1260 (pprint-indent :current 0 stream)
1261 (output-object (pprint-pop) stream)
1262 (pprint-exit-if-list-exhausted)
1263 (write-char #\space stream)
1264 (loop for thing = (pprint-pop)
1265 when (and (symbolp thing)
1266 (member thing *loop-seperating-clauses* :test #'string=))
1267 do (pprint-newline :mandatory stream)
1268 do (output-object thing stream)
1269 do (pprint-exit-if-list-exhausted)
1270 do (write-char #\space stream))))
1272 (defun pprint-loop (stream list &rest noise)
1273 (declare (ignore noise))
1274 (destructuring-bind (loop-symbol . clauses) list
1275 (declare (ignore loop-symbol))
1276 (if (or (atom clauses) (consp (car clauses)))
1277 (pprint-spread-fun-call stream list)
1278 (pprint-extended-loop stream list))))
1280 (defun pprint-if (stream list &rest noise)
1281 (declare (ignore noise))
1282 ;; Indent after the ``predicate'' form, and the ``then'' form.
1283 (funcall (formatter "~:<~^~W~^ ~:I~W~^ ~:@_~@{~W~^ ~:@_~}~:>")
1284 stream
1285 list))
1287 (defun pprint-fun-call (stream list &rest noise)
1288 (declare (ignore noise))
1289 (funcall (formatter "~:<~^~W~^ ~:_~:I~@{~W~^ ~:_~}~:>")
1290 stream
1291 list))
1293 (defun pprint-spread-fun-call (stream list &rest noise)
1294 (declare (ignore noise))
1295 ;; Similiar to PPRINT-FUN-CALL but emit a mandatory newline after
1296 ;; each parameter. I.e. spread out each parameter on its own line.
1297 (funcall (formatter "~:<~^~W~^ ~:_~:I~@{~W~^ ~:@_~}~:>")
1298 stream
1299 list))
1301 (defun pprint-data-list (stream list &rest noise)
1302 (declare (ignore noise))
1303 (pprint-fill stream list))
1305 ;;; Return the number of positional arguments that macro NAME accepts
1306 ;;; by looking for &BODY. A dotted list is indented as it it had &BODY.
1307 ;;; ANSI says that a dotted tail is like &REST, but the pretty-printer
1308 ;;; can do whatever it likes anyway. I happen to think this makes sense.
1309 (defun macro-indentation (name)
1310 (do ((n 0)
1311 (list (%fun-lambda-list (macro-function name)) (cdr list)))
1312 ((or (atom list) (eq (car list) '&body))
1313 (if (null list) nil n))
1314 (unless (eq (car list) '&optional)
1315 (incf n))))
1317 ;;; Pretty-Print macros by looking where &BODY appears in a macro's
1318 ;;; lambda-list.
1319 (defun pprint-macro-call (stream list &rest noise)
1320 (declare (ignore noise))
1321 (let ((indentation (and (car list) (macro-indentation (car list)))))
1322 (unless indentation
1323 (return-from pprint-macro-call
1324 (pprint-fun-call stream list)))
1325 (pprint-logical-block (stream list :prefix "(" :suffix ")")
1326 (output-object (pprint-pop) stream)
1327 (pprint-exit-if-list-exhausted)
1328 (write-char #\space stream)
1329 (loop for indent from 0 below indentation do
1330 (cond
1331 ;; Place the very first argument next to the macro name
1332 ((zerop indent)
1333 (output-object (pprint-pop) stream)
1334 (pprint-exit-if-list-exhausted))
1335 ;; Indent any other non-body argument by the same
1336 ;; amount. It's what Emacs seems to do, too.
1338 (pprint-indent :block 3 stream)
1339 (pprint-newline :mandatory stream)
1340 (output-object (pprint-pop) stream)
1341 (pprint-exit-if-list-exhausted))))
1342 ;; Indent back for the body.
1343 (pprint-indent :block 1 stream)
1344 (pprint-newline :mandatory stream)
1345 (loop
1346 (output-object (pprint-pop) stream)
1347 (pprint-exit-if-list-exhausted)
1348 (pprint-newline :mandatory stream)))))
1350 ;;;; the interface seen by regular (ugly) printer and initialization routines
1352 (eval-when (:compile-toplevel :execute)
1353 (sb!xc:defmacro with-pretty-stream ((stream-var
1354 &optional (stream-expression stream-var))
1355 &body body)
1356 (let ((flet-name (sb!xc:gensym "WITH-PRETTY-STREAM")))
1357 `(flet ((,flet-name (,stream-var)
1358 ,@body))
1359 (let ((stream ,stream-expression))
1360 (if (pretty-stream-p stream)
1361 (,flet-name stream)
1362 (catch 'line-limit-abbreviation-happened
1363 (let ((stream (make-pretty-stream stream)))
1364 (,flet-name stream)
1365 (force-pretty-output stream)))))
1366 nil))))
1368 ;;; OUTPUT-PRETTY-OBJECT is called by OUTPUT-OBJECT when
1369 ;;; *PRINT-PRETTY* is true.
1370 (defun output-pretty-object (object stream)
1371 (multiple-value-bind (fun pretty) (pprint-dispatch object)
1372 (if pretty
1373 (with-pretty-stream (stream)
1374 (funcall fun stream object))
1375 ;; No point in consing up a pretty stream if we are not using pretty
1376 ;; printing the object after all.
1377 (output-ugly-object object stream))))
1379 (defun call-logical-block-printer (proc stream prefix per-line-p suffix
1380 &optional (object nil obj-supplied-p))
1381 ;; PREFIX and SUFFIX will be checked for stringness by START-LOGICAL-BLOCK.
1382 ;; Doing it here would be more strict, but I really don't think it's worth
1383 ;; an extra check. The only observable difference would occur when you have
1384 ;; a non-list object which bypasses START-LOGICAL-BLOCK.
1385 ;; Also, START-LOGICAL-BLOCK could become an FLET inside here.
1386 (declare (function proc))
1387 (with-pretty-stream (stream (out-synonym-of stream))
1388 (if (or (not (listp object)) ; implies obj-supplied-p
1389 (and (eq (car object) 'quasiquote)
1390 ;; We can only bail out from printing this logical block
1391 ;; if the quasiquote printer would *NOT* punt.
1392 ;; If it would punt, then we have to forge ahead.
1393 (singleton-p (cdr object))))
1394 ;; the spec says "If object is not a list, it is printed using WRITE"
1395 ;; but I guess this is close enough.
1396 (output-object object stream)
1397 (dx-let ((state (cons 0 stream)))
1398 (if obj-supplied-p
1399 (with-circularity-detection (object stream)
1400 (descend-into (stream)
1401 (start-logical-block stream prefix per-line-p suffix)
1402 (funcall proc object state stream)
1403 ;; Comment preserved for posterity:
1404 ;; FIXME: Don't we need UNWIND-PROTECT to ensure this
1405 ;; always gets executed?
1406 ;; I think not because I wouldn't characterize this as
1407 ;; "cleanup" code. If and only if you follow the accepted
1408 ;; protocol for defining and using print functions should
1409 ;; the behavior be expected to be reasonable and predictable.
1410 ;; Throwing to LINE-LIMIT-ABBREVIATION-HAPPENED is designed
1411 ;; to do the right thing, and printing should not generally
1412 ;; continue to have side-effects if the user felt it necessary
1413 ;; to nonlocally exit in an unexpected way for other reasons.
1414 (end-logical-block stream)))
1415 (descend-into (stream)
1416 (start-logical-block stream prefix per-line-p suffix)
1417 (funcall proc state stream)
1418 (end-logical-block stream)))))))
1420 ;; Return non-nil if we should keep printing within the logical-block,
1421 ;; or NIL to stop printing due to non-list, length cutoff, or circularity.
1422 (defun pprint-length-check (obj state)
1423 (let ((stream (cdr state)))
1424 (cond ((or (not (listp obj))
1425 ;; Consider (A . `(,B C)) = (A QUASIQUOTE ,B C)
1426 ;; We have to detect this and print as the form on the left,
1427 ;; since pretty commas with no containing #\` will be unreadable
1428 ;; due to a nesting error.
1429 (and (eq (car obj) 'quasiquote) (singleton-p (cdr obj))))
1430 (write-string ". " stream)
1431 (output-object obj stream)
1432 nil)
1433 ((and (not *print-readably*) (eql (car state) *print-length*))
1434 (write-string "..." stream)
1435 nil)
1436 ((and obj
1437 (plusp (car state))
1438 (check-for-circularity obj nil :logical-block))
1439 (write-string ". " stream)
1440 (output-object obj stream)
1441 nil)
1443 (incf (car state))))))
1445 ;; As above, but for logical blocks with an unspecific object.
1446 (defun pprint-length-check* (state)
1447 (let ((stream (cdr state)))
1448 (cond ((and (not *print-readably*) (eql (car state) *print-length*))
1449 (write-string "..." stream)
1450 nil)
1452 (incf (car state))))))
1454 (defun !pprint-cold-init ()
1455 (/show0 "entering !PPRINT-COLD-INIT")
1456 ;; Kludge: We set *STANDARD-PP-D-TABLE* to a new table even though
1457 ;; it's going to be set to a copy of *INITIAL-PP-D-T* below because
1458 ;; it's used in WITH-STANDARD-IO-SYNTAX, and condition reportery
1459 ;; possibly performed in the following extent may use W-S-IO-SYNTAX.
1460 (setf *standard-pprint-dispatch-table* (make-pprint-dispatch-table))
1461 (setf *initial-pprint-dispatch-table* nil)
1462 (let ((*print-pprint-dispatch* (make-pprint-dispatch-table)))
1463 (/show0 "doing SET-PPRINT-DISPATCH for regular types")
1464 (set-pprint-dispatch '(and array (not (or string bit-vector))) 'pprint-array)
1465 ;; MACRO-FUNCTION must have effectively higher priority than FBOUNDP.
1466 ;; The implementation happens to check identical priorities in the order added,
1467 ;; but that's unspecified behavior. Both must be _strictly_ lower than the
1468 ;; default cons entries though.
1469 (set-pprint-dispatch '(cons (and symbol (satisfies macro-function)))
1470 'pprint-macro-call -1)
1471 (set-pprint-dispatch '(cons (and symbol (satisfies fboundp)))
1472 'pprint-fun-call -1)
1473 (set-pprint-dispatch '(cons symbol)
1474 'pprint-data-list -2)
1475 (set-pprint-dispatch 'cons 'pprint-fill -2)
1476 (set-pprint-dispatch 'sb!impl::comma 'pprint-unquoting-comma -3)
1477 ;; cons cells with interesting things for the car
1478 (/show0 "doing SET-PPRINT-DISPATCH for CONS with interesting CAR")
1480 (dolist (magic-form '((lambda pprint-lambda)
1481 ((declare declaim) pprint-declare)
1483 ;; special forms
1484 ((block catch return-from throw eval-when
1485 multiple-value-call multiple-value-prog1
1486 unwind-protect) pprint-block)
1487 ((flet labels macrolet dx-flet) pprint-flet)
1488 ((function quasiquote quote) pprint-quote)
1489 (if pprint-if)
1490 ((let let* symbol-macrolet dx-let) pprint-let)
1491 ((locally progn) pprint-progn)
1492 (progv pprint-progv)
1493 ((setq psetq setf psetf) pprint-setq)
1494 (tagbody pprint-tagbody)
1496 ;; macros
1497 ((case ccase ecase) pprint-case)
1498 ((ctypecase etypecase typecase) pprint-typecase)
1499 ((defconstant defparameter defstruct defvar)
1500 pprint-block)
1501 ((define-modify-macro define-setf-expander
1502 defmacro defsetf deftype defun) pprint-defun)
1503 (defmethod pprint-defmethod)
1504 (defpackage pprint-defpackage)
1505 (destructuring-bind pprint-destructuring-bind)
1506 ((do do*) pprint-do)
1507 ((do-all-symbols do-external-symbols do-symbols
1508 dolist dotimes) pprint-dolist)
1509 #+nil (handler-bind ...)
1510 #+nil (handler-case ...)
1511 (loop pprint-loop)
1512 ((multiple-value-bind prog2) pprint-prog2)
1513 ((multiple-value-setq prog1 pprint-logical-block
1514 print-unreadable-object prog1) pprint-block)
1515 ((prog prog*) pprint-prog)
1516 #+nil (restart-bind ...)
1517 #+nil (restart-case ...)
1518 ((step time) pprint-progn)
1519 ((unless when) pprint-block)
1520 #+nil (with-condition-restarts ...)
1521 ((with-compilation-unit with-simple-restart
1522 with-hash-table-iterator with-package-iterator
1523 with-input-from-string with-output-to-string
1524 with-open-file with-open-stream) pprint-block)
1525 (with-standard-io-syntax pprint-progn)))
1527 ;; Grouping some symbols together in the above list looks pretty.
1528 ;; The sharing of dispatch entries is inconsequential.
1529 (set-pprint-dispatch `(cons (member ,@(ensure-list (first magic-form))))
1530 (second magic-form)))
1531 (setf *initial-pprint-dispatch-table* *print-pprint-dispatch*))
1533 (setf *standard-pprint-dispatch-table*
1534 (copy-pprint-dispatch *initial-pprint-dispatch-table*))
1535 (setf *print-pprint-dispatch*
1536 (copy-pprint-dispatch *initial-pprint-dispatch-table*))
1537 (setf *print-pretty* t))