3 ;; Copyright (C) 2001 Free Software Foundation, Inc.
5 ;; This program is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation; either version 2, or (at your option)
10 ;; This program 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
13 ;; GNU General Public License for more details.
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with this program; see the file COPYING. If not, write to
17 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 ;; Boston, MA 02111-1307, USA.
22 (define-module (system repl describe)
23 :use-module (oop goops)
24 :use-module (ice-9 regex)
25 :use-module (ice-9 format)
26 :use-module (ice-9 and-let-star)
29 (define-method (describe (symbol <symbol>))
30 (format #t "`~s' is " symbol)
31 (if (not (defined? symbol))
32 (display "not defined in the current module.\n")
33 (describe-object (module-ref (current-module) symbol))))
40 (define (safe-class-name class)
41 (if (slot-bound? class 'name)
45 (define-method (display-class class . args)
46 (let* ((name (safe-class-name class))
47 (desc (if (pair? args) (car args) name)))
48 (if (eq? *describe-format* 'tag)
49 (format #t "@class{~a}{~a}" name desc)
50 (format #t "~a" desc))))
52 (define (display-list title list)
53 (if title (begin (display title) (display ":\n\n")))
55 (display "(not defined)\n")
56 (for-each display-summary list)))
58 (define (display-slot-list title instance list)
59 (if title (begin (display title) (display ":\n\n")))
61 (display "(not defined)\n")
62 (for-each (lambda (slot)
63 (let ((name (slot-definition-name slot)))
66 (if (and instance (slot-bound? instance name))
69 (display (slot-ref instance name))))
73 (define (display-file location)
74 (display "Defined in ")
75 (if (eq? *describe-format* 'tag)
76 (format #t "@location{~a}.\n" location)
77 (format #t "`~a'.\n" location)))
79 (define (format-documentation doc)
80 (with-current-buffer (make-buffer #:text doc)
82 (let ((regexp (make-regexp "@([a-z]*)(\\{([^}]*)\\})?")))
83 (do-while (match (re-search-forward regexp))
84 (let ((key (string->symbol (match:substring match 1)))
85 (value (match:substring match 3)))
88 (delete-region! (match:start match)
89 (begin (forward-line) (point))))
91 (replace-match! match 0 (string-upcase value)))
93 (replace-match! match 0 (string-append "`" value "'")))))))
94 (display (string (current-buffer)))
102 (define description-table
104 (cons <boolean> "a boolean")
105 (cons <null> "an empty list")
106 (cons <integer> "an integer")
107 (cons <real> "a real number")
108 (cons <complex> "a complex number")
109 (cons <char> "a character")
110 (cons <symbol> "a symbol")
111 (cons <keyword> "a keyword")
112 (cons <promise> "a promise")
113 (cons <hook> "a hook")
114 (cons <fluid> "a fluid")
115 (cons <stack> "a stack")
116 (cons <variable> "a variable")
117 (cons <regexp> "a regexp object")
118 (cons <module> "a module object")
119 (cons <unknown> "an unknown object")))
121 (define-generic describe-object)
122 (export describe-object)
124 (define-method (describe-object (obj <top>))
126 (display-location obj)
130 (display-documentation obj))
132 (define-generic display-object)
133 (define-generic display-summary)
134 (define-generic display-type)
135 (define-generic display-value)
136 (define-generic display-location)
137 (define-generic display-description)
138 (define-generic display-documentation)
139 (export display-object display-summary display-type display-value
140 display-location display-description display-documentation)
142 (define-method (display-object (obj <top>))
145 (define-method (display-summary (obj <top>))
150 (define-method (display-type (obj <top>))
152 ((eof-object? obj) (display "the end-of-file object"))
153 ((unspecified? obj) (display "unspecified"))
154 (else (let ((class (class-of obj)))
155 (display-class class (or (assq-ref description-table class)
156 (safe-class-name class))))))
159 (define-method (display-value (obj <top>))
160 (if (not (unspecified? obj))
161 (begin (display-object obj) (newline))))
163 (define-method (display-location (obj <top>))
166 (define-method (display-description (obj <top>))
167 (let* ((doc (with-output-to-string (lambda () (display-documentation obj))))
168 (index (string-index doc #\newline)))
169 (display (make-shared-substring doc 0 (1+ index)))))
171 (define-method (display-documentation (obj <top>))
172 (display "Not documented.\n"))
179 (define-method (display-type (obj <pair>))
181 ((list? obj) (display-class <list> "a list"))
182 ((pair? (cdr obj)) (display "an improper list"))
183 (else (display-class <pair> "a pair")))
191 (define-method (display-type (obj <string>))
192 (if (read-only-string? 'obj)
193 (display "a read-only string")
194 (display-class <string> "a string"))
202 (define-method (display-object (obj <procedure>))
205 ;; Construct output from the source.
207 (display (procedure-name obj))
208 (let ((args (cadr (procedure-source obj))))
209 (cond ((null? args) (display ")"))
211 (let ((str (with-output-to-string (lambda () (display args)))))
212 (format #t " ~a" (string-upcase! (substring str 1)))))
214 (format #t " . ~a)" (string-upcase! (symbol->string args)))))))
216 ;; Primitive procedure. Let's lookup the dictionary.
217 (and-let* ((entry (lookup-procedure obj)))
218 (let ((name (entry-property entry 'name))
219 (print-arg (lambda (arg)
221 (display (string-upcase (symbol->string arg))))))
224 (and-let* ((args (entry-property entry 'args)))
225 (for-each print-arg args))
226 (and-let* ((opts (entry-property entry 'opts)))
227 (display " &optional")
228 (for-each print-arg opts))
229 (and-let* ((rest (entry-property entry 'rest)))
234 (define-method (display-summary (obj <procedure>))
235 (display "Procedure: ")
239 (display-description obj))
241 (define-method (display-type (obj <procedure>))
243 ((and (thunk? obj) (not (procedure-name obj))) (display "a thunk"))
244 ((closure? obj) (display-class <procedure> "a procedure"))
245 ((procedure-with-setter? obj)
246 (display-class <procedure-with-setter> "a procedure with setter"))
247 ((not (struct? obj)) (display "a primitive procedure"))
248 (else (display-class <procedure> "a procedure")))
251 (define-method (display-location (obj <procedure>))
252 (and-let* ((entry (lookup-procedure obj)))
253 (display-file (entry-file entry))))
255 (define-method (display-documentation (obj <procedure>))
256 (cond ((cond ((closure? obj) (procedure-documentation obj))
257 ((lookup-procedure obj) => entry-text)
259 => format-documentation)
260 (else (next-method))))
267 (define-method (describe-object (obj <class>))
269 (display-location obj)
271 (display-documentation obj)
275 (define-method (display-summary (obj <class>))
280 (display-description obj))
282 (define-method (display-type (obj <class>))
283 (display-class <class> "a class")
284 (if (not (eq? (class-of obj) <class>))
285 (begin (display " of ") (display-class (class-of obj))))
288 (define-method (display-value (obj <class>))
289 (display-list "Class precedence list" (class-precedence-list obj))
291 (display-list "Direct superclasses" (class-direct-supers obj))
293 (display-list "Direct subclasses" (class-direct-subclasses obj))
295 (display-slot-list "Direct slots" #f (class-direct-slots obj))
297 (display-list "Direct methods" (class-direct-methods obj)))
304 (define-method (display-type (obj <object>))
305 (display-class <object> "an instance")
306 (display " of class ")
307 (display-class (class-of obj))
310 (define-method (display-value (obj <object>))
311 (display-slot-list #f obj (class-slots (class-of obj))))
315 ;;; Generic functions
318 (define-method (display-type (obj <generic>))
319 (display-class <generic> "a generic function")
320 (display " of class ")
321 (display-class (class-of obj))
324 (define-method (display-value (obj <generic>))
325 (display-list #f (generic-function-methods obj)))
332 (define-method (display-object (obj <method>))
334 (let ((gf (method-generic-function obj)))
335 (display (if gf (generic-function-name gf) "#<anonymous>")))
336 (let loop ((args (method-specializers obj)))
341 (display-class (car args))
343 (else (display " . ") (display-class args))))
346 (define-method (display-summary (obj <method>))
351 (display-description obj))
353 (define-method (display-type (obj <method>))
354 (display-class <method> "a method")
355 (display " of class ")
356 (display-class (class-of obj))
359 (define-method (display-documentation (obj <method>))
360 (let ((doc (procedure-documentation (method-procedure obj))))
361 (if doc (format-documentation doc) (next-method))))