Commit | Line | Data |
---|---|---|
07d83abe MV |
1 | @c -*-texinfo-*- |
2 | @c This is part of the GNU Guile Reference Manual. | |
e10cf6b9 | 3 | @c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2010 |
07d83abe MV |
4 | @c Free Software Foundation, Inc. |
5 | @c See the file guile.texi for copying conditions. | |
6 | ||
07d83abe MV |
7 | @node Debugging |
8 | @section Debugging Infrastructure | |
9 | ||
b20ef3a6 | 10 | @cindex Debugging |
5af872e1 | 11 | In order to understand Guile's debugging facilities, you first need to |
42cb9b03 AW |
12 | understand a little about how Guile represent the Scheme control stack. |
13 | With that in place we explain the low level trap calls that the | |
14 | evaluator can be configured to make, and the trap and breakpoint | |
5af872e1 NJ |
15 | infrastructure that builds on top of those calls. |
16 | ||
07d83abe | 17 | @menu |
5af872e1 NJ |
18 | * Evaluation Model:: Evaluation and the Scheme stack. |
19 | * Debug on Error:: Debugging when an error occurs. | |
24dbb5ed | 20 | * Traps:: |
24dbb5ed | 21 | * Debugging Examples:: |
5af872e1 NJ |
22 | @end menu |
23 | ||
24 | @node Evaluation Model | |
25 | @subsection Evaluation and the Scheme Stack | |
26 | ||
42cb9b03 AW |
27 | The idea of the Scheme stack is central to a lot of debugging. The |
28 | Scheme stack is a reified representation of the pending function returns | |
29 | in an expression's continuation. As Guile implements function calls | |
30 | using a stack, this reification takes the form of a number of nested | |
31 | stack frames, each of which has the procedure and its arguments, along | |
32 | with local variables and temporary values. | |
33 | ||
34 | A Scheme stack always exists implicitly, and can be summoned into | |
35 | concrete existence as a first-class Scheme value by the | |
36 | @code{make-stack} call, so that an introspective Scheme program -- such | |
37 | as a debugger -- can present it in some way and allow the user to query | |
38 | its details. The first thing to understand, therefore, is how Guile's | |
39 | function call convention creates the stack. | |
40 | ||
41 | Broadly speaking, Guile represents all control flow on a stack. Calling | |
42 | a function involves pushing an empty frame on the stack, then evaluating | |
43 | the procedure and its arguments, then fixing up the new frame so that it | |
44 | points to the old one. Frames on the stack are thus linked together. A | |
45 | tail call is the same, except it reuses the existing frame instead of | |
46 | pushing on a new one. | |
47 | ||
48 | In this way, the only frames that are on the stack are ``active'' | |
49 | frames, frames which need to do some work before the computation is | |
50 | complete. On the other hand, a function that has tail-called another | |
51 | function will not be on the stack, as it has no work left to do. | |
5af872e1 NJ |
52 | |
53 | Therefore, when an error occurs in a running program, or the program | |
54 | hits a breakpoint, or in fact at any point that the programmer chooses, | |
55 | its state at that point can be represented by a @dfn{stack} of all the | |
56 | evaluations and procedure applications that are logically in progress at | |
57 | that time, each of which is known as a @dfn{frame}. The programmer can | |
58 | learn more about the program's state at that point by inspecting the | |
59 | stack and its frames. | |
60 | ||
61 | @menu | |
07d83abe MV |
62 | * Capturing the Stack or Innermost Stack Frame:: |
63 | * Examining the Stack:: | |
64 | * Examining Stack Frames:: | |
5af872e1 | 65 | * Source Properties:: Remembering the source of an expression. |
07d83abe MV |
66 | * Starting a New Stack:: |
67 | @end menu | |
68 | ||
07d83abe | 69 | @node Capturing the Stack or Innermost Stack Frame |
5af872e1 | 70 | @subsubsection Capturing the Stack or Innermost Stack Frame |
07d83abe | 71 | |
5af872e1 NJ |
72 | A Scheme program can use the @code{make-stack} primitive anywhere in its |
73 | code, with first arg @code{#t}, to construct a Scheme value that | |
74 | describes the Scheme stack at that point. | |
75 | ||
76 | @lisp | |
77 | (make-stack #t) | |
78 | @result{} | |
79 | #<stack 805c840:808d250> | |
80 | @end lisp | |
07d83abe MV |
81 | |
82 | @deffn {Scheme Procedure} make-stack obj . args | |
83 | @deffnx {C Function} scm_make_stack (obj, args) | |
84 | Create a new stack. If @var{obj} is @code{#t}, the current | |
85 | evaluation stack is used for creating the stack frames, | |
86 | otherwise the frames are taken from @var{obj} (which must be | |
42cb9b03 | 87 | a continuation or a frame object). |
07d83abe MV |
88 | |
89 | @var{args} should be a list containing any combination of | |
42cb9b03 | 90 | integer, procedure, prompt tag and @code{#t} values. |
07d83abe MV |
91 | |
92 | These values specify various ways of cutting away uninteresting | |
93 | stack frames from the top and bottom of the stack that | |
94 | @code{make-stack} returns. They come in pairs like this: | |
95 | @code{(@var{inner_cut_1} @var{outer_cut_1} @var{inner_cut_2} | |
96 | @var{outer_cut_2} @dots{})}. | |
97 | ||
42cb9b03 AW |
98 | Each @var{inner_cut_N} can be @code{#t}, an integer, a prompt |
99 | tag, or a procedure. @code{#t} means to cut away all frames up | |
100 | to but excluding the first user module frame. An integer means | |
101 | to cut away exactly that number of frames. A prompt tag means | |
102 | to cut away all frames that are inside a prompt with the given | |
103 | tag. A procedure means to cut away all frames up to but | |
104 | excluding the application frame whose procedure matches the | |
105 | specified one. | |
106 | ||
107 | Each @var{outer_cut_N} can be an integer, a prompt tag, or a | |
108 | procedure. An integer means to cut away that number of frames. | |
109 | A prompt tag means to cut away all frames that are outside a | |
110 | prompt with the given tag. A procedure means to cut away | |
111 | frames down to but excluding the application frame whose | |
07d83abe MV |
112 | procedure matches the specified one. |
113 | ||
07d83abe MV |
114 | If the @var{outer_cut_N} of the last pair is missing, it is |
115 | taken as 0. | |
116 | @end deffn | |
117 | ||
07d83abe MV |
118 | |
119 | @node Examining the Stack | |
5af872e1 | 120 | @subsubsection Examining the Stack |
07d83abe MV |
121 | |
122 | @deffn {Scheme Procedure} stack? obj | |
123 | @deffnx {C Function} scm_stack_p (obj) | |
124 | Return @code{#t} if @var{obj} is a calling stack. | |
125 | @end deffn | |
126 | ||
127 | @deffn {Scheme Procedure} stack-id stack | |
128 | @deffnx {C Function} scm_stack_id (stack) | |
129 | Return the identifier given to @var{stack} by @code{start-stack}. | |
130 | @end deffn | |
131 | ||
132 | @deffn {Scheme Procedure} stack-length stack | |
133 | @deffnx {C Function} scm_stack_length (stack) | |
134 | Return the length of @var{stack}. | |
135 | @end deffn | |
136 | ||
137 | @deffn {Scheme Procedure} stack-ref stack index | |
138 | @deffnx {C Function} scm_stack_ref (stack, index) | |
139 | Return the @var{index}'th frame from @var{stack}. | |
140 | @end deffn | |
141 | ||
7cd44c6d MV |
142 | @deffn {Scheme Procedure} display-backtrace stack port [first [depth [highlights]]] |
143 | @deffnx {C Function} scm_display_backtrace_with_highlights (stack, port, first, depth, highlights) | |
07d83abe | 144 | @deffnx {C Function} scm_display_backtrace (stack, port, first, depth) |
fc3d5c43 | 145 | Display a backtrace to the output port @var{port}. @var{stack} |
07d83abe | 146 | is the stack to take the backtrace from, @var{first} specifies |
fc3d5c43 NJ |
147 | where in the stack to start and @var{depth} how many frames |
148 | to display. @var{first} and @var{depth} can be @code{#f}, | |
07d83abe | 149 | which means that default values will be used. |
fc3d5c43 NJ |
150 | If @var{highlights} is given it should be a list; the elements |
151 | of this list will be highlighted wherever they appear in the | |
152 | backtrace. | |
07d83abe MV |
153 | @end deffn |
154 | ||
155 | ||
156 | @node Examining Stack Frames | |
5af872e1 | 157 | @subsubsection Examining Stack Frames |
07d83abe MV |
158 | |
159 | @deffn {Scheme Procedure} frame? obj | |
160 | @deffnx {C Function} scm_frame_p (obj) | |
161 | Return @code{#t} if @var{obj} is a stack frame. | |
162 | @end deffn | |
163 | ||
07d83abe MV |
164 | @deffn {Scheme Procedure} frame-previous frame |
165 | @deffnx {C Function} scm_frame_previous (frame) | |
166 | Return the previous frame of @var{frame}, or @code{#f} if | |
167 | @var{frame} is the first frame in its stack. | |
168 | @end deffn | |
169 | ||
07d83abe MV |
170 | @deffn {Scheme Procedure} frame-procedure frame |
171 | @deffnx {C Function} scm_frame_procedure (frame) | |
172 | Return the procedure for @var{frame}, or @code{#f} if no | |
173 | procedure is associated with @var{frame}. | |
174 | @end deffn | |
175 | ||
176 | @deffn {Scheme Procedure} frame-arguments frame | |
177 | @deffnx {C Function} scm_frame_arguments (frame) | |
178 | Return the arguments of @var{frame}. | |
179 | @end deffn | |
180 | ||
07d83abe MV |
181 | @deffn {Scheme Procedure} display-application frame [port [indent]] |
182 | @deffnx {C Function} scm_display_application (frame, port, indent) | |
183 | Display a procedure application @var{frame} to the output port | |
184 | @var{port}. @var{indent} specifies the indentation of the | |
185 | output. | |
186 | @end deffn | |
187 | ||
188 | ||
5af872e1 NJ |
189 | @node Source Properties |
190 | @subsubsection Source Properties | |
191 | ||
192 | @cindex source properties | |
193 | As Guile reads in Scheme code from file or from standard input, it | |
194 | remembers the file name, line number and column number where each | |
42cb9b03 AW |
195 | expression begins. These pieces of information are known as the |
196 | @dfn{source properties} of the expression. Syntax expanders and the | |
197 | compiler propagate these source properties to compiled procedures, so | |
198 | that, if an error occurs when evaluating the transformed expression, | |
199 | Guile's debugger can point back to the file and location where the | |
200 | expression originated. | |
5af872e1 NJ |
201 | |
202 | The way that source properties are stored means that Guile can only | |
203 | associate source properties with parenthesized expressions, and not, for | |
204 | example, with individual symbols, numbers or strings. The difference | |
205 | can be seen by typing @code{(xxx)} and @code{xxx} at the Guile prompt | |
206 | (where the variable @code{xxx} has not been defined): | |
207 | ||
208 | @example | |
209 | guile> (xxx) | |
210 | standard input:2:1: In expression (xxx): | |
211 | standard input:2:1: Unbound variable: xxx | |
212 | ABORT: (unbound-variable) | |
213 | guile> xxx | |
214 | <unnamed port>: In expression xxx: | |
215 | <unnamed port>: Unbound variable: xxx | |
216 | ABORT: (unbound-variable) | |
217 | @end example | |
218 | ||
219 | @noindent | |
220 | In the latter case, no source properties were stored, so the best that | |
221 | Guile could say regarding the location of the problem was ``<unnamed | |
222 | port>''. | |
223 | ||
224 | The recording of source properties is controlled by the read option | |
225 | named ``positions'' (@pxref{Reader options}). This option is switched | |
42cb9b03 | 226 | @emph{on} by default. |
5af872e1 NJ |
227 | |
228 | The following procedures can be used to access and set the source | |
229 | properties of read expressions. | |
230 | ||
916f175f NJ |
231 | @deffn {Scheme Procedure} set-source-properties! obj alist |
232 | @deffnx {C Function} scm_set_source_properties_x (obj, alist) | |
233 | Install the association list @var{alist} as the source property | |
5af872e1 NJ |
234 | list for @var{obj}. |
235 | @end deffn | |
236 | ||
237 | @deffn {Scheme Procedure} set-source-property! obj key datum | |
238 | @deffnx {C Function} scm_set_source_property_x (obj, key, datum) | |
239 | Set the source property of object @var{obj}, which is specified by | |
240 | @var{key} to @var{datum}. Normally, the key will be a symbol. | |
241 | @end deffn | |
242 | ||
243 | @deffn {Scheme Procedure} source-properties obj | |
244 | @deffnx {C Function} scm_source_properties (obj) | |
245 | Return the source property association list of @var{obj}. | |
246 | @end deffn | |
247 | ||
248 | @deffn {Scheme Procedure} source-property obj key | |
249 | @deffnx {C Function} scm_source_property (obj, key) | |
916f175f NJ |
250 | Return the property specified by @var{key} from @var{obj}'s source |
251 | properties. | |
5af872e1 NJ |
252 | @end deffn |
253 | ||
42cb9b03 AW |
254 | If the @code{positions} reader option is enabled, each parenthesized |
255 | expression will have values set for the @code{filename}, @code{line} and | |
256 | @code{column} properties. | |
5af872e1 | 257 | |
1fc8dcc7 AW |
258 | If you're stuck with defmacros (@pxref{Defmacros}), and want to preserve |
259 | source information, the following helper function might be useful to | |
260 | you: | |
07d83abe | 261 | |
1fc8dcc7 AW |
262 | @deffn {Scheme Procedure} cons-source xorig x y |
263 | @deffnx {C Function} scm_cons_source (xorig, x, y) | |
264 | Create and return a new pair whose car and cdr are @var{x} and @var{y}. | |
265 | Any source properties associated with @var{xorig} are also associated | |
266 | with the new pair. | |
07d83abe MV |
267 | @end deffn |
268 | ||
269 | ||
270 | @node Starting a New Stack | |
5af872e1 | 271 | @subsubsection Starting a New Stack |
07d83abe MV |
272 | |
273 | @deffn {Scheme Syntax} start-stack id exp | |
274 | Evaluate @var{exp} on a new calling stack with identity @var{id}. If | |
275 | @var{exp} is interrupted during evaluation, backtraces will not display | |
276 | frames farther back than @var{exp}'s top-level form. This macro is a | |
277 | way of artificially limiting backtraces and stack procedures, largely as | |
278 | a convenience to the user. | |
279 | @end deffn | |
280 | ||
281 | ||
5af872e1 NJ |
282 | @node Debug on Error |
283 | @subsection Debugging when an error occurs | |
284 | ||
2202fd6c NJ |
285 | A common requirement is to be able to show as much useful context as |
286 | possible when a Scheme program hits an error. The most immediate | |
287 | information about an error is the kind of error that it is -- such as | |
288 | ``division by zero'' -- and any parameters that the code which signalled | |
289 | the error chose explicitly to provide. This information originates with | |
290 | the @code{error} or @code{throw} call (or their C code equivalents, if | |
291 | the error is detected by C code) that signals the error, and is passed | |
292 | automatically to the handler procedure of the innermost applicable | |
42cb9b03 | 293 | @code{catch} or @code{with-throw-handler} expression. |
2202fd6c NJ |
294 | |
295 | @subsubsection Intercepting basic error information | |
296 | ||
297 | Therefore, to catch errors that occur within a chunk of Scheme code, and | |
298 | to intercept basic information about those errors, you need to execute | |
42cb9b03 AW |
299 | that code inside the dynamic context of a @code{catch} or |
300 | @code{with-throw-handler} expression, or the equivalent in C. In Scheme, | |
301 | this means you need something like this: | |
2202fd6c NJ |
302 | |
303 | @lisp | |
304 | (catch #t | |
305 | (lambda () | |
306 | ;; Execute the code in which | |
307 | ;; you want to catch errors here. | |
308 | ...) | |
309 | (lambda (key . parameters) | |
310 | ;; Put the code which you want | |
311 | ;; to handle an error here. | |
312 | ...)) | |
313 | @end lisp | |
314 | ||
315 | @noindent | |
e10cf6b9 AW |
316 | The @code{catch} here can also be @code{with-throw-handler}; see @ref{Throw |
317 | Handlers} for information on the when you might want to use | |
318 | @code{with-throw-handler} instead of @code{catch}. The @code{#t} means that the | |
319 | catch is applicable to all kinds of error; if you want to restrict your catch to | |
320 | just one kind of error, you can put the symbol for that kind of error instead of | |
321 | @code{#t}. The equivalent to this in C would be something like this: | |
2202fd6c NJ |
322 | |
323 | @lisp | |
324 | SCM my_body_proc (void *body_data) | |
325 | @{ | |
326 | /* Execute the code in which | |
327 | you want to catch errors here. */ | |
328 | ... | |
329 | @} | |
330 | ||
fc3d5c43 NJ |
331 | SCM my_handler_proc (void *handler_data, |
332 | SCM key, | |
333 | SCM parameters) | |
2202fd6c NJ |
334 | @{ |
335 | /* Put the code which you want | |
336 | to handle an error here. */ | |
337 | ... | |
338 | @} | |
339 | ||
340 | @{ | |
341 | ... | |
342 | scm_c_catch (SCM_BOOL_T, | |
343 | my_body_proc, body_data, | |
344 | my_handler_proc, handler_data, | |
345 | NULL, NULL); | |
346 | ... | |
347 | @} | |
348 | @end lisp | |
349 | ||
350 | @noindent | |
351 | Again, as with the Scheme version, @code{scm_c_catch} could be replaced | |
42cb9b03 AW |
352 | by @code{scm_c_with_throw_handler}, and @code{SCM_BOOL_T} could instead |
353 | be the symbol for a particular kind of error. | |
2202fd6c NJ |
354 | |
355 | @subsubsection Capturing the full error stack | |
356 | ||
357 | The other interesting information about an error is the full Scheme | |
358 | stack at the point where the error occurred; in other words what | |
359 | innermost expression was being evaluated, what was the expression that | |
360 | called that one, and so on. If you want to write your code so that it | |
42cb9b03 | 361 | captures and can display this information as well, there are a couple |
2202fd6c NJ |
362 | important things to understand. |
363 | ||
42cb9b03 | 364 | Firstly, the stack at the point of the error needs to be explicitly |
2202fd6c | 365 | captured by a @code{make-stack} call (or the C equivalent |
fc3d5c43 | 366 | @code{scm_make_stack}). The Guile library does not do this |
2202fd6c NJ |
367 | ``automatically'' for you, so you will need to write code with a |
368 | @code{make-stack} or @code{scm_make_stack} call yourself. (We emphasise | |
369 | this point because some people are misled by the fact that the Guile | |
370 | interactive REPL code @emph{does} capture and display the stack | |
371 | automatically. But the Guile interactive REPL is itself a Scheme | |
372 | program@footnote{In effect, it is the default program which is run when | |
373 | no commands or script file are specified on the Guile command line.} | |
374 | running on top of the Guile library, and which uses @code{catch} and | |
375 | @code{make-stack} in the way we are about to describe to capture the | |
376 | stack when an error occurs.) | |
377 | ||
42cb9b03 AW |
378 | And secondly, in order to capture the stack effectively at the point |
379 | where the error occurred, the @code{make-stack} call must be made before | |
380 | Guile unwinds the stack back to the location of the prevailing catch | |
381 | expression. This means that the @code{make-stack} call must be made | |
382 | within the handler of a @code{with-throw-handler} expression, or the | |
383 | optional "pre-unwind" handler of a @code{catch}. (For the full story of | |
384 | how these alternatives differ from each other, see @ref{Exceptions}. The | |
385 | main difference is that @code{catch} terminates the error, whereas | |
386 | @code{with-throw-handler} only intercepts it temporarily and then allow | |
fc3d5c43 NJ |
387 | it to continue propagating up to the next innermost handler.) |
388 | ||
389 | So, here are some examples of how to do all this in Scheme and in C. | |
390 | For the purpose of these examples we assume that the captured stack | |
391 | should be stored in a variable, so that it can be displayed or | |
392 | arbitrarily processed later on. In Scheme: | |
393 | ||
394 | @lisp | |
395 | (let ((captured-stack #f)) | |
396 | (catch #t | |
397 | (lambda () | |
398 | ;; Execute the code in which | |
399 | ;; you want to catch errors here. | |
400 | ...) | |
401 | (lambda (key . parameters) | |
402 | ;; Put the code which you want | |
403 | ;; to handle an error after the | |
404 | ;; stack has been unwound here. | |
405 | ...) | |
406 | (lambda (key . parameters) | |
407 | ;; Capture the stack here: | |
408 | (set! captured-stack (make-stack #t)))) | |
409 | ... | |
410 | (if captured-stack | |
411 | (begin | |
412 | ;; Display or process the captured stack. | |
413 | ...)) | |
414 | ...) | |
415 | @end lisp | |
416 | ||
417 | @noindent | |
418 | And in C: | |
419 | ||
420 | @lisp | |
421 | SCM my_body_proc (void *body_data) | |
422 | @{ | |
423 | /* Execute the code in which | |
424 | you want to catch errors here. */ | |
425 | ... | |
426 | @} | |
427 | ||
428 | SCM my_handler_proc (void *handler_data, | |
429 | SCM key, | |
430 | SCM parameters) | |
431 | @{ | |
432 | /* Put the code which you want | |
433 | to handle an error after the | |
434 | stack has been unwound here. */ | |
435 | ... | |
436 | @} | |
437 | ||
438 | SCM my_preunwind_proc (void *handler_data, | |
439 | SCM key, | |
440 | SCM parameters) | |
441 | @{ | |
442 | /* Capture the stack here: */ | |
443 | *(SCM *)handler_data = scm_make_stack (SCM_BOOL_T, SCM_EOL); | |
444 | @} | |
445 | ||
446 | @{ | |
447 | SCM captured_stack = SCM_BOOL_F; | |
448 | ... | |
449 | scm_c_catch (SCM_BOOL_T, | |
450 | my_body_proc, body_data, | |
451 | my_handler_proc, handler_data, | |
452 | my_preunwind_proc, &captured_stack); | |
453 | ... | |
454 | if (captured_stack != SCM_BOOL_F) | |
455 | @{ | |
456 | /* Display or process the captured stack. */ | |
457 | ... | |
458 | @} | |
459 | ... | |
460 | @} | |
461 | @end lisp | |
462 | ||
463 | @noindent | |
464 | Note that you don't have to wait until after the @code{catch} or | |
465 | @code{scm_c_catch} has returned. You can also do whatever you like with | |
466 | the stack immediately after it has been captured in the pre-unwind | |
467 | handler, or in the normal (post-unwind) handler. (Except that for the | |
468 | latter case in C you will need to change @code{handler_data} in the | |
469 | @code{scm_c_catch(@dots{})} call to @code{&captured_stack}, so that | |
470 | @code{my_handler_proc} has access to the captured stack.) | |
471 | ||
472 | @subsubsection Displaying or interrogating the captured stack | |
473 | ||
474 | Once you have a captured stack, you can interrogate and display its | |
475 | details in any way that you want, using the @code{stack-@dots{}} and | |
476 | @code{frame-@dots{}} API described in @ref{Examining the Stack} and | |
477 | @ref{Examining Stack Frames}. | |
478 | ||
479 | If you want to print out a backtrace in the same format that the Guile | |
480 | REPL does, you can use the @code{display-backtrace} procedure to do so. | |
481 | You can also use @code{display-application} to display an individual | |
482 | application frame -- that is, a frame that satisfies the | |
483 | @code{frame-procedure?} predicate -- in the Guile REPL format. | |
484 | ||
485 | @subsubsection What the Guile REPL does | |
486 | ||
42cb9b03 AW |
487 | The Guile REPL code (in @file{system/repl/repl.scm} and related files) |
488 | uses a @code{catch} with a pre-unwind handler to capture the stack when | |
489 | an error occurs in an expression that was typed into the REPL, and saves | |
490 | the captured stack in a fluid (@pxref{Fluids and Dynamic States}) called | |
491 | @code{the-last-stack}. You can then use the @code{(backtrace)} command, | |
5b2da4cc NJ |
492 | which is basically equivalent to @code{(display-backtrace (fluid-ref |
493 | the-last-stack))}, to print out this stack at any time until it is | |
494 | overwritten by the next error that occurs. | |
fc3d5c43 | 495 | |
5af872e1 NJ |
496 | @deffn {Scheme Procedure} backtrace [highlights] |
497 | @deffnx {C Function} scm_backtrace_with_highlights (highlights) | |
498 | @deffnx {C Function} scm_backtrace () | |
499 | Display a backtrace of the stack saved by the last error | |
fc3d5c43 NJ |
500 | to the current output port. If @var{highlights} is given |
501 | it should be a list; the elements of this list will be | |
502 | highlighted wherever they appear in the backtrace. | |
5af872e1 NJ |
503 | @end deffn |
504 | ||
5b2da4cc NJ |
505 | You can also use the @code{(debug)} command to explore the saved stack |
506 | using an interactive command-line-driven debugger. See @ref{Interactive | |
507 | Debugger} for more information about this. | |
508 | ||
5af872e1 NJ |
509 | @deffn {Scheme Procedure} debug |
510 | Invoke the Guile debugger to explore the context of the last error. | |
511 | @end deffn | |
512 | ||
62ae9557 | 513 | |
24dbb5ed NJ |
514 | @node Traps |
515 | @subsection Traps | |
62ae9557 NJ |
516 | |
517 | @cindex Traps | |
518 | @cindex Evaluator trap calls | |
519 | @cindex Breakpoints | |
520 | @cindex Trace | |
521 | @cindex Tracing | |
522 | @cindex Code coverage | |
523 | @cindex Profiling | |
42cb9b03 AW |
524 | Guile's virtual machine can be configured to call out at key points to |
525 | arbitrary user-specified procedures. For more information on these | |
526 | hooks, and the circumstances under which the VM calls them, see @ref{VM | |
527 | Behaviour}. | |
528 | ||
529 | In principle, these hooks allow Scheme code to implement any model it | |
530 | chooses for examining the evaluation stack as program execution | |
531 | proceeds, and for suspending execution to be resumed later. Possible | |
532 | applications of this feature include breakpoints, runtime tracing, code | |
533 | coverage, and profiling. | |
62ae9557 NJ |
534 | |
535 | @cindex Trap classes | |
536 | @cindex Trap objects | |
24dbb5ed NJ |
537 | Based on these low level trap calls, Guile provides a higher level, |
538 | object-oriented interface for the manipulation of traps. Different | |
539 | kinds of trap are represented as GOOPS classes; for example, the | |
540 | @code{<procedure-trap>} class describes traps that are triggered by | |
541 | invocation of a specified procedure. A particular instance of a trap | |
542 | class --- or @dfn{trap object} --- describes the condition under which | |
543 | a single trap will be triggered, and what will happen then; for | |
544 | example, an instance of @code{<procedure-trap>} whose @code{procedure} | |
545 | and @code{behaviour} slots contain @code{my-factorial} and | |
546 | @code{debug-trap} would be a trap that enters the command line | |
547 | debugger when the @code{my-factorial} procedure is invoked. | |
548 | ||
549 | The following subsections describe all this in detail, for both the | |
550 | user wanting to use traps, and the developer interested in | |
62ae9557 NJ |
551 | understanding how the interface hangs together. |
552 | ||
553 | ||
42cb9b03 AW |
554 | @subsubsection Actually, this section is bitrotten |
555 | ||
556 | Dear reader: the following sections have some great ideas, and some code | |
557 | that just needs a few days of massaging to get it to work with the VM | |
558 | (as opposed to the old interpreter). Want to help? Yes? Yes! | |
559 | @code{guile-devel@@gnu.org}, that's where. | |
560 | ||
561 | ||
62ae9557 NJ |
562 | @subsubsection A Quick Note on Terminology |
563 | ||
564 | @cindex Trap terminology | |
565 | It feels natural to use the word ``trap'' in some form for all levels | |
566 | of the structure just described, so we need to be clear on the | |
567 | terminology we use to describe each particular level. The terminology | |
568 | used in this subsection is as follows. | |
569 | ||
570 | @itemize @bullet | |
571 | @item | |
572 | @cindex Evaluator trap calls | |
573 | @cindex Low level trap calls | |
574 | ``Low level trap calls'', or ``low level traps'', are the calls made | |
575 | directly from the C code of the Guile evaluator. | |
576 | ||
577 | @item | |
578 | @cindex Trap classes | |
579 | ``Trap classes'' are self-explanatory. | |
580 | ||
581 | @item | |
582 | @cindex Trap objects | |
583 | ``Trap objects'', ``trap instances'', or just ``traps'', are instances | |
584 | of a trap class, and each describe a single logical trap condition | |
585 | plus behaviour as specified by the user of this interface. | |
586 | @end itemize | |
587 | ||
588 | A good example of when it is important to be clear, is when we talk | |
589 | below of behaviours that should only happen once per low level trap. | |
590 | A single low level trap call will typically map onto the processing of | |
591 | several trap objects, so ``once per low level trap'' is significantly | |
592 | different from ``once per trap''. | |
593 | ||
594 | ||
595 | @menu | |
596 | * How to Set a Trap:: | |
597 | * Specifying Trap Behaviour:: | |
598 | * Trap Context:: | |
599 | * Tracing Examples:: | |
600 | * Tracing Configuration:: | |
601 | * Tracing and (ice-9 debug):: | |
602 | * Traps Installing More Traps:: | |
603 | * Common Trap Options:: | |
604 | * Procedure Traps:: | |
605 | * Exit Traps:: | |
606 | * Entry Traps:: | |
607 | * Apply Traps:: | |
608 | * Step Traps:: | |
609 | * Source Traps:: | |
610 | * Location Traps:: | |
611 | * Trap Shorthands:: | |
612 | * Trap Utilities:: | |
613 | @end menu | |
614 | ||
615 | ||
616 | @node How to Set a Trap | |
617 | @subsubsection How to Set a Trap | |
618 | ||
619 | @cindex Setting traps | |
620 | @cindex Installing and uninstalling traps | |
621 | Setting a trap is done in two parts. First the trap is defined by | |
622 | creating an instance of the appropriate trap class, with slot values | |
623 | specifying the condition under which the trap will fire and the action | |
624 | to take when it fires. Secondly the trap object thus created must be | |
625 | @dfn{installed}. | |
626 | ||
627 | To make this immediately concrete, here is an example that sets a trap | |
628 | to fire on the next application of the @code{facti} procedure, and to | |
629 | handle the trap by entering the command line debugger. | |
630 | ||
631 | @lisp | |
632 | (install-trap (make <procedure-trap> | |
633 | #:procedure facti | |
634 | #:single-shot #t | |
635 | #:behaviour debug-trap)) | |
636 | @end lisp | |
637 | ||
638 | @noindent | |
639 | Briefly, the elements of this incantation are as follows. (All of | |
640 | these are described more fully in the following subsubsections.) | |
641 | ||
642 | @itemize @bullet | |
643 | @item | |
644 | @code{<procedure-trap>} is the trap class for trapping on invocation | |
645 | of a specific procedure. | |
646 | ||
647 | @item | |
648 | @code{#:procedure facti} says that the specific procedure to trap on for this | |
649 | trap object is @code{facti}. | |
650 | ||
651 | @item | |
652 | @code{#:single-shot #t} says that this trap should only fire on the | |
653 | @emph{next} invocation of @code{facti}, not on all future invocations | |
654 | (which is the default if the @code{#:single-shot} option is not | |
655 | specified). | |
656 | ||
657 | @item | |
658 | @code{#:behaviour debug-trap} says that the trap infrastructure should | |
659 | call the procedure @code{debug-trap} when this trap fires. | |
660 | ||
661 | @item | |
662 | Finally, the @code{install-trap} call installs the trap immediately. | |
663 | @end itemize | |
664 | ||
665 | @noindent | |
666 | It is of course possible for the user to define more convenient | |
667 | shorthands for setting common kinds of traps. @xref{Trap Shorthands}, | |
668 | for some examples. | |
669 | ||
670 | The ability to install, uninstall and reinstall a trap without losing | |
24dbb5ed NJ |
671 | its definition is Guile's equivalent of the disable/enable commands |
672 | provided by debuggers like GDB. | |
62ae9557 NJ |
673 | |
674 | @deffn {Generic Function} install-trap trap | |
675 | Install the trap object @var{trap}, so that its behaviour will be | |
676 | executed when the conditions for the trap firing are met. | |
677 | @end deffn | |
678 | ||
679 | @deffn {Generic Function} uninstall-trap trap | |
680 | Uninstall the trap object @var{trap}, so that its behaviour will | |
681 | @emph{not} be executed even if the conditions for the trap firing are | |
682 | met. | |
683 | @end deffn | |
684 | ||
685 | ||
686 | @node Specifying Trap Behaviour | |
687 | @subsubsection Specifying Trap Behaviour | |
688 | ||
689 | @cindex Trap behaviour | |
24dbb5ed NJ |
690 | Guile provides several ``out-of-the-box'' behaviours for common needs. |
691 | All of the following can be used directly as the value of the | |
692 | @code{#:behaviour} option when creating a trap object. | |
62ae9557 NJ |
693 | |
694 | @deffn {Procedure} debug-trap trap-context | |
695 | Enter Guile's command line debugger to explore the stack at | |
696 | @var{trap-context}, and to single-step or continue program execution | |
697 | from that point. | |
698 | @end deffn | |
699 | ||
700 | @deffn {Procedure} gds-debug-trap trap-context | |
701 | Use the GDS debugging interface, which displays the stack and | |
702 | corresponding source code via Emacs, to explore the stack at | |
703 | @var{trap-context} and to single-step or continue program execution | |
704 | from that point. | |
705 | @end deffn | |
706 | ||
707 | @cindex Trace | |
708 | @cindex Tracing | |
709 | @deffn {Procedure} trace-trap trap-context | |
710 | Display trace information to summarize the current @var{trap-context}. | |
711 | @end deffn | |
712 | ||
713 | @deffn {Procedure} trace-at-exit trap-context | |
714 | Install a further trap to cause the return value of the application or | |
715 | evaluation just starting (as described by @var{trap-context}) to be | |
716 | traced using @code{trace-trap}, when this application or evaluation | |
717 | completes. The extra trap is automatically uninstalled after the | |
718 | return value has been traced. | |
719 | @end deffn | |
720 | ||
721 | @deffn {Procedure} trace-until-exit trap-context | |
722 | Install a further trap so that every step that the evaluator performs | |
723 | as part of the application or evaluation just starting (as described | |
724 | by @var{trap-context}) is traced using @code{trace-trap}. The extra | |
725 | trap is automatically uninstalled when the application or evaluation | |
726 | is complete. @code{trace-until-exit} can be very useful as a first | |
727 | step when all you know is that there is a bug ``somewhere in XXX or in | |
728 | something that XXX calls''. | |
729 | @end deffn | |
730 | ||
731 | @noindent | |
732 | @code{debug-trap} and @code{gds-debug-trap} are provided by the modules | |
733 | @code{(ice-9 debugger)} and @code{(ice-9 gds-client)} respectively, and | |
734 | their behaviours are fairly self-explanatory. For more information on | |
735 | the operation of the GDS interface via Emacs, see @ref{Using Guile in | |
736 | Emacs}. The tracing behaviours are explained more fully below. | |
737 | ||
738 | @cindex Trap context | |
739 | More generally, the @dfn{behaviour} specified for a trap can be any | |
740 | procedure that expects to be called with one @dfn{trap context} | |
741 | argument. A trivial example would be: | |
742 | ||
743 | @lisp | |
744 | (define (report-stack-depth trap-context) | |
745 | (display "Stack depth at the trap is: ") | |
746 | (display (tc:depth trap-context)) | |
747 | (newline)) | |
748 | @end lisp | |
749 | ||
750 | ||
751 | @node Trap Context | |
752 | @subsubsection Trap Context | |
753 | ||
754 | The @dfn{trap context} is an object that caches information about the | |
755 | low level trap call and the stack at the point of the trap, and is | |
756 | passed as the only argument to all behaviour procedures. The | |
757 | information in the trap context can be accessed through the procedures | |
758 | beginning @code{tc:} that are exported by the @code{(ice-9 debugging | |
759 | traps)} module@footnote{Plus of course any procedures that build on | |
760 | these, such as the @code{trace/@dots{}} procedures exported by | |
761 | @code{(ice-9 debugging trace)} (@pxref{Tracing Configuration}).}; the | |
762 | most useful of these are as follows. | |
763 | ||
764 | @deffn {Generic Function} tc:type trap-context | |
765 | Indicates the type of the low level trap by returning one of the | |
766 | keywords @code{#:application}, @code{#:evaluation}, @code{#:return} or | |
767 | @code{#:error}. | |
768 | @end deffn | |
769 | ||
770 | @deffn {Generic Function} tc:return-value trap-context | |
771 | When @code{tc:type} gives @code{#:return}, this provides the value | |
772 | that is being returned. | |
773 | @end deffn | |
774 | ||
775 | @deffn {Generic Function} tc:stack trap-context | |
776 | Provides the stack at the point of the trap (as computed by | |
777 | @code{make-stack}, but cached so that the lengthy @code{make-stack} | |
778 | operation is not performed more than once for the same low level | |
779 | trap). | |
780 | @end deffn | |
781 | ||
782 | @deffn {Generic Function} tc:frame trap-context | |
783 | The innermost frame of the stack at the point of the trap. | |
784 | @end deffn | |
785 | ||
786 | @deffn {Generic Function} tc:depth trap-context | |
787 | The number of frames (including tail recursive non-real frames) in the | |
788 | stack at the point of the trap. | |
789 | @end deffn | |
790 | ||
791 | @deffn {Generic Function} tc:real-depth trap-context | |
792 | The number of real frames (that is, excluding the non-real frames that | |
793 | describe tail recursive calls) in the stack at the point of the trap. | |
794 | @end deffn | |
795 | ||
796 | ||
797 | @node Tracing Examples | |
798 | @subsubsection Tracing Examples | |
799 | ||
800 | The following examples show what tracing is and the kind of output that | |
801 | it generates. In the first example, we define a recursive function for | |
802 | reversing a list, then watch the effect of the recursive calls by | |
803 | tracing each call and return value. | |
804 | ||
805 | @lisp | |
806 | guile> (define (rev ls) | |
807 | (if (null? ls) | |
808 | ls | |
809 | (append (rev (cdr ls)) | |
810 | (list (car ls))))) | |
811 | guile> (use-modules (ice-9 debugging traps) (ice-9 debugging trace)) | |
812 | guile> (define t1 (make <procedure-trap> | |
813 | #:procedure rev | |
814 | #:behaviour (list trace-trap | |
815 | trace-at-exit))) | |
816 | guile> (install-trap t1) | |
817 | guile> (rev '(a b c)) | |
818 | | 2: [rev (a b c)] | |
819 | | 3: [rev (b c)] | |
820 | | 4: [rev (c)] | |
821 | | 5: [rev ()] | |
822 | | 5: =>() | |
823 | | 4: =>(c) | |
824 | | 3: =>(c b) | |
825 | | 2: =>(c b a) | |
826 | (c b a) | |
827 | @end lisp | |
828 | ||
829 | @noindent | |
830 | The number before the colon in this output (which follows @code{(ice-9 | |
831 | debugging trace)}'s default output format) is the number of real frames | |
832 | on the stack. The fact that this number increases for each recursive | |
833 | call confirms that the implementation above of @code{rev} is not | |
834 | tail-recursive. | |
835 | ||
836 | In the next example, we probe the @emph{internal} workings of | |
837 | @code{rev} in more detail by using the @code{trace-until-exit} | |
838 | behaviour. | |
839 | ||
840 | @lisp | |
841 | guile> (uninstall-trap t1) | |
842 | guile> (define t2 (make <procedure-trap> | |
843 | #:procedure rev | |
844 | #:behaviour (list trace-trap | |
845 | trace-until-exit))) | |
846 | guile> (install-trap t2) | |
847 | guile> (rev '(a b)) | |
848 | | 2: [rev (a b)] | |
849 | | 2: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) | |
850 | | 3: (null? ls) | |
851 | | 3: [null? (a b)] | |
852 | | 3: =>#f | |
853 | | 2: (append (rev (cdr ls)) (list (car ls))) | |
854 | | 3: (rev (cdr ls)) | |
855 | | 4: (cdr ls) | |
856 | | 4: [cdr (a b)] | |
857 | | 4: =>(b) | |
858 | | 3: [rev (b)] | |
859 | | 3: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) | |
860 | | 4: (null? ls) | |
861 | | 4: [null? (b)] | |
862 | | 4: =>#f | |
863 | | 3: (append (rev (cdr ls)) (list (car ls))) | |
864 | | 4: (rev (cdr ls)) | |
865 | | 5: (cdr ls) | |
866 | | 5: [cdr (b)] | |
867 | | 5: =>() | |
868 | | 4: [rev ()] | |
869 | | 4: (if (null? ls) ls (append (rev (cdr ls)) (list (car ls)))) | |
870 | | 5: (null? ls) | |
871 | | 5: [null? ()] | |
872 | | 5: =>#t | |
873 | | 4: (list (car ls)) | |
874 | | 5: (car ls) | |
875 | | 5: [car (b)] | |
876 | | 5: =>b | |
877 | | 4: [list b] | |
878 | | 4: =>(b) | |
879 | | 3: [append () (b)] | |
880 | | 3: =>(b) | |
881 | | 3: (list (car ls)) | |
882 | | 4: (car ls) | |
883 | | 4: [car (a b)] | |
884 | | 4: =>a | |
885 | | 3: [list a] | |
886 | | 3: =>(a) | |
887 | | 2: [append (b) (a)] | |
888 | | 2: =>(b a) | |
889 | (b a) | |
890 | @end lisp | |
891 | ||
892 | @noindent | |
893 | The output in this case shows every step that the evaluator performs | |
894 | in evaluating @code{(rev '(a b))}. | |
895 | ||
896 | ||
897 | @node Tracing Configuration | |
898 | @subsubsection Tracing Configuration | |
899 | ||
900 | The detail of what gets printed in each trace line, and the port to | |
901 | which tracing is written, can be configured by the procedures | |
902 | @code{set-trace-layout} and @code{trace-port}, both exported by the | |
903 | @code{(ice-9 debugging trace)} module. | |
904 | ||
905 | @deffn {Procedure with Setter} trace-port | |
906 | Get or set the port to which tracing is printed. The default is the | |
907 | value of @code{(current-output-port)} when the @code{(ice-9 debugging | |
908 | trace)} module is first loaded. | |
909 | @end deffn | |
910 | ||
911 | @deffn {Procedure} set-trace-layout format-string . arg-procs | |
912 | Layout each trace line using @var{format-string} and @var{arg-procs}. | |
913 | For each trace line, the list of values to be printed is obtained by | |
914 | calling all the @var{arg-procs}, passing the trap context as the only | |
915 | parameter to each one. This list of values is then formatted using | |
916 | the specified @var{format-string}. | |
917 | @end deffn | |
918 | ||
919 | @noindent | |
920 | The @code{(ice-9 debugging trace)} module exports a set of arg-proc | |
921 | procedures to cover most common needs, with names beginning | |
922 | @code{trace/}. These are all implemented on top of the @code{tc:} trap | |
923 | context accessor procedures documented in @ref{Trap Context}, and if any | |
924 | trace output not provided by the following is needed, it should be | |
925 | possible to implement based on a combination of the @code{tc:} | |
926 | procedures. | |
927 | ||
928 | @deffn {Procedure} trace/pid trap-context | |
929 | An arg-proc that returns the current process ID. | |
930 | @end deffn | |
931 | ||
932 | @deffn {Procedure} trace/stack-id trap-context | |
933 | An arg-proc that returns the stack ID of the stack in which the | |
934 | current trap occurred. | |
935 | @end deffn | |
936 | ||
937 | @deffn {Procedure} trace/stack-depth trap-context | |
938 | An arg-proc that returns the length (including non-real frames) of the | |
939 | stack at the point of the current trap. | |
940 | @end deffn | |
941 | ||
942 | @deffn {Procedure} trace/stack-real-depth trap-context | |
943 | An arg-proc that returns the length excluding non-real frames of the | |
944 | stack at the point of the current trap. | |
945 | @end deffn | |
946 | ||
947 | @deffn {Procedure} trace/stack trap-context | |
948 | An arg-proc that returns a string summarizing stack information. This | |
949 | string includes the stack ID, real depth, and count of additional | |
950 | non-real frames, with the format @code{"~a:~a+~a"}. | |
951 | @end deffn | |
952 | ||
953 | @deffn {Procedure} trace/source-file-name trap-context | |
954 | An arg-proc that returns the name of the source file for the innermost | |
955 | stack frame, or an empty string if source is not available for the | |
956 | innermost frame. | |
957 | @end deffn | |
958 | ||
959 | @deffn {Procedure} trace/source-line trap-context | |
960 | An arg-proc that returns the line number of the source code for the | |
961 | innermost stack frame, or zero if source is not available for the | |
962 | innermost frame. | |
963 | @end deffn | |
964 | ||
965 | @deffn {Procedure} trace/source-column trap-context | |
966 | An arg-proc that returns the column number of the start of the source | |
967 | code for the innermost stack frame, or zero if source is not available | |
968 | for the innermost frame. | |
969 | @end deffn | |
970 | ||
971 | @deffn {Procedure} trace/source trap-context | |
972 | An arg-proc that returns the source location for the innermost stack | |
973 | frame. This is a string composed of file name, line and column number | |
974 | with the format @code{"~a:~a:~a"}, or an empty string if source is not | |
975 | available for the innermost frame. | |
976 | @end deffn | |
977 | ||
978 | @deffn {Procedure} trace/type trap-context | |
979 | An arg-proc that returns a three letter abbreviation indicating the | |
980 | type of the current trap: @code{"APP"} for an application frame, | |
981 | @code{"EVA"} for an evaluation, @code{"RET"} for an exit trap, or | |
982 | @code{"ERR"} for an error (pseudo-)trap. | |
983 | @end deffn | |
984 | ||
985 | @deffn {Procedure} trace/real? trap-context | |
986 | An arg-proc that returns @code{" "} if the innermost stack frame is a | |
987 | real frame, or @code{"t"} if it is not. | |
988 | @end deffn | |
989 | ||
990 | @deffn {Procedure} trace/info trap-context | |
991 | An arg-proc that returns a string describing the expression being | |
992 | evaluated, application being performed, or return value, according to | |
993 | the current trap type. | |
994 | @end deffn | |
995 | ||
996 | @noindent | |
997 | @code{trace/stack-depth} and @code{trace/stack-real-depth} are identical | |
998 | to the trap context methods @code{tc:depth} and @code{tc:real-depth} | |
999 | described before (@pxref{Trap Context}), but renamed here for | |
1000 | convenience. | |
1001 | ||
1002 | The default trace layout, as exhibited by the examples of the previous | |
1003 | subsubsubsection, is set by this line of code from the @code{(ice-9 debugging | |
1004 | traps)} module: | |
1005 | ||
1006 | @lisp | |
1007 | (set-trace-layout "|~3@@a: ~a\n" trace/stack-real-depth trace/info) | |
1008 | @end lisp | |
1009 | ||
1010 | @noindent | |
1011 | If we rerun the first of those examples, but with trace layout | |
1012 | configured to show source location and trap type in addition, the | |
1013 | output looks like this: | |
1014 | ||
1015 | @lisp | |
1016 | guile> (set-trace-layout "| ~25a ~3@@a: ~a ~a\n" | |
1017 | trace/source | |
1018 | trace/stack-real-depth | |
1019 | trace/type | |
1020 | trace/info) | |
1021 | guile> (rev '(a b c)) | |
1022 | | standard input:29:0 2: APP [rev (a b c)] | |
1023 | | standard input:4:21 3: APP [rev (b c)] | |
1024 | | standard input:4:21 4: APP [rev (c)] | |
1025 | | standard input:4:21 5: APP [rev ()] | |
1026 | | standard input:2:9 5: RET =>() | |
1027 | | standard input:4:13 4: RET =>(c) | |
1028 | | standard input:4:13 3: RET =>(c b) | |
1029 | | standard input:4:13 2: RET =>(c b a) | |
1030 | (c b a) | |
1031 | @end lisp | |
1032 | ||
1033 | ||
1034 | @node Tracing and (ice-9 debug) | |
1035 | @subsubsection Tracing and (ice-9 debug) | |
1036 | ||
24dbb5ed NJ |
1037 | The @code{(ice-9 debug)} module provides a tracing facility |
1038 | (@pxref{Tracing}) that is roughly similar to that described here, but | |
1039 | there are important differences. | |
62ae9557 NJ |
1040 | |
1041 | @itemize @bullet | |
1042 | @item | |
1043 | The @code{(ice-9 debug)} trace gives a nice pictorial view of changes | |
1044 | in stack depth, by using indentation like this: | |
1045 | ||
1046 | @lisp | |
1047 | [fact1 4] | |
1048 | | [fact1 3] | |
1049 | | | [fact1 2] | |
1050 | | | | [fact1 1] | |
1051 | | | | | [fact1 0] | |
1052 | | | | | 1 | |
1053 | | | | 1 | |
1054 | | | 2 | |
1055 | | 6 | |
1056 | 24 | |
1057 | @end lisp | |
1058 | ||
1059 | However its output can @emph{only} show the information seen here, | |
24dbb5ed NJ |
1060 | which corresponds to @code{(ice-9 debugging trace)}'s |
1061 | @code{trace/info} procedure; it cannot be configured to show other | |
1062 | pieces of information about the trap context in the way that the | |
1063 | @code{(ice-9 debugging trace)} implementation can. | |
62ae9557 NJ |
1064 | |
1065 | @item | |
1066 | The @code{(ice-9 debug)} trace only allows the tracing of procedure | |
24dbb5ed NJ |
1067 | applications and their return values, whereas the @code{(ice-9 debugging |
1068 | trace)} implementation allows any kind of trap to be traced. | |
62ae9557 NJ |
1069 | |
1070 | It's interesting to note that @code{(ice-9 debug)}'s restriction here, | |
1071 | which might initially appear to be just a straightforward consequence | |
1072 | of its implementation, is also somewhat dictated by its pictorial | |
1073 | display. The use of indentation in the output relies on hooking into | |
1074 | the low level trap calls in such a way that the trapped application | |
24dbb5ed NJ |
1075 | entries and exits exactly balance each other. The @code{ice-9 |
1076 | debugging trace} implementation allows traps to be installed such that | |
1077 | entry and exit traps don't necessarily balance, which means that, in | |
1078 | general, indentation diagrams like the one above don't work. | |
62ae9557 NJ |
1079 | @end itemize |
1080 | ||
1081 | It isn't currently possible to use both @code{(ice-9 debug)} trace and | |
24dbb5ed NJ |
1082 | @code{(ice-9 debugging trace)} in the same Guile session, because |
1083 | their settings of the low level trap options conflict with each other. | |
62ae9557 NJ |
1084 | |
1085 | ||
1086 | @node Traps Installing More Traps | |
1087 | @subsubsection Traps Installing More Traps | |
1088 | ||
1089 | Sometimes it is desirable for the behaviour at one trap to install | |
1090 | further traps. In other words, the behaviour is something like | |
1091 | ``Don't do much right now, but set things up to stop after two or | |
1092 | three more steps'', or ``@dots{} when this frame completes''. This is | |
1093 | absolutely fine. For example, it is easy to code a generic ``do | |
1094 | so-and-so when the current frame exits'' procedure, which can be used | |
1095 | wherever a trap context is available, as follows. | |
1096 | ||
1097 | @lisp | |
1098 | (define (at-exit trap-context behaviour) | |
1099 | (install-trap (make <exit-trap> | |
1100 | #:depth (tc:depth trap-context) | |
1101 | #:single-shot #t | |
1102 | #:behaviour behaviour))) | |
1103 | @end lisp | |
1104 | ||
1105 | To continue and pin down the example, this could then be used as part | |
1106 | of a behaviour whose purpose was to measure the accumulated time spent | |
1107 | in and below a specified procedure. | |
1108 | ||
1109 | @lisp | |
1110 | (define calls 0) | |
1111 | (define total 0) | |
1112 | ||
1113 | (define accumulate-time | |
1114 | (lambda (trap-context) | |
1115 | (set! calls (+ calls 1)) | |
1116 | (let ((entry (current-time))) | |
1117 | (at-exit trap-context | |
1118 | (lambda (ignored) | |
1119 | (set! total | |
1120 | (+ total (- (current-time) | |
1121 | entry)))))))) | |
1122 | ||
1123 | (install-trap (make <procedure-trap> | |
1124 | #:procedure my-proc | |
1125 | #:behaviour accumulate-time)) | |
1126 | @end lisp | |
1127 | ||
1128 | ||
1129 | @node Common Trap Options | |
1130 | @subsubsection Common Trap Options | |
1131 | ||
1132 | When creating any kind of trap object, settings for the trap being | |
1133 | created are specified as options on the @code{make} call using syntax | |
1134 | like this: | |
1135 | ||
1136 | @lisp | |
1137 | (make <@var{trap-class}> | |
1138 | #:@var{option-keyword} @var{setting} | |
1139 | @dots{}) | |
1140 | @end lisp | |
1141 | ||
1142 | The following common options are provided by the base class | |
1143 | @code{<trap>}, and so can be specified for any kind of trap. | |
1144 | ||
1145 | @deffn {Class} <trap> | |
1146 | Base class for trap objects. | |
1147 | @end deffn | |
1148 | ||
1149 | @deffn {Trap Option} #:condition thunk | |
1150 | If not @code{#f}, this is a thunk which is called when the trap fires, | |
1151 | to determine whether trap processing should proceed any further. If | |
1152 | the thunk returns @code{#f}, the trap is basically suppressed. | |
1153 | Otherwise processing continues normally. (Default value @code{#f}.) | |
1154 | @end deffn | |
1155 | ||
1156 | @deffn {Trap Option} #:skip-count count | |
1157 | A count of valid (after @code{#:condition} processing) firings of this | |
1158 | trap to skip. (Default value 0.) | |
1159 | @end deffn | |
1160 | ||
1161 | @deffn {Trap Option} #:single-shot boolean | |
1162 | If not @code{#f}, this indicates that the trap should be automatically | |
1163 | uninstalled after it has successfully fired (after @code{#:condition} | |
1164 | and @code{#:skip-count} processing) for the first time. (Default | |
1165 | value @code{#f}.) | |
1166 | @end deffn | |
1167 | ||
1168 | @deffn {Trap Option} #:behaviour behaviour-proc | |
1169 | A trap behaviour procedure --- as discussed in the preceding subsubsection | |
1170 | --- or a list of such procedures, in which case each procedure is | |
1171 | called in turn when the trap fires. (Default value @code{'()}.) | |
1172 | @end deffn | |
1173 | ||
1174 | @deffn {Trap Option} #:repeat-identical-behaviour boolean | |
1175 | Normally, if multiple trap objects are triggered by the same low level | |
1176 | trap, and they request the same behaviour, it's only actually useful | |
1177 | to do that behaviour once (per low level trap); so by default multiple | |
1178 | requests for the same behaviour are coalesced. If this option is set | |
1179 | other than @code{#f}, the contents of the @code{#:behaviour} option | |
1180 | are uniquified so that they avoid being coalesced in this way. | |
1181 | (Default value @code{#f}.) | |
1182 | @end deffn | |
1183 | ||
1184 | ||
1185 | @node Procedure Traps | |
1186 | @subsubsection Procedure Traps | |
1187 | ||
1188 | The @code{<procedure-trap>} class implements traps that are triggered | |
1189 | upon application of a specified procedure. Instances of this class | |
1190 | should use the @code{#:procedure} option to specify the procedure to | |
1191 | trap on. | |
1192 | ||
1193 | @deffn {Class} <procedure-trap> | |
1194 | Class for traps triggered by application of a specified procedure. | |
1195 | @end deffn | |
1196 | ||
1197 | @deffn {Trap Option} #:procedure procedure | |
1198 | Specifies the procedure to trap on. | |
1199 | @end deffn | |
1200 | ||
1201 | @noindent | |
1202 | Example: | |
1203 | ||
1204 | @lisp | |
1205 | (install-trap (make <procedure-trap> | |
1206 | #:procedure my-proc | |
1207 | #:behaviour (list trace-trap | |
1208 | trace-until-exit))) | |
1209 | @end lisp | |
1210 | ||
1211 | ||
1212 | @node Exit Traps | |
1213 | @subsubsection Exit Traps | |
1214 | ||
1215 | The @code{<exit-trap>} class implements traps that are triggered upon | |
1216 | stack frame exit past a specified stack depth. Instances of this | |
1217 | class should use the @code{#:depth} option to specify the target stack | |
1218 | depth. | |
1219 | ||
1220 | @deffn {Class} <exit-trap> | |
1221 | Class for traps triggered by exit past a specified stack depth. | |
1222 | @end deffn | |
1223 | ||
1224 | @deffn {Trap Option} #:depth depth | |
1225 | Specifies the reference depth for the trap. | |
1226 | @end deffn | |
1227 | ||
1228 | @noindent | |
1229 | Example: | |
1230 | ||
1231 | @lisp | |
1232 | (define (trace-at-exit trap-context) | |
1233 | (install-trap (make <exit-trap> | |
1234 | #:depth (tc:depth trap-context) | |
1235 | #:single-shot #t | |
1236 | #:behaviour trace-trap))) | |
1237 | @end lisp | |
1238 | ||
1239 | @noindent | |
1240 | (This is the actual definition of the @code{trace-at-exit} behaviour.) | |
1241 | ||
1242 | ||
1243 | @node Entry Traps | |
1244 | @subsubsection Entry Traps | |
1245 | ||
1246 | The @code{<entry-trap>} class implements traps that are triggered upon | |
1247 | any stack frame entry. No further parameters are needed to specify an | |
1248 | instance of this class, so there are no class-specific trap options. | |
1249 | Note that it remains possible to use the common trap options | |
1250 | (@pxref{Common Trap Options}), for example to set a trap for the | |
1251 | @var{n}th next frame entry. | |
1252 | ||
1253 | @deffn {Class} <entry-trap> | |
1254 | Class for traps triggered by any stack frame entry. | |
1255 | @end deffn | |
1256 | ||
1257 | @noindent | |
1258 | Example: | |
1259 | ||
1260 | @lisp | |
1261 | (install-trap (make <entry-trap> | |
1262 | #:skip-count 5 | |
1263 | #:behaviour gds-debug-trap)) | |
1264 | @end lisp | |
1265 | ||
1266 | ||
1267 | @node Apply Traps | |
1268 | @subsubsection Apply Traps | |
1269 | ||
1270 | The @code{<apply-trap>} class implements traps that are triggered upon | |
1271 | any procedure application. No further parameters are needed to | |
1272 | specify an instance of this class, so there are no class-specific trap | |
1273 | options. Note that it remains possible to use the common trap options | |
1274 | (@pxref{Common Trap Options}), for example to set a trap for the next | |
1275 | application where some condition is true. | |
1276 | ||
1277 | @deffn {Class} <apply-trap> | |
1278 | Class for traps triggered by any procedure application. | |
1279 | @end deffn | |
1280 | ||
1281 | @noindent | |
1282 | Example: | |
1283 | ||
1284 | @lisp | |
1285 | (install-trap (make <apply-trap> | |
1286 | #:condition my-condition | |
1287 | #:behaviour gds-debug-trap)) | |
1288 | @end lisp | |
1289 | ||
1290 | ||
1291 | @node Step Traps | |
1292 | @subsubsection Step Traps | |
1293 | ||
1294 | The @code{<step-trap>} class implements traps that do single-stepping | |
1295 | through a program's execution. They come in two flavours, with and | |
1296 | without a specified file name. If a file name is specified, the trap | |
1297 | is triggered by the next evaluation, application or frame exit | |
1298 | pertaining to source code from the specified file. If a file name is | |
1299 | not specified, the trap is triggered by the next evaluation, | |
1300 | application or frame exit from any file (or for code whose source | |
1301 | location was not recorded), in other words by the next evaluator step | |
1302 | of any kind. | |
1303 | ||
1304 | The design goal of the @code{<step-trap>} class is to match what a | |
1305 | user would intuitively think of as single-stepping through their code, | |
1306 | either through code in general (roughly corresponding to GDB's | |
1307 | @code{step} command, for example), or through code from a particular | |
1308 | source file (roughly corresponding to GDB's @code{next}). Therefore | |
24dbb5ed NJ |
1309 | if you are using a step trap to single-step through code and finding |
1310 | its behaviour counter-intuitive, please report that so we can improve | |
1311 | it. | |
62ae9557 NJ |
1312 | |
1313 | The implementation and options of the @code{<step-trap>} class are | |
1314 | complicated by the fact that it is unreliable to determine whether a | |
1315 | low level frame exit trap is applicable to a specified file by | |
1316 | examining the details of the reported frame. This is a consequence of | |
1317 | tail recursion, which has the effect that many frames can be removed | |
1318 | from the stack at once, with only the outermost frame being reported | |
1319 | by the low level trap call. The effects of this on the | |
1320 | @code{<step-trap>} class are such as to require the introduction of | |
1321 | the strange-looking @code{#:exit-depth} option, for the following | |
1322 | reasons. | |
1323 | ||
1324 | @itemize @bullet | |
1325 | @item | |
1326 | When stopped at the start of an application or evaluation frame, and | |
1327 | it is desired to continue execution until the next ``step'' in the same | |
1328 | source file, that next step could be the start of a nested application | |
1329 | or evaluation frame, or --- if the procedure definition is in a | |
1330 | different file, for example --- it could be the exit from the current | |
1331 | frame. | |
1332 | ||
1333 | @item | |
1334 | Because of the effects of tail recursion noted above, the current | |
1335 | frame exit possibility must be expressed as frame exit past a | |
1336 | specified stack depth. When an instance of the @code{<step-trap>} | |
1337 | class is installed from the context of an application or evaluation | |
1338 | frame entry, the @code{#:exit-depth} option should be used to specify | |
1339 | this stack depth. | |
1340 | ||
1341 | @item | |
1342 | When stopped at a frame exit, on the other hand, we know that the next | |
1343 | step must be an application or evaluation frame entry. In this | |
1344 | context the @code{#:exit-depth} option is not needed and should be | |
1345 | omitted or set to @code{#f}. | |
1346 | @end itemize | |
1347 | ||
1348 | @noindent | |
1349 | When a step trap is installed without @code{#:single-shot #t}, such | |
1350 | that it keeps firing, the @code{<step-trap>} code automatically | |
1351 | updates its idea of the @code{#:exit-depth} setting each time, so that | |
1352 | the trap always fires correctly for the following step. | |
1353 | ||
1354 | @deffn {Class} <step-trap> | |
1355 | Class for single-stepping traps. | |
1356 | @end deffn | |
1357 | ||
1358 | @deffn {Trap Option} #:file-name name | |
1359 | If not @code{#f}, this is a string containing the name of a source | |
1360 | file, and restricts the step trap to evaluation steps within that | |
1361 | source file. (Default value @code{#f}.) | |
1362 | @end deffn | |
1363 | ||
1364 | @deffn {Trap Option} #:exit-depth depth | |
1365 | If not @code{#f}, this is a positive integer implying that the next | |
1366 | step may be frame exit past the stack depth @var{depth}. See the | |
1367 | discussion above for more details. (Default value @code{#f}.) | |
1368 | @end deffn | |
1369 | ||
1370 | @noindent | |
1371 | Example: | |
1372 | ||
1373 | @lisp | |
1374 | (install-trap (make <step-trap> | |
1375 | #:file-name (frame-file-name | |
1376 | (stack-ref stack index)) | |
1377 | #:exit-depth (- (stack-length stack) | |
1378 | (stack-ref stack index)) | |
1379 | #:single-shot #t | |
1380 | #:behaviour debug-trap)) | |
1381 | @end lisp | |
1382 | ||
1383 | ||
1384 | @node Source Traps | |
1385 | @subsubsection Source Traps | |
1386 | ||
1387 | The @code{<source-trap>} class implements traps that are attached to a | |
1388 | precise source code expression, as read by the reader, and which fire | |
1389 | each time that that expression is evaluated. These traps use a low | |
1390 | level Guile feature which can mark individual expressions for | |
1391 | trapping, and are relatively efficient. But it can be tricky to get | |
1392 | at the source expression in the first place, and these traps are | |
1393 | liable to become irrelevant if the procedure containing the expression | |
1394 | is reevaluated; these issues are discussed further below. | |
1395 | ||
1396 | @deffn {Class} <source-trap> | |
1397 | Class for traps triggered by evaluation of a specific Scheme | |
1398 | expression. | |
1399 | @end deffn | |
1400 | ||
1401 | @deffn {Trap Option} #:expression expr | |
1402 | Specifies the Scheme expression to trap on. | |
1403 | @end deffn | |
1404 | ||
1405 | @noindent | |
1406 | Example: | |
1407 | ||
1408 | @lisp | |
1409 | (display "Enter an expression: ") | |
1410 | (let ((x (read))) | |
1411 | (install-trap (make <source-trap> | |
1412 | #:expression x | |
1413 | #:behaviour (list trace-trap | |
1414 | trace-at-exit))) | |
1415 | (primitive-eval x)) | |
1416 | @print{} | |
1417 | Enter an expression: (+ 1 2 3 4 5 6) | |
1418 | | 3: (+ 1 2 3 4 5 6) | |
1419 | | 3: =>21 | |
1420 | 21 | |
1421 | @end lisp | |
1422 | ||
1423 | The key point here is that the expression specified by the | |
1424 | @code{#:expression} option must be @emph{exactly} (i.e. @code{eq?} to) | |
1425 | what is going to be evaluated later. It doesn't work, for example, to | |
1426 | say @code{#:expression '(+ x 3)}, with the expectation that the trap | |
1427 | will fire whenever evaluating any expression @code{(+ x 3)}. | |
1428 | ||
1429 | The @code{trap-here} macro can be used in source code to create and | |
1430 | install a source trap correctly. Take for example the factorial | |
1431 | function defined in the @code{(ice-9 debugging example-fns)} module: | |
1432 | ||
1433 | @lisp | |
1434 | (define (fact1 n) | |
1435 | (if (= n 0) | |
1436 | 1 | |
1437 | (* n (fact1 (- n 1))))) | |
1438 | @end lisp | |
1439 | ||
1440 | @noindent | |
1441 | To set a source trap on a particular expression --- let's say the | |
1442 | expression @code{(= n 0)} --- edit the code so that the expression is | |
1443 | enclosed in a @code{trap-here} macro call like this: | |
1444 | ||
1445 | @lisp | |
1446 | (define (fact1 n) | |
1447 | (if (trap-here (= n 0) #:behaviour debug-trap) | |
1448 | 1 | |
1449 | (* n (fact1 (- n 1))))) | |
1450 | @end lisp | |
1451 | ||
1452 | @deffn {Macro} trap-here expression . trap-options | |
1453 | Install a source trap with options @var{trap-options} on | |
1454 | @var{expression}, then return with the whole call transformed to | |
1455 | @code{(begin @var{expression})}. | |
1456 | @end deffn | |
1457 | ||
1458 | Note that if the @code{trap-here} incantation is removed, and | |
1459 | @code{fact1} then redefined by reloading its source file, the effect | |
1460 | of the source trap is lost, because the text ``(= n 0)'' is read again | |
1461 | from scratch and becomes a new expression @code{(= n 0)} which does | |
1462 | not have the ``trap here'' mark on it. | |
1463 | ||
1464 | If the semantics and setting of source traps seem unwieldy, location | |
1465 | traps may meet your need more closely; these are described in the | |
1466 | following subsubsection. | |
1467 | ||
1468 | ||
1469 | @node Location Traps | |
1470 | @subsubsection Location Traps | |
1471 | ||
1472 | The @code{<location-trap>} class implements traps that are triggered | |
24dbb5ed NJ |
1473 | by evaluation of code at a specific source location. When compared |
1474 | with source traps, they are easier to set, and do not become | |
1475 | irrelevant when the relevant code is reloaded; but unfortunately they | |
1476 | are a lot less efficient, as they require running some ``are we in the | |
1477 | right place for a trap'' code on every low level frame entry trap | |
1478 | call. | |
62ae9557 NJ |
1479 | |
1480 | @deffn {Class} <location-trap> | |
1481 | Class for traps triggered by evaluation of code at a specific source | |
24dbb5ed | 1482 | location. |
62ae9557 NJ |
1483 | @end deffn |
1484 | ||
1485 | @deffn {Trap Option} #:file-regexp regexp | |
1486 | A regular expression specifying the filenames that will match this | |
1487 | trap. This option must be specified when creating a location trap. | |
1488 | @end deffn | |
1489 | ||
24dbb5ed NJ |
1490 | @deffn {Trap Option} #:line line |
1491 | The line number (0-based) of the source location at which the trap | |
1492 | should be triggered. This option must be specified when creating a | |
1493 | location trap. | |
62ae9557 NJ |
1494 | @end deffn |
1495 | ||
24dbb5ed NJ |
1496 | @deffn {Trap Option} #:column column |
1497 | The column number (0-based) of the source location at which the trap | |
1498 | should be triggered. This option must be specified when creating a | |
1499 | location trap. | |
62ae9557 NJ |
1500 | @end deffn |
1501 | ||
1502 | @noindent | |
24dbb5ed NJ |
1503 | Here is an example, which matches the @code{(facti (- n 1) (* a n))} |
1504 | expression in @file{ice-9/debugging/example-fns.scm}: | |
62ae9557 NJ |
1505 | |
1506 | @lisp | |
1507 | (install-trap (make <location-trap> | |
1508 | #:file-regexp "example-fns.scm" | |
24dbb5ed NJ |
1509 | #:line 11 |
1510 | #:column 6 | |
62ae9557 NJ |
1511 | #:behaviour gds-debug-trap)) |
1512 | @end lisp | |
1513 | ||
1514 | ||
1515 | @node Trap Shorthands | |
1516 | @subsubsection Trap Shorthands | |
1517 | ||
1518 | If the code described in the preceding subsubsections for creating and | |
1519 | manipulating traps seems a little long-winded, it is of course | |
1520 | possible to define more convenient shorthand forms for typical usage | |
24dbb5ed | 1521 | patterns. Here are some examples. |
62ae9557 NJ |
1522 | |
1523 | @lisp | |
1524 | (define (break! proc) | |
1525 | (install-trap (make <procedure-trap> | |
1526 | #:procedure proc | |
1527 | #:behaviour gds-debug-trap))) | |
1528 | ||
1529 | (define (trace! proc) | |
1530 | (install-trap (make <procedure-trap> | |
1531 | #:procedure proc | |
1532 | #:behaviour (list trace-trap | |
1533 | trace-at-exit)))) | |
1534 | ||
1535 | (define (trace-subtree! proc) | |
1536 | (install-trap (make <procedure-trap> | |
1537 | #:procedure proc | |
1538 | #:behaviour (list trace-trap | |
1539 | trace-until-exit)))) | |
1540 | @end lisp | |
1541 | ||
24dbb5ed NJ |
1542 | Definitions like these are not provided out-of-the-box by Guile, |
1543 | because different users will have different ideas about what their | |
1544 | default debugger should be, or, for example, which of the common trap | |
1545 | options (@pxref{Common Trap Options}) it might be useful to expose | |
1546 | through such shorthand procedures. | |
62ae9557 NJ |
1547 | |
1548 | ||
1549 | @node Trap Utilities | |
1550 | @subsubsection Trap Utilities | |
1551 | ||
1552 | @code{list-traps} can be used to print a description of all known trap | |
1553 | objects. This uses a weak value hash table, keyed by a trap index | |
1554 | number. Each trap object has its index number assigned, and is added | |
1555 | to the hash table, when it is created by a @code{make @var{trap-class} | |
1556 | @dots{}} call. When a trap object is GC'd, it is automatically | |
1557 | removed from the hash table, and so no longer appears in the output | |
1558 | from @code{list-traps}. | |
1559 | ||
1560 | @deffn {Variable} all-traps | |
1561 | Weak value hash table containing all known trap objects. | |
1562 | @end deffn | |
1563 | ||
1564 | @deffn {Procedure} list-traps | |
1565 | Print a description of all known trap objects. | |
1566 | @end deffn | |
1567 | ||
1568 | The following example shows a single trap that traces applications of | |
1569 | the procedure @code{facti}. | |
1570 | ||
1571 | @lisp | |
1572 | guile> (list-traps) | |
1573 | #<<procedure-trap> 100d2e30> is an instance of class <procedure-trap> | |
1574 | Slots are: | |
1575 | number = 1 | |
1576 | installed = #t | |
1577 | condition = #f | |
1578 | skip-count = 0 | |
1579 | single-shot = #f | |
1580 | behaviour = (#<procedure trace-trap (trap-context)>) | |
1581 | repeat-identical-behaviour = #f | |
1582 | procedure = #<procedure facti (n a)> | |
1583 | @end lisp | |
1584 | ||
1585 | When @code{all-traps} or @code{list-traps} reveals a trap that you | |
1586 | want to modify but no longer have a reference to, you can retrieve the | |
1587 | trap object by calling @code{get-trap} with the trap's number. For | |
1588 | example, here's how you could change the behaviour of the trap listed | |
1589 | just above. | |
1590 | ||
1591 | @lisp | |
1592 | (slot-set! (get-trap 1) 'behaviour (list debug-trap)) | |
1593 | @end lisp | |
1594 | ||
1595 | @deffn {Procedure} get-trap number | |
1596 | Return the trap object with the specified @var{number}, or @code{#f} | |
1597 | if there isn't one. | |
1598 | @end deffn | |
1599 | ||
1600 | ||
24dbb5ed NJ |
1601 | @node Debugging Examples |
1602 | @subsection Debugging Examples | |
1603 | ||
1604 | Here we present some examples of what you can do with the debugging | |
1605 | facilities just described. | |
1606 | ||
1607 | @menu | |
1608 | * Single Stepping through a Procedure's Code:: | |
1609 | * Profiling or Tracing a Procedure's Code:: | |
1610 | @end menu | |
1611 | ||
1612 | ||
1613 | @node Single Stepping through a Procedure's Code | |
1614 | @subsubsection Single Stepping through a Procedure's Code | |
1615 | ||
1616 | A good way to explore in detail what a Scheme procedure does is to set | |
1617 | a trap on it and then single step through what it does. To do this, | |
1618 | make and install a @code{<procedure-trap>} with the @code{debug-trap} | |
ba5f8bf4 | 1619 | behaviour from @code{(ice-9 debugger)}. |
24dbb5ed NJ |
1620 | |
1621 | The following sample session illustrates this. It assumes that the | |
1622 | file @file{matrix.scm} defines a procedure @code{mkmatrix}, which is | |
1623 | the one we want to explore, and another procedure @code{do-main} which | |
1624 | calls @code{mkmatrix}. | |
1625 | ||
1626 | @lisp | |
1627 | $ /usr/bin/guile -q | |
1628 | guile> (use-modules (ice-9 debugger) | |
24dbb5ed NJ |
1629 | (ice-9 debugging traps)) |
1630 | guile> (load "matrix.scm") | |
1631 | guile> (install-trap (make <procedure-trap> | |
1632 | #:procedure mkmatrix | |
1633 | #:behaviour debug-trap)) | |
1634 | guile> (do-main 4) | |
1635 | This is the Guile debugger -- for help, type `help'. | |
1636 | There are 3 frames on the stack. | |
1637 | ||
1638 | Frame 2 at matrix.scm:8:3 | |
1639 | [mkmatrix] | |
1640 | debug> next | |
1641 | Frame 3 at matrix.scm:4:3 | |
45867c2a | 1642 | (let ((x 1)) (quote hi!)) |
24dbb5ed NJ |
1643 | debug> info frame |
1644 | Stack frame: 3 | |
1645 | This frame is an evaluation. | |
1646 | The expression being evaluated is: | |
1647 | matrix.scm:4:3: | |
45867c2a | 1648 | (let ((x 1)) (quote hi!)) |
24dbb5ed NJ |
1649 | debug> next |
1650 | Frame 3 at matrix.scm:5:21 | |
45867c2a | 1651 | (quote hi!) |
24dbb5ed NJ |
1652 | debug> bt |
1653 | In unknown file: | |
1654 | ?: 0* [primitive-eval (do-main 4)] | |
1655 | In standard input: | |
1656 | 4: 1* [do-main 4] | |
1657 | In matrix.scm: | |
1658 | 8: 2 [mkmatrix] | |
1659 | ... | |
45867c2a | 1660 | 5: 3 (quote hi!) |
24dbb5ed | 1661 | debug> quit |
45867c2a | 1662 | hi! |
24dbb5ed NJ |
1663 | guile> |
1664 | @end lisp | |
1665 | ||
1666 | Or you can use Guile's Emacs interface (GDS), by using the module | |
1667 | @code{(ice-9 gds-client)} instead of @code{(ice-9 debugger)} and | |
ba5f8bf4 NJ |
1668 | changing @code{debug-trap} to @code{gds-debug-trap}. Then the stack and |
1669 | corresponding source locations are displayed in Emacs instead of on the | |
1670 | Guile command line. | |
24dbb5ed NJ |
1671 | |
1672 | ||
1673 | @node Profiling or Tracing a Procedure's Code | |
1674 | @subsubsection Profiling or Tracing a Procedure's Code | |
1675 | ||
1676 | What if you wanted to get a trace of everything that the Guile | |
1677 | evaluator does within a given procedure, but without Guile stopping | |
1678 | and waiting for your input at every step? For this requirement you | |
1679 | can install a trap on the procedure, as in the previous example, but | |
1680 | instead of @code{debug-trap} or @code{gds-debug-trap}, use the | |
1681 | @code{trace-trap} and @code{trace-until-exit} behaviours provided by | |
1682 | the @code{(ice-9 debugging trace)} module. | |
1683 | ||
1684 | @lisp | |
1685 | guile> (use-modules (ice-9 debugging traps) (ice-9 debugging trace)) | |
1686 | guile> (load "matrix.scm") | |
1687 | guile> (install-trap (make <procedure-trap> | |
1688 | #:procedure mkmatrix | |
1689 | #:behaviour (list trace-trap trace-until-exit))) | |
1690 | guile> (do-main 4) | |
1691 | | 2: [mkmatrix] | |
1692 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> define #f] | |
1693 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> define #f] | |
1694 | | 4: (and (memq sym bindings) (let ...)) | |
1695 | | 5: (memq sym bindings) | |
1696 | | 5: [memq define (debug)] | |
1697 | | 5: =>#f | |
1698 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> define #f] | |
1699 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> define #f] | |
1700 | | 4: (and (memq sym bindings) (let ...)) | |
1701 | | 5: (memq sym bindings) | |
1702 | | 5: [memq define (debug)] | |
1703 | | 5: =>#f | |
1704 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1705 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1706 | | 4: (and (memq sym bindings) (let ...)) | |
1707 | | 5: (memq sym bindings) | |
1708 | | 5: [memq let (debug)] | |
1709 | | 5: =>#f | |
1710 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1711 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1712 | | 4: (and (memq sym bindings) (let ...)) | |
1713 | | 5: (memq sym bindings) | |
1714 | | 5: [memq let (debug)] | |
1715 | | 5: =>#f | |
1716 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1717 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1718 | | 4: (and (memq sym bindings) (let ...)) | |
1719 | | 5: (memq sym bindings) | |
1720 | | 5: [memq let (debug)] | |
1721 | | 5: =>#f | |
45867c2a | 1722 | | 2: (letrec ((yy 23)) (let ((x 1)) (quote hi!))) |
24dbb5ed NJ |
1723 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] |
1724 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1725 | | 4: (and (memq sym bindings) (let ...)) | |
1726 | | 5: (memq sym bindings) | |
1727 | | 5: [memq let (debug)] | |
1728 | | 5: =>#f | |
1729 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1730 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1731 | | 4: (and (memq sym bindings) (let ...)) | |
1732 | | 5: (memq sym bindings) | |
1733 | | 5: [memq let (debug)] | |
1734 | | 5: =>#f | |
1735 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1736 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1737 | | 4: (and (memq sym bindings) (let ...)) | |
1738 | | 5: (memq sym bindings) | |
1739 | | 5: [memq let (debug)] | |
1740 | | 5: =>#f | |
45867c2a | 1741 | | 2: (let ((x 1)) (quote hi!)) |
24dbb5ed NJ |
1742 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] |
1743 | | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | |
1744 | | 4: (and (memq sym bindings) (let ...)) | |
1745 | | 5: (memq sym bindings) | |
1746 | | 5: [memq let (debug)] | |
1747 | | 5: =>#f | |
1748 | | 2: [let (let # #) (# # #)] | |
1749 | | 2: [let (let # #) (# # #)] | |
45867c2a NJ |
1750 | | 2: =>(#@@let* (x 1) #@@let (quote hi!)) |
1751 | hi! | |
24dbb5ed NJ |
1752 | guile> (do-main 4) |
1753 | | 2: [mkmatrix] | |
45867c2a NJ |
1754 | | 2: (letrec ((yy 23)) (let* ((x 1)) (quote hi!))) |
1755 | | 2: (let* ((x 1)) (quote hi!)) | |
1756 | | 2: (quote hi!) | |
1757 | | 2: =>hi! | |
1758 | hi! | |
24dbb5ed NJ |
1759 | guile> |
1760 | @end lisp | |
1761 | ||
1762 | This example shows the default configuration for how each line of trace | |
1763 | output is formatted, which is: | |
1764 | ||
1765 | @itemize | |
1766 | @item | |
1767 | the character @code{|}, a visual clue that the line is a line of trace | |
1768 | output, followed by | |
1769 | ||
1770 | @item | |
1771 | a number indicating the real evaluator stack depth (where ``real'' means | |
1772 | not counting tail-calls), followed by | |
1773 | ||
1774 | @item | |
1775 | a summary of the expression being evaluated (@code{(@dots{})}), the | |
1776 | procedure being called (@code{[@dots{}]}), or the value being returned | |
1777 | from an evaluation or procedure call (@code{=>@dots{}}). | |
1778 | @end itemize | |
1779 | ||
1780 | @noindent | |
1781 | You can customize @code{(ice-9 debugging trace)} to show different | |
1782 | information in each trace line using the @code{set-trace-layout} | |
1783 | procedure. The next example shows how to get the source location in | |
1784 | each trace line instead of the stack depth. | |
1785 | ||
1786 | @lisp | |
1787 | guile> (set-trace-layout "|~16@@a: ~a\n" trace/source trace/info) | |
1788 | guile> (do-main 4) | |
1789 | | matrix.scm:7:2: [mkmatrix] | |
45867c2a NJ |
1790 | | : (letrec ((yy 23)) (let* ((x 1)) (quote hi!))) |
1791 | | matrix.scm:3:2: (let* ((x 1)) (quote hi!)) | |
1792 | | matrix.scm:4:4: (quote hi!) | |
1793 | | matrix.scm:4:4: =>hi! | |
1794 | hi! | |
24dbb5ed NJ |
1795 | guile> |
1796 | @end lisp | |
1797 | ||
07d83abe MV |
1798 | @c Local Variables: |
1799 | @c TeX-master: "guile.texi" | |
1800 | @c End: |