1
;; Copyright (C) 1994 M. Hagiya, W. Schelter, T. Yuasa
3
;; This file is part of GNU Common Lisp, herein referred to as GCL
5
;; GCL is free software; you can redistribute it and/or modify it under
6
;; the terms of the GNU LIBRARY GENERAL PUBLIC LICENSE as published by
7
;; the Free Software Foundation; either version 2, or (at your option)
10
;; GCL is distributed in the hope that it will be useful, but WITHOUT
11
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13
;; License for more details.
15
;; You should have received a copy of the GNU Library General Public License
16
;; along with GCL; see the file COPYING. If not, write to the Free Software
17
;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22
;;;; DESCRIBE and INSPECT
27
(export '(describe inspect))
33
(proclaim '(optimize (safety 2) (space 3)))
36
(defvar *inspect-level* 0)
37
(defvar *inspect-history* nil)
38
(defvar *inspect-mode* nil)
40
(defvar *old-print-level* nil)
41
(defvar *old-print-length* nil)
44
(defun inspect-read-line ()
45
(do ((char (read-char *query-io*) (read-char *query-io*)))
46
((or (char= char #\Newline) (char= char #\Return)))))
48
(defun read-inspect-command (label object allow-recursive)
49
(unless *inspect-mode*
52
(progn (princ label) (inspect-object object))
53
(format t label object))
54
(return-from read-inspect-command nil))
61
(format t label object))
64
(case (do ((char (read-char *query-io*) (read-char *query-io*)))
65
((and (char/= char #\Space) (char/= #\Tab)) char))
67
(when allow-recursive (inspect-object object))
71
(when allow-recursive (inspect-object object))
73
((#\s #\S) (inspect-read-line) (return nil))
76
(let ((*print-pretty* t) (*print-level* nil) (*print-length* nil))
79
((#\a #\A) (inspect-read-line) (throw 'abort-inspect nil))
81
(return (values t (prog1
82
(eval (read-preserving-whitespace *query-io*))
83
(inspect-read-line)))))
85
(dolist (x (multiple-value-list
87
(eval (read-preserving-whitespace *query-io*))
88
(inspect-read-line))))
90
:level *old-print-level*
91
:length *old-print-length*)
93
((#\q #\Q) (inspect-read-line) (throw 'quit-inspect nil))
94
(t (inspect-read-line)
98
n (or N or Newline): inspects the field (recursively).~%~
99
s (or S): skips the field.~%~
100
p (or P): pretty-prints the field.~%~
101
a (or A): aborts the inspection ~
102
of the rest of the fields.~%~
103
u (or U) form: updates the field ~
104
with the value of the form.~%~
105
e (or E) form: evaluates and prints the form.~%~
106
q (or Q): quits the inspection.~%~
107
?: prints this.~%~%")))))
109
(defmacro inspect-recursively (label object &optional place)
111
`(multiple-value-bind (update-flag new-value)
112
(read-inspect-command ,label ,object t)
113
(when update-flag (setf ,place new-value)))
114
`(when (read-inspect-command ,label ,object t)
115
(princ "Not updated.")
118
(defmacro inspect-print (label object &optional place)
120
`(multiple-value-bind (update-flag new-value)
121
(read-inspect-command ,label ,object nil)
122
(when update-flag (setf ,place new-value)))
123
`(when (read-inspect-command ,label ,object nil)
124
(princ "Not updated.")
127
(defun inspect-indent ()
130
(* 4 (if (< *inspect-level* 8) *inspect-level* 8))))
132
(defun inspect-indent-1 ()
135
(- (* 4 (if (< *inspect-level* 8) *inspect-level* 8)) 3)))
138
(defun inspect-symbol (symbol)
139
(let ((p (symbol-package symbol)))
141
(format t "~:@(~S~) - uninterned symbol" symbol))
142
((eq p (find-package "KEYWORD"))
143
(format t "~:@(~S~) - keyword" symbol))
145
(format t "~:@(~S~) - ~:[internal~;external~] symbol in ~A package"
147
(multiple-value-bind (b f)
148
(find-symbol (symbol-name symbol) p)
153
(when (boundp symbol)
155
(inspect-recursively "value:"
156
(symbol-value symbol)
157
(symbol-value symbol))
158
(inspect-print "value:~% ~S"
159
(symbol-value symbol)
160
(symbol-value symbol))))
162
(do ((pl (symbol-plist symbol) (cddr pl)))
164
(unless (and (symbolp (car pl))
165
(or (eq (symbol-package (car pl)) (find-package 'system))
166
(eq (symbol-package (car pl)) (find-package 'compiler))))
168
(inspect-recursively (format nil "property ~S:" (car pl))
170
(get symbol (car pl)))
171
(inspect-print (format nil "property ~:@(~S~):~% ~~S" (car pl))
173
(get symbol (car pl))))))
175
(when (print-doc symbol t)
176
(format t "~&-----------------------------------------------------------------------------~%"))
179
(defun inspect-package (package)
180
(format t "~S - package" package)
181
(when (package-nicknames package)
182
(inspect-print "nicknames: ~S" (package-nicknames package)))
183
(when (package-use-list package)
184
(inspect-print "use list: ~S" (package-use-list package)))
185
(when (package-used-by-list package)
186
(inspect-print "used-by list: ~S" (package-used-by-list package)))
187
(when (package-shadowing-symbols package)
188
(inspect-print "shadowing symbols: ~S"
189
(package-shadowing-symbols package))))
191
(defun inspect-character (character)
193
(cond ((standard-char-p character) "~S - standard character")
194
((string-char-p character) "~S - string character")
195
(t "~S - character"))
197
(inspect-print "code: #x~X" (char-code character))
198
(inspect-print "bits: ~D" (char-bits character))
199
(inspect-print "font: ~D" (char-font character)))
201
(defun inspect-number (number)
202
(case (type-of number)
203
(fixnum (format t "~S - fixnum (32 bits)" number))
204
(bignum (format t "~S - bignum" number))
206
(format t "~S - ratio" number)
207
(inspect-recursively "numerator:" (numerator number))
208
(inspect-recursively "denominator:" (denominator number)))
210
(format t "~S - complex" number)
211
(inspect-recursively "real part:" (realpart number))
212
(inspect-recursively "imaginary part:" (imagpart number)))
213
((short-float single-float)
214
(format t "~S - short-float" number)
215
(multiple-value-bind (signif expon sign)
216
(integer-decode-float number)
217
(declare (ignore sign))
218
(inspect-print "exponent: ~D" expon)
219
(inspect-print "mantissa: ~D" signif)))
220
((long-float double-float)
221
(format t "~S - long-float" number)
222
(multiple-value-bind (signif expon sign)
223
(integer-decode-float number)
224
(declare (ignore sign))
225
(inspect-print "exponent: ~D" expon)
226
(inspect-print "mantissa: ~D" signif)))))
228
(defun inspect-cons (cons)
231
((lambda lambda-block lambda-closure lambda-block-closure)
233
(quote "~S - constant")
240
(inspect-recursively (format nil "nthcdr ~D:" i)
241
l (cdr (nthcdr (1- i) cons))))
242
(inspect-recursively (format nil "nth ~D:" i)
243
(car l) (nth i cons)))))
245
(defun inspect-string (string)
246
(format t (if (simple-string-p string) "~S - simple string" "~S - string")
248
(inspect-print "dimension: ~D"(array-dimension string 0))
249
(when (array-has-fill-pointer-p string)
250
(inspect-print "fill pointer: ~D"
251
(fill-pointer string)
252
(fill-pointer string)))
254
(dotimes (i (array-dimension string 0))
255
(inspect-recursively (format nil "aref ~D:" i)
259
(defun inspect-vector (vector)
260
(format t (if (simple-vector-p vector) "~S - simple vector" "~S - vector")
262
(inspect-print "dimension: ~D" (array-dimension vector 0))
263
(when (array-has-fill-pointer-p vector)
264
(inspect-print "fill pointer: ~D"
265
(fill-pointer vector)
266
(fill-pointer vector)))
268
(dotimes (i (array-dimension vector 0))
269
(inspect-recursively (format nil "aref ~D:" i)
273
(defun inspect-array (array)
274
(format t (if (adjustable-array-p array)
275
"~S - adjustable aray"
278
(inspect-print "rank: ~D" (array-rank array))
279
(inspect-print "dimensions: ~D" (array-dimensions array))
280
(inspect-print "total size: ~D" (array-total-size array)))
282
(defun inspect-structure (x &aux name)
283
(format t "Structure of type ~a ~%Byte:[Slot Type]Slot Name :Slot Value"
284
(setq name (type-of x)))
285
(let* ((sd (get name 'si::s-data))
286
(spos (s-data-slot-position sd)))
287
(dolist (v (s-data-slot-descriptions sd))
288
(format t "~%~4d:~@[[~s] ~]~20a:~s"
289
(aref spos (nth 4 v))
290
(let ((type (nth 2 v)))
291
(if (eq t type) nil type))
293
(structure-ref1 x (nth 4 v))))))
296
(defun inspect-object (object &aux (*inspect-level* *inspect-level*))
298
(when (and (not *inspect-mode*)
299
(or (> *inspect-level* 5)
300
(member object *inspect-history*)))
302
(return-from inspect-object))
303
(incf *inspect-level*)
304
(push object *inspect-history*)
305
(catch 'abort-inspect
306
(cond ((symbolp object) (inspect-symbol object))
307
((packagep object) (inspect-package object))
308
((characterp object) (inspect-character object))
309
((numberp object) (inspect-number object))
310
((consp object) (inspect-cons object))
311
((stringp object) (inspect-string object))
312
((vectorp object) (inspect-vector object))
313
((arrayp object) (inspect-array object))
314
((structurep object)(inspect-structure object))
315
(t (format t "~S - ~S" object (type-of object))))))
318
(defun describe (object &aux (*inspect-mode* nil)
320
(*inspect-history* nil)
322
(*print-length* nil))
323
; "The lisp function DESCRIBE."
325
(catch 'quit-inspect (inspect-object object))
329
(defun inspect (object &aux (*inspect-mode* t)
331
(*inspect-history* nil)
332
(*old-print-level* *print-level*)
333
(*old-print-length* *print-length*)
336
; "The lisp function INSPECT."
338
(princ "Type ? and a newline for help.")
340
(catch 'quit-inspect (inspect-object object))
344
(defun print-doc (symbol &optional (called-from-apropos-doc-p nil)
346
(flet ((doc1 (doc ind)
349
"~&-----------------------------------------------------------------------------~%~53S~24@A~%~A"
352
(if (eq (symbol-package symbol) (find-package "LISP"))
353
(find-package "SYSTEM")
356
(cond ((special-form-p symbol)
357
(doc1 (or (documentation symbol 'function) "")
358
(if (macro-function symbol)
359
"[Special form and Macro]"
361
((macro-function symbol)
362
(doc1 (or (documentation symbol 'function) "") "[Macro]"))
365
(or (documentation symbol 'function)
366
(if (consp (setq x (symbol-function symbol)))
368
(lambda (format nil "~%Args: ~S" (cadr x)))
369
(lambda-block (format nil "~%Args: ~S" (caddr x)))
371
(format nil "~%Args: ~S" (car (cddddr x))))
372
(lambda-block-closure
373
(format nil "~%Args: ~S" (cadr (cddddr x))))
377
((setq x (documentation symbol 'function))
378
(doc1 x "[Macro or Function]")))
380
(cond ((constantp symbol)
381
(unless (and (eq (symbol-package symbol) (find-package "KEYWORD"))
382
(null (documentation symbol 'variable)))
383
(doc1 (or (documentation symbol 'variable) "") "[Constant]")))
384
((si:specialp symbol)
385
(doc1 (or (documentation symbol 'variable) "")
386
"[Special variable]"))
387
((or (setq x (documentation symbol 'variable)) (boundp symbol))
388
(doc1 (or x "") "[Variable]")))
390
(cond ((setq x (documentation symbol 'type))
392
((setq x (get symbol 'deftype-form))
393
(let ((*package* (good-package)))
394
(doc1 (format nil "~%Defined as: ~S~%See the doc of DEFTYPE." x)
397
(cond ((setq x (documentation symbol 'structure))
398
(doc1 x "[Structure]"))
399
((setq x (get symbol 'defstruct-form))
400
(doc1 (format nil "~%Defined as: ~S~%See the doc of DEFSTRUCT." x)
403
(cond ((setq x (documentation symbol 'setf))
405
((setq x (get symbol 'setf-update-fn))
406
(let ((*package* (good-package)))
407
(doc1 (format nil "~%Defined as: ~S~%See the doc of DEFSETF."
408
`(defsetf ,symbol ,(get symbol 'setf-update-fn)))
410
((setq x (get symbol 'setf-lambda))
411
(let ((*package* (good-package)))
412
(doc1 (format nil "~%Defined as: ~S~%See the doc of DEFSETF."
413
`(defsetf ,symbol ,@(get symbol 'setf-lambda)))
415
((setq x (get symbol 'setf-method))
416
(let ((*package* (good-package)))
419
"~@[~%Defined as: ~S~%See the doc of DEFINE-SETF-METHOD.~]"
422
(lambda `(define-setf-method ,@(cdr x)))
423
(lambda-block `(define-setf-method ,@(cddr x)))
424
(lambda-closure `(define-setf-method ,@(cddddr x)))
425
(lambda-block-closure
426
`(define-setf-method ,@(cdr (cddddr x))))
431
(idescribe (symbol-name symbol))
432
(if called-from-apropos-doc-p
435
(format t "~&-----------------------------------------------------------------------------")
436
(format t "~&No documentation for ~:@(~S~)." symbol))
439
(defun apropos-doc (string &optional (package 'lisp) &aux (f nil))
440
(setq string (string string))
442
(do-symbols (symbol package)
443
(when (substringp string (string symbol))
444
(setq f (or (print-doc symbol t) f))))
445
(do-all-symbols (symbol)
446
(when (substringp string (string symbol))
447
(setq f (or (print-doc symbol t) f)))))
449
(format t "~&-----------------------------------------------------------------------------")
450
(format t "~&No documentation for ~S in ~:[any~;~A~] package."
452
(and package (package-name (coerce-to-package package)))))