*PRINT-ESCAPE*.")
(defvar *print-escape* T
#!+sb-doc
- "Flag which indicates that slashification is on. See the manual")
+ "Should we print in a reasonably machine-readable way? (possibly
+ overridden by *PRINT-READABLY*)")
(defvar *print-pretty* nil ; (set later when pretty-printer is initialized)
#!+sb-doc
- "Flag which indicates that pretty printing is to be used")
+ "Should pretty printing be used?")
(defvar *print-base* 10.
#!+sb-doc
- "The output base for integers and rationals.")
+ "the output base for RATIONALs (including integers)")
(defvar *print-radix* nil
#!+sb-doc
- "This flag requests to verify base when printing rationals.")
+ "Should base be verified when printing RATIONALs?")
(defvar *print-level* nil
#!+sb-doc
- "How many levels deep to print. Unlimited if null.")
+ "How many levels should be printed before abbreviating with \"#\"?")
(defvar *print-length* nil
#!+sb-doc
- "How many elements to print on each level. Unlimited if null.")
+ "How many elements at any level should be printed before abbreviating
+ with \"...\"?")
(defvar *print-circle* nil
#!+sb-doc
- "Whether to worry about circular list structures. See the manual.")
+ "Should we use #n= and #n# notation to preserve uniqueness in general (and
+ circularity in particular) when printing?")
(defvar *print-case* :upcase
#!+sb-doc
- "What kind of case the printer should use by default")
+ "What case should the printer should use default?")
(defvar *print-array* t
#!+sb-doc
- "Whether the array should print its guts out")
+ "Should the contents of arrays be printed?")
(defvar *print-gensym* t
#!+sb-doc
- "If true, symbols with no home package are printed with a #: prefix.
- If false, no prefix is printed.")
+ "Should #: prefixes be used when printing symbols with null SYMBOL-PACKAGE?")
(defvar *print-lines* nil
#!+sb-doc
- "The maximum number of lines to print. If NIL, unlimited.")
+ "the maximum number of lines to print per object")
(defvar *print-right-margin* nil
#!+sb-doc
- "The position of the right margin in ems. If NIL, try to determine this
- from the stream in use.")
+ "the position of the right margin in ems (for pretty-printing)")
(defvar *print-miser-width* nil
#!+sb-doc
"If the remaining space between the current column and the right margin
turned off. If NIL, never use miser mode.")
(defvar *print-pprint-dispatch* nil
#!+sb-doc
- "The pprint-dispatch-table that controls how to pretty print objects. See
- COPY-PPRINT-DISPATH, PPRINT-DISPATCH, and SET-PPRINT-DISPATCH.")
+ "the pprint-dispatch-table that controls how to pretty-print objects")
(defmacro with-standard-io-syntax (&body body)
#!+sb-doc
*READ-DEFAULT-FLOAT-FORMAT* SINGLE-FLOAT
*READ-EVAL* T
*READ-SUPPRESS* NIL
- *READTABLE* the standard readtable."
+ *READTABLE* the standard readtable"
`(%with-standard-io-syntax #'(lambda () ,@body)))
(defun %with-standard-io-syntax (function)
(*read-eval* t)
(*read-suppress* nil)
;; FIXME: It doesn't seem like a good idea to expose our
- ;; disaster-recovery *STANDARD-READTABLE* here. Perhaps we
- ;; should do a COPY-READTABLE? The consing would be unfortunate,
- ;; though.
+ ;; disaster-recovery *STANDARD-READTABLE* here. What if some
+ ;; enterprising user corrupts the disaster-recovery readtable
+ ;; by doing destructive readtable operations within
+ ;; WITH-STANDARD-IO-SYNTAX? Perhaps we should do a
+ ;; COPY-READTABLE? The consing would be unfortunate, though.
(*readtable* *standard-readtable*))
(funcall function)))
\f
((:pprint-dispatch *print-pprint-dispatch*)
*print-pprint-dispatch*))
#!+sb-doc
- "Outputs OBJECT to the specified stream, defaulting to *STANDARD-OUTPUT*"
+ "Output OBJECT to the specified stream, defaulting to *STANDARD-OUTPUT*"
(output-object object (out-synonym-of stream))
object)
(defun prin1 (object &optional stream)
#!+sb-doc
- "Outputs a mostly READable printed representation of OBJECT on the specified
+ "Output a mostly READable printed representation of OBJECT on the specified
STREAM."
(let ((*print-escape* T))
(output-object object (out-synonym-of stream)))
(defun princ (object &optional stream)
#!+sb-doc
- "Outputs an aesthetic but not necessarily READable printed representation
+ "Output an aesthetic but not necessarily READable printed representation
of OBJECT on the specified STREAM."
(let ((*print-escape* NIL)
(*print-readably* NIL))
(defun print (object &optional stream)
#!+sb-doc
- "Outputs a terpri, the mostly READable printed represenation of OBJECT, and
+ "Output a newline, the mostly READable printed representation of OBJECT, and
space to the specified STREAM."
(let ((stream (out-synonym-of stream)))
(terpri stream)
(defun pprint (object &optional stream)
#!+sb-doc
- "Prettily outputs OBJECT preceded by a newline."
+ "Prettily output OBJECT preceded by a newline."
(let ((*print-pretty* t)
(*print-escape* t)
(stream (out-synonym-of stream)))
((:pprint-dispatch *print-pprint-dispatch*)
*print-pprint-dispatch*))
#!+sb-doc
- "Returns the printed representation of OBJECT as a string."
+ "Return the printed representation of OBJECT as a string."
(stringify-object object))
(defun prin1-to-string (object)
#!+sb-doc
- "Returns the printed representation of OBJECT as a string with
+ "Return the printed representation of OBJECT as a string with
slashification on."
(stringify-object object t))
(defun princ-to-string (object)
#!+sb-doc
- "Returns the printed representation of OBJECT as a string with
+ "Return the printed representation of OBJECT as a string with
slashification off."
(stringify-object object nil))
-;;; This produces the printed representation of an object as a string. The
-;;; few ...-TO-STRING functions above call this.
+;;; This produces the printed representation of an object as a string.
+;;; The few ...-TO-STRING functions above call this.
(defvar *string-output-streams* ())
(defun stringify-object (object &optional (*print-escape* *print-escape*))
(let ((stream (if *string-output-streams*
(write-char #\> stream))))
nil)
\f
-;;;; WHITESPACE-CHAR-P
-
-;;; This is used in other files, but is defined in this one for some reason.
-
-(defun whitespace-char-p (char)
- #!+sb-doc
- "Determines whether or not the character is considered whitespace."
- (or (char= char #\space)
- (char= char (code-char tab-char-code))
- (char= char (code-char return-char-code))
- (char= char #\linefeed)))
-\f
;;;; circularity detection stuff
-;;; When *PRINT-CIRCLE* is T, this gets bound to a hash table that (eventually)
-;;; ends up with entries for every object printed. When we are initially
-;;; looking for circularities, we enter a T when we find an object for the
-;;; first time, and a 0 when we encounter an object a second time around.
-;;; When we are actually printing, the 0 entries get changed to the actual
-;;; marker value when they are first printed.
+;;; When *PRINT-CIRCLE* is T, this gets bound to a hash table that
+;;; (eventually) ends up with entries for every object printed. When
+;;; we are initially looking for circularities, we enter a T when we
+;;; find an object for the first time, and a 0 when we encounter an
+;;; object a second time around. When we are actually printing, the 0
+;;; entries get changed to the actual marker value when they are first
+;;; printed.
(defvar *circularity-hash-table* nil)
-;;; When NIL, we are just looking for circularities. After we have found them
-;;; all, this gets bound to 0. Then whenever we need a new marker, it is
-;;; incremented.
+;;; When NIL, we are just looking for circularities. After we have
+;;; found them all, this gets bound to 0. Then whenever we need a new
+;;; marker, it is incremented.
(defvar *circularity-counter* nil)
+;;; Check to see whether OBJECT is a circular reference, and return
+;;; something non-NIL if it is. If ASSIGN is T, then the number to use
+;;; in the #n= and #n# noise is assigned at this time.
+;;;
+;;; Note: CHECK-FOR-CIRCULARITY must be called *exactly* once with
+;;; ASSIGN true, or the circularity detection noise will get confused
+;;; about when to use #n= and when to use #n#. If this returns non-NIL
+;;; when ASSIGN is true, then you must call HANDLE-CIRCULARITY on it.
+;;; If you are not using this inside a WITH-CIRCULARITY-DETECTION,
+;;; then you have to be prepared to handle a return value of :INITIATE
+;;; which means it needs to initiate the circularity detection noise.
(defun check-for-circularity (object &optional assign)
- #!+sb-doc
- "Check to see whether OBJECT is a circular reference, and return something
- non-NIL if it is. If ASSIGN is T, then the number to use in the #n= and
- #n# noise is assigned at this time. Note: CHECK-FOR-CIRCULARITY must
- be called *EXACTLY* once with ASSIGN T, or the circularity detection noise
- will get confused about when to use #n= and when to use #n#. If this
- returns non-NIL when ASSIGN is T, then you must call HANDLE-CIRCULARITY
- on it. If you are not using this inside a WITH-CIRCULARITY-DETECTION,
- then you have to be prepared to handle a return value of :INITIATE which
- means it needs to initiate the circularity detection noise. See the
- source for info on how to do that."
(cond ((null *print-circle*)
;; Don't bother, nobody cares.
nil)
((null *circularity-counter*)
(ecase (gethash object *circularity-hash-table*)
((nil)
- ;; First encounter.
+ ;; first encounter
(setf (gethash object *circularity-hash-table*) t)
;; We need to keep looking.
nil)
((t)
- ;; Second encounter.
+ ;; second encounter
(setf (gethash object *circularity-hash-table*) 0)
;; It's a circular reference.
t)
(let ((value (gethash object *circularity-hash-table*)))
(case value
((nil t)
- ;; If NIL, we found an object that wasn't there the first time
- ;; around. If T, exactly one occurance of this object appears.
- ;; Either way, just print the thing without any special
- ;; processing. Note: you might argue that finding a new object
- ;; means that something is broken, but this can happen. If
- ;; someone uses the ~@<...~:> format directive, it conses a
- ;; new list each time though format (i.e. the &REST list), so
- ;; we will have different cdrs.
+ ;; If NIL, we found an object that wasn't there the
+ ;; first time around. If T, this object appears exactly
+ ;; once. Either way, just print the thing without any
+ ;; special processing. Note: you might argue that
+ ;; finding a new object means that something is broken,
+ ;; but this can happen. If someone uses the ~@<...~:>
+ ;; format directive, it conses a new list each time
+ ;; though format (i.e. the &REST list), so we will have
+ ;; different cdrs.
nil)
(0
(if assign
(let ((value (incf *circularity-counter*)))
- ;; First occurance of this object. Set the counter.
+ ;; first occurrence of this object: Set the counter.
(setf (gethash object *circularity-hash-table*) value)
value)
t))
(t
- ;; Second or later occurance.
+ ;; second or later occurrence
(- value)))))))
+;;; Handle the results of CHECK-FOR-CIRCULARITY. If this returns T then
+;;; you should go ahead and print the object. If it returns NIL, then
+;;; you should blow it off.
(defun handle-circularity (marker stream)
- #!+sb-doc
- "Handle the results of CHECK-FOR-CIRCULARITY. If this returns T then
- you should go ahead and print the object. If it returns NIL, then
- you should blow it off."
(case marker
(:initiate
;; Someone forgot to initiate circularity detection.
\f
;;;; OUTPUT-OBJECT -- the main entry point
-(defvar *pretty-printer* nil
- #!+sb-doc
- "The current pretty printer. Should be either a function that takes two
- arguments (the object and the stream) or NIL to indicate that there is
- no pretty printer installed.")
+;;; the current pretty printer. This should be either a function that
+;;; takes two arguments (the object and the stream) or NIL to indicate
+;;; that there is no pretty printer installed.
+(defvar *pretty-printer* nil)
+;;; Objects whose print representation identifies them EQLly don't
+;;; need to be checked for circularity.
+(defun uniquely-identified-by-print-p (x)
+ (or (numberp x)
+ (characterp x)
+ (and (symbolp x)
+ (symbol-package x))))
+
+;;; Output OBJECT to STREAM observing all printer control variables.
(defun output-object (object stream)
- #!+sb-doc
- "Output OBJECT to STREAM observing all printer control variables."
(labels ((print-it (stream)
(if *print-pretty*
(if *pretty-printer*
(t
(when (handle-circularity marker stream)
(print-it stream)))))))
- (cond ((or (not *print-circle*)
- (numberp object)
- (characterp object)
- (and (symbolp object) (symbol-package object) t))
- ;; If it a number, character, or interned symbol, we do not want
- ;; to check for circularity/sharing.
+ (cond (;; Maybe we don't need to bother with circularity detection.
+ (or (not *print-circle*)
+ (uniquely-identified-by-print-p object))
(print-it stream))
- ((or *circularity-hash-table*
- (consp object)
- (typep object 'instance)
- (typep object '(array t *)))
- ;; If we have already started circularity detection, this object
- ;; might be a sharded reference. If we have not, then if it is
- ;; a cons, a instance, or an array of element type t it might
- ;; contain a circular reference to itself or multiple shared
- ;; references.
+ (;; If we have already started circularity detection, this
+ ;; object might be a shared reference. If we have not, then
+ ;; if it is a compound object it might contain a circular
+ ;; reference to itself or multiple shared references.
+ (or *circularity-hash-table*
+ (compound-object-p x))
(check-it stream))
(t
(print-it stream)))))
+;;; Output OBJECT to STREAM observing all printer control variables
+;;; except for *PRINT-PRETTY*. Note: if *PRINT-PRETTY* is non-NIL,
+;;; then the pretty printer will be used for any components of OBJECT,
+;;; just not for OBJECT itself.
(defun output-ugly-object (object stream)
- #!+sb-doc
- "Output OBJECT to STREAM observing all printer control variables except
- for *PRINT-PRETTY*. Note: if *PRINT-PRETTY* is non-NIL, then the pretty
- printer will be used for any components of OBJECT, just not for OBJECT
- itself."
(typecase object
;; KLUDGE: The TYPECASE approach here is non-ANSI; the ANSI definition of
;; PRINT-OBJECT says it provides printing and we're supposed to provide
\f
;;;; symbols
-;;; Values of *PRINT-CASE* and (READTABLE-CASE *READTABLE*) the last time the
-;;; printer was called.
+;;; Values of *PRINT-CASE* and (READTABLE-CASE *READTABLE*) the last
+;;; time the printer was called.
(defvar *previous-case* nil)
(defvar *previous-readtable-case* nil)
-;;; This variable contains the current definition of one of three symbol
-;;; printers. SETUP-PRINTER-STATE sets this variable.
+;;; This variable contains the current definition of one of three
+;;; symbol printers. SETUP-PRINTER-STATE sets this variable.
(defvar *internal-symbol-output-function* nil)
;;; This function sets the internal global symbol
(output-symbol-name name stream))
(output-symbol-name (symbol-name object) stream nil)))
-;;; Output the string NAME as if it were a symbol name. In other words,
-;;; diddle its case according to *PRINT-CASE* and READTABLE-CASE.
+;;; Output the string NAME as if it were a symbol name. In other
+;;; words, diddle its case according to *PRINT-CASE* and
+;;; READTABLE-CASE.
(defun output-symbol-name (name stream &optional (maybe-quote t))
(declare (type simple-base-string name))
(setup-printer-state)
(declaim (type (simple-array (unsigned-byte 16) (#.char-code-limit))
*character-attributes*))
-;;; Constants which are a bit-mask for each interesting character attribute.
+;;; constants which are a bit-mask for each interesting character attribute
(defconstant other-attribute (ash 1 0)) ; Anything else legal.
(defconstant number-attribute (ash 1 1)) ; A numeric digit.
(defconstant uppercase-attribute (ash 1 2)) ; An uppercase letter.
(when (zerop (aref *character-attributes* i))
(setf (aref *character-attributes* i) funny-attribute))))
-;;; For each character, the value of the corresponding element is the lowest
-;;; base in which that character is a digit.
+;;; For each character, the value of the corresponding element is the
+;;; lowest base in which that character is a digit.
(defvar *digit-bases*
(make-array char-code-limit
:element-type '(unsigned-byte 8)
TEST-SIGN ; At end, see whether it is a sign...
(return (not (test sign)))
- OTHER ; Not potential number, see whether funny chars...
+ OTHER ; not potential number, see whether funny chars...
(let ((mask (logxor (logior lowercase-attribute uppercase-attribute
funny-attribute)
letter-attribute)))
(when (test sign extension) (advance START-STUFF nil))
(return t)
- DOT-FOUND ; Leading dots...
+ DOT-FOUND ; leading dots...
(when (test letter) (advance START-DOT-MARKER nil))
(when (digitp) (advance DOT-DIGIT))
(when (test number other) (advance OTHER nil))
(when (char= current #\.) (advance DOT-FOUND))
(return t)
- START-STUFF ; Leading stuff before any dot or digit.
+ START-STUFF ; leading stuff before any dot or digit
(when (digitp)
(if (test letter)
(advance LAST-DIGIT-ALPHA)
(when (test sign extension slash) (advance START-STUFF nil))
(return t)
- START-MARKER ; Number marker in leading stuff...
+ START-MARKER ; number marker in leading stuff...
(when (test letter) (advance OTHER nil))
(go START-STUFF)
- START-DOT-STUFF ; Leading stuff containing dot w/o digit...
+ START-DOT-STUFF ; leading stuff containing dot without digit...
(when (test letter) (advance START-DOT-STUFF nil))
(when (digitp) (advance DOT-DIGIT))
(when (test sign extension dot slash) (advance START-DOT-STUFF nil))
(when (test number other) (advance OTHER nil))
(return t)
- START-DOT-MARKER ; Number marker in leading stuff w/ dot..
- ;; Leading stuff containing dot w/o digit followed by letter...
+ START-DOT-MARKER ; number marker in leading stuff with dot..
+ ;; leading stuff containing dot without digit followed by letter...
(when (test letter) (advance OTHER nil))
(go START-DOT-STUFF)
- DOT-DIGIT ; In a thing with dots...
+ DOT-DIGIT ; in a thing with dots...
(when (test letter) (advance DOT-MARKER))
(when (digitp) (advance DOT-DIGIT))
(when (test number other) (advance OTHER nil))
(when (test sign extension dot slash) (advance DOT-DIGIT))
(return t)
- DOT-MARKER ; Number maker in number with dot...
+ DOT-MARKER ; number marker in number with dot...
(when (test letter) (advance OTHER nil))
(go DOT-DIGIT)
- LAST-DIGIT-ALPHA ; Previous char is a letter digit...
+ LAST-DIGIT-ALPHA ; previous char is a letter digit...
(when (or (digitp) (test sign slash))
(advance ALPHA-DIGIT))
(when (test letter number other dot) (advance OTHER nil))
(return t)
- ALPHA-DIGIT ; Seen a digit which is a letter...
+ ALPHA-DIGIT ; seen a digit which is a letter...
(when (or (digitp) (test sign slash))
(if (test letter)
(advance LAST-DIGIT-ALPHA)
(when (test number other dot) (advance OTHER nil))
(return t)
- ALPHA-MARKER ; Number marker in number with alpha digit...
+ ALPHA-MARKER ; number marker in number with alpha digit...
(when (test letter) (advance OTHER nil))
(go ALPHA-DIGIT)
- DIGIT ; Seen only real numeric digits...
+ DIGIT ; seen only ordinary (non-alphabetic) numeric digits...
(when (digitp)
(if (test letter)
(advance ALPHA-DIGIT)
(when (char= current #\.) (advance DOT-DIGIT))
(return t)
- MARKER ; Number marker in a numeric number...
+ MARKER ; number marker in a numeric number...
(when (test letter) (advance OTHER nil))
(go DIGIT))))
\f
;;;; *INTERNAL-SYMBOL-OUTPUT-FUNCTION*
;;;;
;;;; Case hackery. These functions are stored in
-;;;; *INTERNAL-SYMBOL-OUTPUT-FUNCTION* according to the values of *PRINT-CASE*
-;;;; and READTABLE-CASE.
-
-;; Called when:
-;; READTABLE-CASE *PRINT-CASE*
-;; :UPCASE :UPCASE
-;; :DOWNCASE :DOWNCASE
-;; :PRESERVE any
+;;;; *INTERNAL-SYMBOL-OUTPUT-FUNCTION* according to the values of
+;;;; *PRINT-CASE* and READTABLE-CASE.
+
+;;; called when:
+;;; READTABLE-CASE *PRINT-CASE*
+;;; :UPCASE :UPCASE
+;;; :DOWNCASE :DOWNCASE
+;;; :PRESERVE any
(defun output-preserve-symbol (pname stream)
(declare (simple-string pname))
(write-string pname stream))
-;; Called when:
-;; READTABLE-CASE *PRINT-CASE*
-;; :UPCASE :DOWNCASE
+;;; called when:
+;;; READTABLE-CASE *PRINT-CASE*
+;;; :UPCASE :DOWNCASE
(defun output-lowercase-symbol (pname stream)
(declare (simple-string pname))
(dotimes (index (length pname))
(let ((char (schar pname index)))
(write-char (char-downcase char) stream))))
-;; Called when:
-;; READTABLE-CASE *PRINT-CASE*
-;; :DOWNCASE :UPCASE
+;;; called when:
+;;; READTABLE-CASE *PRINT-CASE*
+;;; :DOWNCASE :UPCASE
(defun output-uppercase-symbol (pname stream)
(declare (simple-string pname))
(dotimes (index (length pname))
(let ((char (schar pname index)))
(write-char (char-upcase char) stream))))
-;; Called when:
-;; READTABLE-CASE *PRINT-CASE*
-;; :UPCASE :CAPITALIZE
-;; :DOWNCASE :CAPITALIZE
+;;; called when:
+;;; READTABLE-CASE *PRINT-CASE*
+;;; :UPCASE :CAPITALIZE
+;;; :DOWNCASE :CAPITALIZE
(defun output-capitalize-symbol (pname stream)
(declare (simple-string pname))
(let ((prev-not-alpha t)
stream)
(setq prev-not-alpha (not (alpha-char-p char)))))))
-;; Called when:
-;; READTABLE-CASE *PRINT-CASE*
-;; :INVERT any
+;;; called when:
+;;; READTABLE-CASE *PRINT-CASE*
+;;; :INVERT any
(defun output-invert-symbol (pname stream)
(declare (simple-string pname))
(let ((all-upper t)
(output-terse-array vector stream))
((bit-vector-p vector)
(write-string "#*" stream)
- (dotimes (i (length vector))
- (output-object (aref vector i) stream)))
+ (dovector (bit vector)
+ ;; (Don't use OUTPUT-OBJECT here, since this code
+ ;; has to work for all possible *PRINT-BASE* values.)
+ (write-char (if (zerop bit) #\0 #\1) stream)))
(t
(when (and *print-readably*
- (not (eq (array-element-type vector) 't)))
+ (not (eq (array-element-type vector) t)))
(error 'print-not-readable :object vector))
(descend-into (stream)
(write-string "#(" stream)
(write-string ")" stream)))))
;;; This function outputs a string quoting characters sufficiently
-;;; that so someone can read it in again. Basically, put a slash in
+;;; so that someone can read it in again. Basically, put a slash in
;;; front of an character satisfying NEEDS-SLASH-P.
(defun quote-string (string stream)
(macrolet ((needs-slash-p (char)
(when (needs-slash-p char) (write-char #\\ stream))
(write-char char stream))))))
+;;; Output the printed representation of any array in either the #< or #A
+;;; form.
(defun output-array (array stream)
- #!+sb-doc
- "Outputs the printed representation of any array in either the #< or #A
- form."
(if (or *print-array* *print-readably*)
(output-array-guts array stream)
(output-terse-array array stream)))
-;;; to output the abbreviated #< form of an array
+;;; Output the abbreviated #< form of an array.
(defun output-terse-array (array stream)
(let ((*print-level* nil)
(*print-length* nil))
(print-unreadable-object (array stream :type t :identity t))))
-;;; to output the readable #A form of an array
+;;; Output the readable #A form of an array.
(defun output-array-guts (array stream)
(when (and *print-readably*
(not (eq (array-element-type array) t)))
stream)))
\f
;;;; bignum printing
-;;;;
-;;;; written by Steven Handerson (based on Skef's idea)
-;;;;
-;;;; rewritten to remove assumptions about the length of fixnums for the
-;;;; MIPS port by William Lott
-;;; *BASE-POWER* holds the number that we keep dividing into the bignum for
-;;; each *print-base*. We want this number as close to *most-positive-fixnum*
-;;; as possible, i.e. (floor (log most-positive-fixnum *print-base*)).
+;;; *BASE-POWER* holds the number that we keep dividing into the
+;;; bignum for each *print-base*. We want this number as close to
+;;; *most-positive-fixnum* as possible, i.e. (floor (log
+;;; most-positive-fixnum *print-base*)).
(defparameter *base-power* (make-array 37 :initial-element nil))
-;;; *FIXNUM-POWER--1* holds the number of digits for each *print-base* that
-;;; fit in the corresponding *base-power*.
+;;; *FIXNUM-POWER--1* holds the number of digits for each *PRINT-BASE*
+;;; that fit in the corresponding *base-power*.
(defparameter *fixnum-power--1* (make-array 37 :initial-element nil))
-;;; Print the bignum to the stream. We first generate the correct value for
-;;; *base-power* and *fixnum-power--1* if we have not already. Then we call
-;;; bignum-print-aux to do the printing.
+;;; Print the bignum to the stream. We first generate the correct
+;;; value for *base-power* and *fixnum-power--1* if we have not
+;;; already. Then we call bignum-print-aux to do the printing.
(defun print-bignum (big stream)
(unless (aref *base-power* *print-base*)
(do ((power-1 -1 (1+ power-1))
(write-char #\) stream))
\f
;;;; float printing
-;;;;
-;;;; written by Bill Maddox
-;;; FLONUM-TO-STRING (and its subsidiary function FLOAT-STRING) does most of
-;;; the work for all printing of floating point numbers in the printer and in
-;;; FORMAT. It converts a floating point number to a string in a free or
-;;; fixed format with no exponent. The interpretation of the arguments is as
-;;; follows:
+;;; FLONUM-TO-STRING (and its subsidiary function FLOAT-STRING) does
+;;; most of the work for all printing of floating point numbers in the
+;;; printer and in FORMAT. It converts a floating point number to a
+;;; string in a free or fixed format with no exponent. The
+;;; interpretation of the arguments is as follows:
;;;
;;; X - The floating point number to convert, which must not be
;;; negative.
;;; POINT-POS - The position of the digit preceding the decimal
;;; point. Zero indicates point before first digit.
;;;
-;;; NOTE: FLONUM-TO-STRING goes to a lot of trouble to guarantee accuracy.
-;;; Specifically, the decimal number printed is the closest possible
-;;; approximation to the true value of the binary number to be printed from
-;;; among all decimal representations with the same number of digits. In
-;;; free-format output, i.e. with the number of digits unconstrained, it is
-;;; guaranteed that all the information is preserved, so that a properly-
-;;; rounding reader can reconstruct the original binary number, bit-for-bit,
-;;; from its printed decimal representation. Furthermore, only as many digits
-;;; as necessary to satisfy this condition will be printed.
+;;; NOTE: FLONUM-TO-STRING goes to a lot of trouble to guarantee
+;;; accuracy. Specifically, the decimal number printed is the closest
+;;; possible approximation to the true value of the binary number to
+;;; be printed from among all decimal representations with the same
+;;; number of digits. In free-format output, i.e. with the number of
+;;; digits unconstrained, it is guaranteed that all the information is
+;;; preserved, so that a properly- rounding reader can reconstruct the
+;;; original binary number, bit-for-bit, from its printed decimal
+;;; representation. Furthermore, only as many digits as necessary to
+;;; satisfy this condition will be printed.
;;;
-;;; FLOAT-STRING actually generates the digits for positive numbers. The
-;;; algorithm is essentially that of algorithm Dragon4 in "How to Print
-;;; Floating-Point Numbers Accurately" by Steele and White. The current
-;;; (draft) version of this paper may be found in [CMUC]<steele>tradix.press.
-;;; DO NOT EVEN THINK OF ATTEMPTING TO UNDERSTAND THIS CODE WITHOUT READING
-;;; THE PAPER!
+;;; FLOAT-STRING actually generates the digits for positive numbers.
+;;; The algorithm is essentially that of algorithm Dragon4 in "How to
+;;; Print Floating-Point Numbers Accurately" by Steele and White. The
+;;; current (draft) version of this paper may be found in
+;;; [CMUC]<steele>tradix.press. DO NOT EVEN THINK OF ATTEMPTING TO
+;;; UNDERSTAND THIS CODE WITHOUT READING THE PAPER!
(defvar *digits* "0123456789")
:fill-pointer 0
:adjustable t)))
;; Represent fraction as r/s, error bounds as m+/s and m-/s.
- ;; Rational arithmetic avoids loss of precision in subsequent calculations.
+ ;; Rational arithmetic avoids loss of precision in subsequent
+ ;; calculations.
(cond ((> exponent 0)
(setq r (ash fraction exponent))
(setq m- (ash 1 exponent))
(setq m+ m-))
((< exponent 0)
(setq s (ash 1 (- exponent)))))
- ;;adjust the error bounds m+ and m- for unequal gaps
+ ;; Adjust the error bounds m+ and m- for unequal gaps.
(when (= fraction (ash 1 precision))
(setq m+ (ash m+ 1))
(setq r (ash r 1))
(setq s (ash s 1)))
- ;;scale value by requested amount, and update error bounds
+ ;; Scale value by requested amount, and update error bounds.
(when scale
(if (minusp scale)
(let ((scale-factor (expt 10 (- scale))))
(setq r (* r scale-factor))
(setq m+ (* m+ scale-factor))
(setq m- (* m- scale-factor)))))
- ;;scale r and s and compute initial k, the base 10 logarithm of r
+ ;; Scale r and s and compute initial k, the base 10 logarithm of r.
(do ()
((>= r (ceiling s 10)))
(decf k)
((< (+ (ash r 1) m+) (ash s 1)))
(setq s (* s 10))
(incf k))
- ;;determine number of fraction digits to generate
+ ;; Determine number of fraction digits to generate.
(cond (fdigits
- ;;use specified number of fraction digits
+ ;; Use specified number of fraction digits.
(setq cutoff (- fdigits))
;;don't allow less than fmin fraction digits
(if (and fmin (> cutoff (- fmin))) (setq cutoff (- fmin))))
(width
- ;;use as many fraction digits as width will permit
- ;;but force at least fmin digits even if width will be exceeded
+ ;; Use as many fraction digits as width will permit but
+ ;; force at least fmin digits even if width will be
+ ;; exceeded.
(if (< k 0)
(setq cutoff (- 1 width))
(setq cutoff (1+ (- k width))))
(if (and fmin (> cutoff (- fmin))) (setq cutoff (- fmin)))))
- ;;If we decided to cut off digit generation before precision has
- ;;been exhausted, rounding the last digit may cause a carry propagation.
- ;;We can prevent this, preserving left-to-right digit generation, with
- ;;a few magical adjustments to m- and m+. Of course, correct rounding
- ;;is also preserved.
+ ;; If we decided to cut off digit generation before precision
+ ;; has been exhausted, rounding the last digit may cause a carry
+ ;; propagation. We can prevent this, preserving left-to-right
+ ;; digit generation, with a few magical adjustments to m- and
+ ;; m+. Of course, correct rounding is also preserved.
(when (or fdigits width)
(let ((a (- cutoff k))
(y s))
(setq m+ (max y m+))
(when (= m+ y) (setq roundup t))))
(when (< (+ (ash r 1) m+) (ash s 1)) (return)))
- ;;zero-fill before fraction if no integer part
+ ;; Zero-fill before fraction if no integer part.
(when (< k 0)
(setq decpnt digits)
(vector-push-extend #\. digit-string)
(dotimes (i (- k))
(incf digits) (vector-push-extend #\0 digit-string)))
- ;;generate the significant digits
+ ;; Generate the significant digits.
(do ()(nil)
(decf k)
(when (= k -1)
(if roundup
(setq high (>= (ash r 1) (- (ash s 1) m+)))
(setq high (> (ash r 1) (- (ash s 1) m+))))
- ;;stop when either precision is exhausted or we have printed as many
- ;;fraction digits as permitted
+ ;; Stop when either precision is exhausted or we have printed as
+ ;; many fraction digits as permitted.
(when (or low high (and cutoff (<= k cutoff))) (return))
(vector-push-extend (char *digits* u) digit-string)
(incf digits))
;; If cutoff occurred before first digit, then no digits are
;; generated at all.
(when (or (not cutoff) (>= k cutoff))
- ;;last digit may need rounding
+ ;; Last digit may need rounding
(vector-push-extend (char *digits*
(cond ((and low (not high)) u)
((and high (not low)) (1+ u))
(t (if (<= (ash r 1) s) u (1+ u)))))
digit-string)
(incf digits))
- ;;zero-fill after integer part if no fraction
+ ;; Zero-fill after integer part if no fraction.
(when (>= k 0)
(dotimes (i k) (incf digits) (vector-push-extend #\0 digit-string))
(vector-push-extend #\. digit-string)
(setq decpnt digits))
- ;;add trailing zeroes to pad fraction if fdigits specified
+ ;; Add trailing zeroes to pad fraction if fdigits specified.
(when fdigits
(dotimes (i (- fdigits (- digits decpnt)))
(incf digits)
(vector-push-extend #\0 digit-string)))
- ;;all done
+ ;; all done
(values digit-string (1+ digits) (= decpnt 0) (= decpnt digits) decpnt)))
-;;; Given a non-negative floating point number, SCALE-EXPONENT returns a new
-;;; floating point number Z in the range (0.1, 1.0] and an exponent E such
-;;; that Z * 10^E is (approximately) equal to the original number. There may
-;;; be some loss of precision due the floating point representation. The
-;;; scaling is always done with long float arithmetic, which helps printing of
-;;; lesser precisions as well as avoiding generic arithmetic.
+;;; Given a non-negative floating point number, SCALE-EXPONENT returns
+;;; a new floating point number Z in the range (0.1, 1.0] and an
+;;; exponent E such that Z * 10^E is (approximately) equal to the
+;;; original number. There may be some loss of precision due the
+;;; floating point representation. The scaling is always done with
+;;; long float arithmetic, which helps printing of lesser precisions
+;;; as well as avoiding generic arithmetic.
;;;
-;;; When computing our initial scale factor using EXPT, we pull out part of
-;;; the computation to avoid over/under flow. When denormalized, we must pull
-;;; out a large factor, since there is more negative exponent range than
-;;; positive range.
+;;; When computing our initial scale factor using EXPT, we pull out
+;;; part of the computation to avoid over/under flow. When
+;;; denormalized, we must pull out a large factor, since there is more
+;;; negative exponent range than positive range.
(defun scale-exponent (original-x)
(let* ((x (coerce original-x 'long-float)))
(multiple-value-bind (sig exponent) (decode-float x)
\f
;;;; entry point for the float printer
-;;; Entry point for the float printer as called by PRINT, PRIN1, PRINC,
-;;; etc. The argument is printed free-format, in either exponential or
+;;; the float printer as called by PRINT, PRIN1, PRINC, etc. The
+;;; argument is printed free-format, in either exponential or
;;; non-exponential notation, depending on its magnitude.
;;;
-;;; NOTE: When a number is to be printed in exponential format, it is scaled in
-;;; floating point. Since precision may be lost in this process, the
-;;; guaranteed accuracy properties of FLONUM-TO-STRING are lost. The
-;;; difficulty is that FLONUM-TO-STRING performs extensive computations with
-;;; integers of similar magnitude to that of the number being printed. For
-;;; large exponents, the bignums really get out of hand. If bignum arithmetic
-;;; becomes reasonably fast and the exponent range is not too large, then it
-;;; might become attractive to handle exponential notation with the same
-;;; accuracy as non-exponential notation, using the method described in the
+;;; NOTE: When a number is to be printed in exponential format, it is
+;;; scaled in floating point. Since precision may be lost in this
+;;; process, the guaranteed accuracy properties of FLONUM-TO-STRING
+;;; are lost. The difficulty is that FLONUM-TO-STRING performs
+;;; extensive computations with integers of similar magnitude to that
+;;; of the number being printed. For large exponents, the bignums
+;;; really get out of hand. If bignum arithmetic becomes reasonably
+;;; fast and the exponent range is not too large, then it might become
+;;; attractive to handle exponential notation with the same accuracy
+;;; as non-exponential notation, using the method described in the
;;; Steele and White paper.
;;; Print the appropriate exponent marker for X and the specified exponent.
(long-float #\L))
plusp exp))))
-;;; Write out an infinity using #. notation, or flame out if
-;;; *PRINT-READABLY* is true and *READ-EVAL* is false.
(defun output-float-infinity (x stream)
- (declare (type float x) (type stream stream))
+ (declare (float x) (stream stream))
(cond (*read-eval*
- (write-string "#." stream))
- (*print-readably*
- (error 'print-not-readable :object x))
- (t
- (write-string "#<" stream)))
- (write-string "EXT:" stream)
- (princ (float-format-name x) stream)
+ (write-string "#." stream))
+ (*print-readably*
+ (error 'print-not-readable :object x))
+ (t
+ (write-string "#<" stream)))
+ (write-string "SB-EXT:" stream)
+ (write-string (symbol-name (float-format-name x)) stream)
(write-string (if (plusp x) "-POSITIVE-" "-NEGATIVE-")
- stream)
+ stream)
(write-string "INFINITY" stream)
(unless *read-eval*
(write-string ">" stream)))
-;;; Output a #< NaN or die trying.
(defun output-float-nan (x stream)
(print-unreadable-object (x stream)
(princ (float-format-name x) stream)
(defun output-function (object stream)
(let* ((*print-length* 3) ; in case we have to..
(*print-level* 3) ; ..print an interpreted function definition
- (name (cond ((find (function-subtype object)
- #(#.sb!vm:closure-header-type
- #.sb!vm:byte-code-closure-type))
- "CLOSURE")
- ((sb!eval::interpreted-function-p object)
- (or (sb!eval::interpreted-function-%name object)
- (sb!eval:interpreted-function-lambda-expression
- object)))
- ((find (function-subtype object)
- #(#.sb!vm:function-header-type
- #.sb!vm:closure-function-header-type))
- (%function-name object))
- (t 'no-name-available)))
+ ;; FIXME: This find-the-function-name idiom ought to be
+ ;; encapsulated in a function somewhere.
+ (name (case (function-subtype object)
+ (#.sb!vm:closure-header-widetag "CLOSURE")
+ (#.sb!vm:simple-fun-header-widetag (%simple-fun-name object))
+ (t 'no-name-available)))
(identified-by-name-p (and (symbolp name)
(fboundp name)
(eq (fdefinition name) object))))
(defun output-random (object stream)
(print-unreadable-object (object stream :identity t)
- (let ((lowtag (get-lowtag object)))
+ (let ((lowtag (lowtag-of object)))
(case lowtag
- (#.sb!vm:other-pointer-type
- (let ((type (get-type object)))
- (case type
- (#.sb!vm:value-cell-header-type
+ (#.sb!vm:other-pointer-lowtag
+ (let ((widetag (widetag-of object)))
+ (case widetag
+ (#.sb!vm:value-cell-header-widetag
(write-string "value cell " stream)
- (output-object (sb!c:value-cell-ref object) stream))
+ (output-object (value-cell-ref object) stream))
(t
- (write-string "unknown pointer object, type=" stream)
+ (write-string "unknown pointer object, widetag=" stream)
(let ((*print-base* 16) (*print-radix* t))
- (output-integer type stream))))))
- ((#.sb!vm:function-pointer-type
- #.sb!vm:instance-pointer-type
- #.sb!vm:list-pointer-type)
- (write-string "unknown pointer object, type=" stream))
+ (output-integer widetag stream))))))
+ ((#.sb!vm:fun-pointer-lowtag
+ #.sb!vm:instance-pointer-lowtag
+ #.sb!vm:list-pointer-lowtag)
+ (write-string "unknown pointer object, lowtag=" stream)
+ (let ((*print-base* 16) (*print-radix* t))
+ (output-integer lowtag stream)))
(t
- (case (get-type object)
- (#.sb!vm:unbound-marker-type
+ (case (widetag-of object)
+ (#.sb!vm:unbound-marker-widetag
(write-string "unbound marker" stream))
(t
(write-string "unknown immediate object, lowtag=" stream)
(let ((*print-base* 2) (*print-radix* t))
(output-integer lowtag stream))
- (write-string ", type=" stream)
+ (write-string ", widetag=" stream)
(let ((*print-base* 16) (*print-radix* t))
- (output-integer (get-type object) stream)))))))))
+ (output-integer (widetag-of object) stream)))))))))