;;;; provided with absolutely no warranty. See the COPYING and CREDITS
;;;; files for more information.
-(in-package "SB-IMPL")
+(in-package "SB-IMPL") ;(SB-IMPL, not SB!IMPL, since we're built in warm load.)
+
+(declaim #.*optimize-byte-compilation*)
+
\f
(defvar *describe-indentation-step* 3
#+sb-doc
(defun describe (x &optional (stream-designator *standard-output*))
#+sb-doc
"Print a description of the object X."
+ (declare #.*optimize-external-despite-byte-compilation*)
(let ((stream (out-synonym-of stream-designator)))
- #+nil (fresh-line stream)
(pprint-logical-block (stream nil)
- (describe-object x stream)))
+ (fresh-line stream)
+ (describe-object x stream)
+ (fresh-line stream)))
(values))
\f
;;;; miscellaneous DESCRIBE-OBJECT methods
;;; Print the specified kind of documentation about the given NAME. If
;;; NAME is null, or not a valid name, then don't print anything.
-(declaim (ftype (function (symbol stream t t) (values)) %describe-doc))
+(declaim (ftype (function (t stream t t) (values)) %describe-doc))
(defun %describe-doc (name s kind kind-doc)
(when (and name (typep name '(or symbol cons)))
(let ((doc (fdocumentation name kind)))
(values))
;;; Describe various stuff about the functional semantics attached to
-;;; the specified Name. Type-Spec is the function type specifier
+;;; the specified NAME, if NAME is the kind of thing you can look
+;;; up as a name. (In the case of anonymous closures and other
+;;; things, it might not be.) TYPE-SPEC is the function type specifier
;;; extracted from the definition, or NIL if none.
-(declaim (ftype (function ((or symbol cons) stream t)) %describe-function-name))
+(declaim (ftype (function (t stream t)) %describe-function-name))
(defun %describe-function-name (name s type-spec)
- (multiple-value-bind (type where)
- (if (or (symbolp name) (and (listp name) (eq (car name) 'setf)))
- (values (type-specifier (info :function :type name))
- (info :function :where-from name))
- (values type-spec :defined))
- (when (consp type)
- (format s "~@:_Its ~(~A~) argument types are:~@:_ ~S"
- where (second type))
- (format s "~@:_Its result type is:~@:_ ~S" (third type))))
- (let ((inlinep (info :function :inlinep name)))
- (when inlinep
- (format s "~@:_It is currently declared ~(~A~);~
+ (when (and name (typep name '(or symbol cons)))
+ (multiple-value-bind (type where)
+ (if (or (symbolp name) (and (listp name) (eq (car name) 'setf)))
+ (values (type-specifier (info :function :type name))
+ (info :function :where-from name))
+ (values type-spec :defined))
+ (when (consp type)
+ (format s "~@:_Its ~(~A~) argument types are:~@:_ ~S"
+ where (second type))
+ (format s "~@:_Its result type is:~@:_ ~S" (third type))))
+ (let ((inlinep (info :function :inlinep name)))
+ (when inlinep
+ (format s
+ "~@:_It is currently declared ~(~A~);~
~:[no~;~] expansion is available."
- inlinep (info :function :inline-expansion name)))))
-
-;;; Interpreted function describing; handles both closure and
-;;; non-closure functions. Instead of printing the compiled-from info,
-;;; we print the definition.
-(defun %describe-function-interpreted (x s kind name)
- (declare (type stream s))
- (multiple-value-bind (exp closure-p dname)
- (sb-eval:interpreted-function-lambda-expression x)
- (let ((args (sb-eval:interpreted-function-arglist x)))
- (format s "~@:_~@(~@[~A ~]arguments:~@:_~)" kind)
- (if args
- (format s " ~<~S~:>" args)
- (write-string " There are no arguments." s)))
- (let ((name (or name dname)))
- (%describe-doc name s 'function kind)
- (unless (eq kind :macro)
- (%describe-function-name
- name
- s
- (type-specifier (sb-eval:interpreted-function-type x)))))
- (when closure-p
- (format s "~@:_Its closure environment is:")
- (pprint-logical-block (s nil)
- (pprint-indent :current 2)
- (let ((clos (sb-eval:interpreted-function-closure x)))
- (dotimes (i (length clos))
- (format s "~@:_~S: ~S" i (svref clos i))))))
- (format s "~@:_Its definition is:~@:_ ~S" exp)))
+ inlinep (info :function :inline-expansion name))))))
;;; Print information from the debug-info about where CODE-OBJ was
;;; compiled from.
(ecase (sb-c::debug-source-from source)
(:file
(format s "~@:_~A~@:_ Created: " (namestring name))
- (sb-int:format-universal-time t (sb-c::debug-source-created
- source)))
+ (format-universal-time s (sb-c::debug-source-created
+ source)))
(:lisp (format s "~@:_~S" name))))))))))
;;; Describe a compiled function. The closure case calls us to print
(let ((data (byte-closure-data x)))
(dotimes (i (length data))
(format s "~@:_~S: ~S" i (svref data i))))))
- (sb-eval:interpreted-function
- (%describe-function-interpreted x s kind name))
(standard-generic-function
;; There should be a special method for this case; we'll
;; delegate to that.
(multiple-value-bind (symbol status)
(find-symbol (symbol-name x) package)
(declare (ignore symbol))
- (format s "~S is an ~(~A~) symbol in ~S."
+ (format s "~S is ~_an ~(~A~) symbol ~_in ~S."
x status (symbol-package x)))
- (format s "~S is an uninterned symbol." x)))
+ (format s "~S is ~_an uninterned symbol." x)))
;; TO DO: We could grovel over all packages looking for and
;; reporting other phenomena, e.g. IMPORT and SHADOW, or
;; availability in some package even after (SYMBOL-PACKAGE X) has
(format s "~@<Its current value is ~3I~:_~S.~:>"
(eval x))))
((boundp x)
- (format s "~@:_It is a ~A; its value is ~S." wot (symbol-value x)))
+ (format s "~@:_It is a ~A; its ~_value is ~S." wot (symbol-value x)))
((not (eq kind :global))
(format s "~@:_It is a ~A; no current value." wot)))
(when (eq (info :variable :where-from x) :declared)
- (format s "~@:_Its declared type is ~S."
+ (format s "~@:_Its declared type ~_is ~S."
(type-specifier (info :variable :type x))))
(%describe-doc x s 'variable kind))
((fboundp x)
(%describe-function (fdefinition x) s :function x)))
- ;; TO DO: Print out other stuff from the INFO database:
- ;; * Does it name a type or class?
- ;; * Is it a structure accessor? (important since those are
+ ;; FIXME: Print out other stuff from the INFO database:
+ ;; * Does it name a type?
+ ;; * Is it a structure accessor? (This is important since those are
;; magical in some ways, e.g. blasting the structure if you
- ;; redefine them)
+ ;; redefine them.)
;; Print other documentation.
(%describe-doc x s 'structure "Structure")
(%describe-doc x s 'type "Type")
(%describe-doc x s 'setf "Setf macro")
+
(dolist (assoc (info :random-documentation :stuff x))
(format s
"~@:_Documentation on the ~(~A~):~@:_~A"
(car assoc)
- (cdr assoc))))
+ (cdr assoc)))
+
+ ;; Describe the associated class, if any.
+ (let ((symbol-named-class (cl:find-class x nil)))
+ (when symbol-named-class
+ (format t "~&It names a class ~A." symbol-named-class)
+ (describe symbol-named-class))))