Merge commit 'feccd2d3100fd2964d4c2df58ab3da7ce4949a66' into vm-check
[bpt/guile.git] / module / ice-9 / debugger / utils.scm
CommitLineData
8ee7506b
NJ
1
2(define-module (ice-9 debugger utils)
3 #:use-module (ice-9 debugger state)
4 #:export (display-position
5 source-position
6 write-frame-args-long
7 write-frame-index-long
8 write-frame-short/expression
9 write-frame-short/application
25bdfbb6 10 write-frame-long
8ee7506b
NJ
11 write-state-long
12 write-state-short))
13
9529c681
NJ
14;;; Procedures in this module print information about a stack frame.
15;;; The available information is as follows.
16;;;
17;;; * Source code location.
18;;;
19;;; For an evaluation frame, this is the location recorded at the time
20;;; that the expression being evaluated was read, if the 'positions
21;;; read option was enabled at that time.
22;;;
23;;; For an application frame, I'm not yet sure. Some applications
24;;; seem to have associated source expressions.
25;;;
26;;; * Whether frame is still evaluating its arguments.
27;;;
28;;; Only applies to an application frame. For example, an expression
29;;; like `(+ (* 2 3) 4)' goes through the following stages of
30;;; evaluation.
31;;;
32;;; (+ (* 2 3) 4) -- evaluation
33;;; [+ ... -- application; the car of the evaluation
34;;; has been evaluated and found to be a
35;;; procedure; before this procedure can
36;;; be applied, its arguments must be evaluated
37;;; [+ 6 ... -- same application after evaluating the
38;;; first argument
39;;; [+ 6 4] -- same application after evaluating all
40;;; arguments
41;;; 10 -- result
42;;;
43;;; * Whether frame is real or tail-recursive.
44;;;
45;;; If a frame is tail-recursive, its containing frame as shown by the
46;;; debugger backtrace doesn't really exist as far as the Guile
47;;; evaluator is concerned. The effect of this is that when a
48;;; tail-recursive frame returns, it looks as though its containing
49;;; frame returns at the same time. (And if the containing frame is
50;;; also tail-recursive, _its_ containing frame returns at that time
51;;; also, and so on ...)
52;;;
53;;; A `real' frame is one that is not tail-recursive.
54
55
8ee7506b
NJ
56(define (write-state-short state)
57 (let* ((frame (stack-ref (state-stack state) (state-index state)))
58 (source (frame-source frame))
59 (position (and source (source-position source))))
60 (format #t "Frame ~A at " (frame-number frame))
61 (if position
62 (display-position position)
63 (display "unknown source location"))
64 (newline)
65 (write-char #\tab)
66 (write-frame-short frame)
67 (newline)))
68
69(define (write-state-short* stack index)
70 (write-frame-index-short stack index)
71 (write-char #\space)
72 (write-frame-short (stack-ref stack index))
73 (newline))
74
75(define (write-frame-index-short stack index)
76 (let ((s (number->string (frame-number (stack-ref stack index)))))
77 (display s)
78 (write-char #\:)
79 (write-chars #\space (- 4 (string-length s)))))
80
81(define (write-frame-short frame)
82 (if (frame-procedure? frame)
83 (write-frame-short/application frame)
84 (write-frame-short/expression frame)))
85
86(define (write-frame-short/application frame)
87 (write-char #\[)
88 (write (let ((procedure (frame-procedure frame)))
89 (or (and (procedure? procedure)
90 (procedure-name procedure))
91 procedure)))
92 (if (frame-evaluating-args? frame)
93 (display " ...")
94 (begin
95 (for-each (lambda (argument)
96 (write-char #\space)
97 (write argument))
98 (frame-arguments frame))
99 (write-char #\]))))
100
101;;; Use builtin function instead:
102(set! write-frame-short/application
103 (lambda (frame)
104 (display-application frame (current-output-port) 12)))
105
106(define (write-frame-short/expression frame)
107 (write (let* ((source (frame-source frame))
108 (copy (source-property source 'copy)))
109 (if (pair? copy)
110 copy
2f843c4b 111 (unmemoize-expr source)))))
8ee7506b
NJ
112\f
113(define (write-state-long state)
114 (let ((index (state-index state)))
115 (let ((frame (stack-ref (state-stack state) index)))
116 (write-frame-index-long frame)
117 (write-frame-long frame))))
118
119(define (write-frame-index-long frame)
120 (display "Stack frame: ")
121 (write (frame-number frame))
122 (if (frame-real? frame)
123 (display " (real)"))
124 (newline))
125
126(define (write-frame-long frame)
127 (if (frame-procedure? frame)
128 (write-frame-long/application frame)
129 (write-frame-long/expression frame)))
130
131(define (write-frame-long/application frame)
132 (display "This frame is an application.")
133 (newline)
134 (if (frame-source frame)
135 (begin
136 (display "The corresponding expression is:")
137 (newline)
138 (display-source frame)
139 (newline)))
140 (display "The procedure being applied is: ")
141 (write (let ((procedure (frame-procedure frame)))
142 (or (and (procedure? procedure)
143 (procedure-name procedure))
144 procedure)))
145 (newline)
146 (display "The procedure's arguments are")
147 (if (frame-evaluating-args? frame)
148 (display " being evaluated.")
149 (begin
150 (display ": ")
151 (write (frame-arguments frame))))
152 (newline))
153
154(define (display-source frame)
155 (let* ((source (frame-source frame))
156 (copy (source-property source 'copy)))
157 (cond ((source-position source)
158 => (lambda (p) (display-position p) (display ":\n"))))
159 (display " ")
2f843c4b 160 (write (or copy (unmemoize-expr source)))))
8ee7506b
NJ
161
162(define (source-position source)
163 (let ((fname (source-property source 'filename))
164 (line (source-property source 'line))
165 (column (source-property source 'column)))
166 (and fname
167 (list fname line column))))
168
169(define (display-position pos)
170 (format #t "~A:~D:~D" (car pos) (+ 1 (cadr pos)) (+ 1 (caddr pos))))
171
172(define (write-frame-long/expression frame)
173 (display "This frame is an evaluation.")
174 (newline)
175 (display "The expression being evaluated is:")
176 (newline)
177 (display-source frame)
178 (newline))
179
180(define (write-frame-args-long frame)
181 (if (frame-procedure? frame)
182 (let ((arguments (frame-arguments frame)))
183 (let ((n (length arguments)))
184 (display "This frame has ")
185 (write n)
186 (display " argument")
187 (if (not (= n 1))
188 (display "s"))
189 (write-char (if (null? arguments) #\. #\:))
190 (newline))
191 (for-each (lambda (argument)
192 (display " ")
193 (write argument)
194 (newline))
195 arguments))
196 (begin
197 (display "This frame is an evaluation frame; it has no arguments.")
198 (newline))))
199
200(define (write-chars char n)
201 (do ((i 0 (+ i 1)))
202 ((>= i n))
203 (write-char char)))