eval.c closures are now applicable smobs, not tc3s
[bpt/guile.git] / module / system / repl / describe.scm
CommitLineData
ea9c5dab 1;;; Describe objects
17e90c5e 2
314b8716 3;; Copyright (C) 2001, 2009 Free Software Foundation, Inc.
17e90c5e 4
e1203ea0
LC
5;;; This library is free software; you can redistribute it and/or
6;;; modify it under the terms of the GNU Lesser General Public
7;;; License as published by the Free Software Foundation; either
8;;; version 3 of the License, or (at your option) any later version.
9;;;
10;;; This library is distributed in the hope that it will be useful,
11;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;;; Lesser General Public License for more details.
14;;;
15;;; You should have received a copy of the GNU Lesser General Public
16;;; License along with this library; if not, write to the Free Software
17;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17e90c5e
KN
18
19;;; Code:
20
21(define-module (system repl describe)
1a1a10d3
AW
22 #:use-module (oop goops)
23 #:use-module (ice-9 regex)
24 #:use-module (ice-9 format)
25 #:use-module (ice-9 and-let-star)
26 #:export (describe))
17e90c5e 27
8f5cfc81 28(define-method (describe (symbol <symbol>))
17e90c5e
KN
29 (format #t "`~s' is " symbol)
30 (if (not (defined? symbol))
31 (display "not defined in the current module.\n")
8f5cfc81 32 (describe-object (module-ref (current-module) symbol))))
17e90c5e
KN
33
34\f
35;;;
36;;; Display functions
37;;;
38
39(define (safe-class-name class)
40 (if (slot-bound? class 'name)
41 (class-name class)
42 class))
43
44(define-method (display-class class . args)
45 (let* ((name (safe-class-name class))
46 (desc (if (pair? args) (car args) name)))
47 (if (eq? *describe-format* 'tag)
48 (format #t "@class{~a}{~a}" name desc)
49 (format #t "~a" desc))))
50
77046be3 51(define (display-list title list)
17e90c5e
KN
52 (if title (begin (display title) (display ":\n\n")))
53 (if (null? list)
54 (display "(not defined)\n")
55 (for-each display-summary list)))
56
77046be3 57(define (display-slot-list title instance list)
17e90c5e
KN
58 (if title (begin (display title) (display ":\n\n")))
59 (if (null? list)
60 (display "(not defined)\n")
61 (for-each (lambda (slot)
62 (let ((name (slot-definition-name slot)))
63 (display "Slot: ")
64 (display name)
65 (if (and instance (slot-bound? instance name))
66 (begin
67 (display " = ")
68 (display (slot-ref instance name))))
69 (newline)))
70 list)))
71
77046be3 72(define (display-file location)
17e90c5e
KN
73 (display "Defined in ")
74 (if (eq? *describe-format* 'tag)
75 (format #t "@location{~a}.\n" location)
76 (format #t "`~a'.\n" location)))
77
77046be3 78(define (format-documentation doc)
17e90c5e
KN
79 (with-current-buffer (make-buffer #:text doc)
80 (lambda ()
5163e951 81 (let ((regexp (make-regexp "@([a-z]*)(\\{([^}]*)\\})?")))
17e90c5e
KN
82 (do-while (match (re-search-forward regexp))
83 (let ((key (string->symbol (match:substring match 1)))
84 (value (match:substring match 3)))
85 (case key
86 ((deffnx)
87 (delete-region! (match:start match)
88 (begin (forward-line) (point))))
89 ((var)
90 (replace-match! match 0 (string-upcase value)))
91 ((code)
92 (replace-match! match 0 (string-append "`" value "'")))))))
93 (display (string (current-buffer)))
94 (newline))))
95
96\f
97;;;
98;;; Top
99;;;
100
101(define description-table
102 (list
103 (cons <boolean> "a boolean")
104 (cons <null> "an empty list")
105 (cons <integer> "an integer")
106 (cons <real> "a real number")
107 (cons <complex> "a complex number")
108 (cons <char> "a character")
109 (cons <symbol> "a symbol")
110 (cons <keyword> "a keyword")
111 (cons <promise> "a promise")
112 (cons <hook> "a hook")
113 (cons <fluid> "a fluid")
114 (cons <stack> "a stack")
115 (cons <variable> "a variable")
116 (cons <regexp> "a regexp object")
117 (cons <module> "a module object")
118 (cons <unknown> "an unknown object")))
119
120(define-generic describe-object)
121(export describe-object)
122
123(define-method (describe-object (obj <top>))
124 (display-type obj)
125 (display-location obj)
126 (newline)
127 (display-value obj)
128 (newline)
129 (display-documentation obj))
130
131(define-generic display-object)
132(define-generic display-summary)
133(define-generic display-type)
134(define-generic display-value)
135(define-generic display-location)
136(define-generic display-description)
137(define-generic display-documentation)
138(export display-object display-summary display-type display-value
139 display-location display-description display-documentation)
140
141(define-method (display-object (obj <top>))
142 (write obj))
143
144(define-method (display-summary (obj <top>))
145 (display "Value: ")
146 (display-object obj)
147 (newline))
148
149(define-method (display-type (obj <top>))
150 (cond
151 ((eof-object? obj) (display "the end-of-file object"))
152 ((unspecified? obj) (display "unspecified"))
153 (else (let ((class (class-of obj)))
154 (display-class class (or (assq-ref description-table class)
155 (safe-class-name class))))))
156 (display ".\n"))
157
158(define-method (display-value (obj <top>))
159 (if (not (unspecified? obj))
160 (begin (display-object obj) (newline))))
161
162(define-method (display-location (obj <top>))
163 *unspecified*)
164
165(define-method (display-description (obj <top>))
166 (let* ((doc (with-output-to-string (lambda () (display-documentation obj))))
167 (index (string-index doc #\newline)))
168 (display (make-shared-substring doc 0 (1+ index)))))
169
170(define-method (display-documentation (obj <top>))
171 (display "Not documented.\n"))
172
173\f
174;;;
175;;; Pairs
176;;;
177
178(define-method (display-type (obj <pair>))
179 (cond
180 ((list? obj) (display-class <list> "a list"))
181 ((pair? (cdr obj)) (display "an improper list"))
182 (else (display-class <pair> "a pair")))
183 (display ".\n"))
184
185\f
186;;;
187;;; Strings
188;;;
189
190(define-method (display-type (obj <string>))
191 (if (read-only-string? 'obj)
192 (display "a read-only string")
193 (display-class <string> "a string"))
194 (display ".\n"))
195
196\f
197;;;
198;;; Procedures
199;;;
200
201(define-method (display-object (obj <procedure>))
202 (cond
314b8716 203 ;; FIXME: VM programs, ...
17e90c5e
KN
204 (else
205 ;; Primitive procedure. Let's lookup the dictionary.
206 (and-let* ((entry (lookup-procedure obj)))
207 (let ((name (entry-property entry 'name))
208 (print-arg (lambda (arg)
209 (display " ")
210 (display (string-upcase (symbol->string arg))))))
211 (display "(")
212 (display name)
213 (and-let* ((args (entry-property entry 'args)))
214 (for-each print-arg args))
215 (and-let* ((opts (entry-property entry 'opts)))
216 (display " &optional")
217 (for-each print-arg opts))
218 (and-let* ((rest (entry-property entry 'rest)))
219 (display " &rest")
220 (print-arg rest))
221 (display ")"))))))
222
223(define-method (display-summary (obj <procedure>))
224 (display "Procedure: ")
225 (display-object obj)
226 (newline)
227 (display " ")
228 (display-description obj))
229
230(define-method (display-type (obj <procedure>))
231 (cond
232 ((and (thunk? obj) (not (procedure-name obj))) (display "a thunk"))
17e90c5e
KN
233 ((procedure-with-setter? obj)
234 (display-class <procedure-with-setter> "a procedure with setter"))
17e90c5e
KN
235 (else (display-class <procedure> "a procedure")))
236 (display ".\n"))
237
238(define-method (display-location (obj <procedure>))
239 (and-let* ((entry (lookup-procedure obj)))
240 (display-file (entry-file entry))))
241
242(define-method (display-documentation (obj <procedure>))
314b8716
AW
243 (cond ((or (procedure-documentation obj)
244 (and=> (lookup-procedure obj) entry-text))
17e90c5e
KN
245 => format-documentation)
246 (else (next-method))))
247
248\f
249;;;
250;;; Classes
251;;;
252
253(define-method (describe-object (obj <class>))
254 (display-type obj)
255 (display-location obj)
256 (newline)
257 (display-documentation obj)
258 (newline)
259 (display-value obj))
260
261(define-method (display-summary (obj <class>))
262 (display "Class: ")
263 (display-class obj)
264 (newline)
265 (display " ")
266 (display-description obj))
267
268(define-method (display-type (obj <class>))
269 (display-class <class> "a class")
270 (if (not (eq? (class-of obj) <class>))
271 (begin (display " of ") (display-class (class-of obj))))
272 (display ".\n"))
273
274(define-method (display-value (obj <class>))
275 (display-list "Class precedence list" (class-precedence-list obj))
276 (newline)
277 (display-list "Direct superclasses" (class-direct-supers obj))
278 (newline)
279 (display-list "Direct subclasses" (class-direct-subclasses obj))
280 (newline)
281 (display-slot-list "Direct slots" #f (class-direct-slots obj))
282 (newline)
283 (display-list "Direct methods" (class-direct-methods obj)))
284
285\f
286;;;
287;;; Instances
288;;;
289
8f5cfc81 290(define-method (display-type (obj <object>))
17e90c5e
KN
291 (display-class <object> "an instance")
292 (display " of class ")
293 (display-class (class-of obj))
294 (display ".\n"))
295
8f5cfc81 296(define-method (display-value (obj <object>))
17e90c5e
KN
297 (display-slot-list #f obj (class-slots (class-of obj))))
298
299\f
300;;;
301;;; Generic functions
302;;;
303
8f5cfc81 304(define-method (display-type (obj <generic>))
17e90c5e
KN
305 (display-class <generic> "a generic function")
306 (display " of class ")
307 (display-class (class-of obj))
308 (display ".\n"))
309
8f5cfc81 310(define-method (display-value (obj <generic>))
17e90c5e
KN
311 (display-list #f (generic-function-methods obj)))
312
313\f
314;;;
315;;; Methods
316;;;
317
318(define-method (display-object (obj <method>))
319 (display "(")
320 (let ((gf (method-generic-function obj)))
321 (display (if gf (generic-function-name gf) "#<anonymous>")))
322 (let loop ((args (method-specializers obj)))
323 (cond
324 ((null? args))
325 ((pair? args)
326 (display " ")
327 (display-class (car args))
328 (loop (cdr args)))
329 (else (display " . ") (display-class args))))
330 (display ")"))
331
332(define-method (display-summary (obj <method>))
333 (display "Method: ")
334 (display-object obj)
335 (newline)
336 (display " ")
337 (display-description obj))
338
339(define-method (display-type (obj <method>))
340 (display-class <method> "a method")
341 (display " of class ")
342 (display-class (class-of obj))
343 (display ".\n"))
344
345(define-method (display-documentation (obj <method>))
346 (let ((doc (procedure-documentation (method-procedure obj))))
347 (if doc (format-documentation doc) (next-method))))