0.6.7.22: removed CVS dollar-Header-dollar tags from sources
[sbcl.git] / src / code / describe.lisp
1 ;;;; most of the DESCRIBE mechanism -- that part which isn't derived
2 ;;;; from PCL code
3
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
12
13 (in-package "SB-IMPL")
14 \f
15 (defvar *describe-indentation-step* 3
16   #+sb-doc
17   "the number of spaces that sets off each line of a recursive description")
18
19 (declaim (ftype (function (t stream)) describe-object))
20 (defgeneric describe-object ((x t) stream))
21
22 (defun describe (x &optional (stream-designator *standard-output*))
23   #+sb-doc
24   "Print a description of the object X."
25   (let ((stream (out-synonym-of stream-designator)))
26     #+nil (fresh-line stream)
27     (pprint-logical-block (stream nil)
28       (describe-object x stream)))
29   (values))
30 \f
31 ;;;; miscellaneous DESCRIBE-OBJECT methods
32
33 (defmethod describe-object ((x t) s)
34   (format s "~@<~S ~_is a ~S.~:>" x (type-of x)))
35
36 (defmethod describe-object ((x cons) s)
37   (call-next-method)
38   (when (and (legal-function-name-p x)
39              (fboundp x))
40     (format s "Its FDEFINITION is ~S.~@:_" (fdefinition x))
41     ;; TO DO: should check for SETF documentation.
42     ;; TO DO: should make it clear whether the definition is a
43     ;; DEFUN (SETF FOO) or DEFSETF FOO or what.
44     ))
45
46 (defmethod describe-object ((x array) s)
47   (let ((rank (array-rank x)))
48     (cond ((> rank 1)
49            (format s "~S ~_is " x)
50            (write-string (if (%array-displaced-p x) "a displaced" "an") s)
51            (format s " array of rank ~S." rank)
52            (format s "~@:_Its dimensions are ~S." (array-dimensions x)))
53           (t
54            (format s
55                    "~@:_~S is a ~:[~;displaced ~]vector of length ~S." x
56                    (and (array-header-p x) (%array-displaced-p x)) (length x))
57            (when (array-has-fill-pointer-p x)
58              (format s "~@:_It has a fill pointer, currently ~S."
59                      (fill-pointer x))))))
60   (let ((array-element-type (array-element-type x)))
61     (unless (eq array-element-type t)
62       (format s
63               "~@:_Its element type is specialized to ~S."
64               array-element-type))))
65
66 (defmethod describe-object ((x hash-table) s)
67   (declare (type stream s))
68   (format s "~@<~S ~_is an ~S hash table.~:>" x (hash-table-test x))
69   (format s "~_Its SIZE is ~S." (hash-table-size x))
70   (format s
71           "~@:_~@<Its REHASH-SIZE is ~S. ~_Its REHASH-THRESHOLD is ~S.~:>"
72           (hash-table-rehash-size x)
73           (hash-table-rehash-threshold x))
74   (let ((count (hash-table-count x)))
75     (format s "~@:_It holds ~S key/value pair~:P~:[: ~2I~_~;.~]"
76             count (zerop count))
77     (let ((n 0))
78       (declare (type index n))
79       (dohash (k v x)
80         (unless (zerop n)
81           (write-char #\space s))
82         (incf n)
83         (when (and *print-length* (> n *print-length*))
84           (format s "~:_...")
85           (return))
86         (format s "~:_(~S ~S)" k v)))))
87 \f
88 ;;;; DESCRIBE-OBJECT methods for symbols and functions, including all
89 ;;;; sorts of messy stuff about documentation, type information,
90 ;;;; packaging, function implementation, etc..
91
92 ;;; Print the specified kind of documentation about the given NAME. If
93 ;;; NAME is null, or not a valid name, then don't print anything.
94 (declaim (ftype (function (symbol stream t t) (values)) %describe-doc))
95 (defun %describe-doc (name s kind kind-doc)
96   (when (and name (typep name '(or symbol cons)))
97     (let ((doc (fdocumentation name kind)))
98       (when doc
99         (format s "~_~@(~A documentation:~)~@:_  ~A"
100                 (or kind-doc kind) doc))))
101   (values))
102
103 ;;; Describe various stuff about the functional semantics attached to
104 ;;; the specified Name. Type-Spec is the function type specifier
105 ;;; extracted from the definition, or NIL if none.
106 (declaim (ftype (function ((or symbol cons) stream t)) %describe-function-name))
107 (defun %describe-function-name (name s type-spec) 
108   (multiple-value-bind (type where)
109       (if (or (symbolp name) (and (listp name) (eq (car name) 'setf)))
110           (values (type-specifier (info :function :type name))
111                   (info :function :where-from name))
112           (values type-spec :defined))
113     (when (consp type)
114       (format s "~@:_Its ~(~A~) argument types are:~@:_  ~S"
115               where (second type))
116       (format s "~@:_Its result type is:~@:_  ~S" (third type))))
117   (let ((inlinep (info :function :inlinep name)))
118     (when inlinep
119       (format s "~@:_It is currently declared ~(~A~);~
120                  ~:[no~;~] expansion is available."
121               inlinep (info :function :inline-expansion name)))))
122
123 ;;; Interpreted function describing; handles both closure and
124 ;;; non-closure functions. Instead of printing the compiled-from info,
125 ;;; we print the definition.
126 (defun %describe-function-interpreted (x s kind name)
127   (declare (type stream s))
128   (multiple-value-bind (exp closure-p dname)
129       (sb-eval:interpreted-function-lambda-expression x)
130     (let ((args (sb-eval:interpreted-function-arglist x)))
131       (format s "~@:_~@(~@[~A ~]arguments:~@:_~)" kind)
132       (if args
133           (format s "  ~<~S~:>" args)
134           (write-string "  There are no arguments." s)))
135     (let ((name (or name dname)))
136       (%describe-doc name s 'function kind)
137       (unless (eq kind :macro)
138         (%describe-function-name
139          name
140          s
141          (type-specifier (sb-eval:interpreted-function-type x)))))
142     (when closure-p
143       (format s "~@:_Its closure environment is:")
144       (pprint-logical-block (s nil)
145         (pprint-indent :current 2)
146         (let ((clos (sb-eval:interpreted-function-closure x)))
147           (dotimes (i (length clos))
148             (format s "~@:_~S: ~S" i (svref clos i))))))
149     (format s "~@:_Its definition is:~@:_  ~S" exp)))
150
151 ;;; Print information from the debug-info about where CODE-OBJ was
152 ;;; compiled from.
153 (defun %describe-compiled-from (code-obj s)
154   (declare (type stream s))
155   (let ((info (sb-kernel:%code-debug-info code-obj)))
156     (when info
157       (let ((sources (sb-c::debug-info-source info)))
158         (format s "~@:_On ~A it was compiled from:"
159                 ;; FIXME: The FORMAT-UNIVERSAL-TIME calls in the system
160                 ;; should become more consistent, probably not using
161                 ;; any nondefault options.
162                 (format-universal-time nil
163                                        (sb-c::debug-source-compiled
164                                         (first sources))
165                                        :style :abbreviated))
166         (dolist (source sources)
167           (let ((name (sb-c::debug-source-name source)))
168             (ecase (sb-c::debug-source-from source)
169               (:file
170                (format s "~@:_~A~@:_  Created: " (namestring name))
171                (sb-int:format-universal-time t (sb-c::debug-source-created
172                                                 source))
173                (let ((comment (sb-c::debug-source-comment source)))
174                  (when comment
175                    (format s "~@:_  Comment: ~A" comment))))
176               (:lisp (format s "~@:_~S" name)))))))))
177
178 ;;; Describe a compiled function. The closure case calls us to print
179 ;;; the guts.
180 (defun %describe-function-compiled (x s kind name)
181   (declare (type stream s))
182   ;; FIXME: The lowercaseness of %FUNCTION-ARGLIST results, and the
183   ;; non-sentenceness of the "Arguments" label, makes awkward output.
184   ;; Better would be "Its arguments are: ~S" (with uppercase argument
185   ;; names) when arguments are known, and otherwise "There is no
186   ;; information available about its arguments." or "It has no
187   ;; arguments." (And why is %FUNCTION-ARGLIST a string instead of a
188   ;; list of symbols anyway?)
189   (let ((args (%function-arglist x)))
190     (format s "~@:_~@(~@[~A ~]arguments:~@:_~)" kind)
191     (cond ((not args)
192            (format s "  There is no argument information available."))
193           ((string= args "()")
194            (write-string "  There are no arguments." s))
195           (t
196            (write-string "  " s)
197            (pprint-logical-block (s nil)
198              (pprint-indent :current 2)
199              (write-string args s)))))
200   (let ((name (or name (%function-name x))))
201     (%describe-doc name s 'function kind)
202     (unless (eq kind :macro)
203       (%describe-function-name name s (%function-type x))))
204   (%describe-compiled-from (sb-kernel:function-code-header x) s))
205
206 (defun %describe-function-byte-compiled (x s kind name)
207   (declare (type stream s))
208   (let ((name (or name (sb-c::byte-function-name x))))
209     (%describe-doc name s 'function kind)
210     (unless (eq kind :macro)
211       (%describe-function-name name s 'function)))
212   (%describe-compiled-from (sb-c::byte-function-component x) s))
213
214 ;;; Describe a function with the specified kind and name. The latter
215 ;;; arguments provide some information about where the function came
216 ;;; from. Kind NIL means not from a name.
217 (defun %describe-function (x s &optional (kind nil) name)
218   (declare (type function x))
219   (declare (type stream s))
220   (declare (type (member :macro :function nil) kind))
221   (fresh-line s)
222   (ecase kind
223     (:macro (format s "Macro-function: ~S" x))
224     (:function (format s "Function: ~S" x))
225     ((nil) (format s "~S is a function." x)))
226   (case (get-type x)
227     (#.sb-vm:closure-header-type
228      (%describe-function-compiled (%closure-function x) s kind name)
229      (format s "~@:_Its closure environment is:")
230      (pprint-logical-block (s nil)
231        (pprint-indent :current 8)
232        (dotimes (i (- (get-closure-length x) (1- sb-vm:closure-info-offset)))
233          (format s "~@:_~S: ~S" i (%closure-index-ref x i)))))
234     ((#.sb-vm:function-header-type #.sb-vm:closure-function-header-type)
235      (%describe-function-compiled x s kind name))
236     (#.sb-vm:funcallable-instance-header-type
237      (typecase x
238        (sb-kernel:byte-function
239         (%describe-function-byte-compiled x s kind name))
240        (sb-kernel:byte-closure
241         (%describe-function-byte-compiled (byte-closure-function x)
242                                           s kind name)
243         (format s "~@:_Its closure environment is:")
244         (pprint-logical-block (s nil)
245           (pprint-indent :current 8)
246           (let ((data (byte-closure-data x)))
247             (dotimes (i (length data))
248               (format s "~@:_~S: ~S" i (svref data i))))))
249        (sb-eval:interpreted-function
250         (%describe-function-interpreted x s kind name))
251        (standard-generic-function
252         ;; There should be a special method for this case; we'll
253         ;; delegate to that.
254         (describe-object x s))
255        (t
256         (format s "~@:_It is an unknown type of funcallable instance."))))
257     (t
258      (format s "~@:_It is an unknown type of function."))))
259
260 (defmethod describe-object ((x function) s)
261   (%describe-function x s))
262   
263 (defmethod describe-object ((x symbol) s)
264   (declare (type stream s))
265
266   ;; Describe the packaging.
267   (let ((package (symbol-package x)))
268     (if package
269         (multiple-value-bind (symbol status)
270             (find-symbol (symbol-name x) package)
271           (declare (ignore symbol))
272           (format s "~S is an ~(~A~) symbol in ~S."
273                   x status (symbol-package x)))
274         (format s "~S is an uninterned symbol." x)))
275   ;; TO DO: We could grovel over all packages looking for and
276   ;; reporting other phenomena, e.g. IMPORT and SHADOW, or
277   ;; availability in some package even after (SYMBOL-PACKAGE X) has
278   ;; been set to NIL.
279
280   ;; Describe the value cell.
281   (let* ((kind (info :variable :kind x))
282          (wot (ecase kind
283                 (:special "special variable")
284                 (:constant "constant")
285                 (:global "undefined variable")
286                 (:alien nil))))
287     (cond
288      ((eq kind :alien)
289       (let ((info (info :variable :alien-info x)))
290         (format s "~@:_~@<It is an alien at #X~8,'0X of type ~3I~:_~S.~:>~@:_"
291                 (sap-int (eval (sb-alien::heap-alien-info-sap-form info)))
292                 (sb-alien-internals:unparse-alien-type
293                  (sb-alien::heap-alien-info-type info)))
294         (format s "~@<Its current value is ~3I~:_~S.~:>"
295                 (eval x))))
296      ((boundp x)
297       (format s "~@:_It is a ~A; its value is ~S." wot (symbol-value x)))
298      ((not (eq kind :global))
299       (format s "~@:_It is a ~A; no current value." wot)))
300
301     (when (eq (info :variable :where-from x) :declared)
302       (format s "~@:_Its declared type is ~S."
303               (type-specifier (info :variable :type x))))
304
305     (%describe-doc x s 'variable kind))
306
307   ;; Print out properties.
308   (format s "~@[~@:_Its SYMBOL-PLIST is ~@<~2I~_~S~:>.~]" (symbol-plist x))
309
310   ;; Describe the function cell.
311   (cond ((macro-function x)
312          (%describe-function (macro-function x) s :macro x))
313         ((special-operator-p x)
314          (%describe-doc x s 'function "Special form"))
315         ((fboundp x)
316          (%describe-function (fdefinition x) s :function x)))
317
318   ;; TO DO: Print out other stuff from the INFO database:
319   ;;   * Does it name a type or class?
320   ;;   * Is it a structure accessor? (important since those are 
321   ;;     magical in some ways, e.g. blasting the structure if you 
322   ;;     redefine them)
323
324   ;; Print other documentation.
325   (%describe-doc x s 'structure "Structure")
326   (%describe-doc x s 'type "Type")
327   (%describe-doc x s 'setf "Setf macro")
328   (dolist (assoc (info :random-documentation :stuff x))
329     (format s
330             "~@:_Documentation on the ~(~A~):~@:_~A"
331             (car assoc)
332             (cdr assoc))))