Debugging in Chez Scheme This is a quick description of some of the debugging facilities in Chez Scheme. Thanks to Richard Kelsey for writing Part 1. **************************************************************** Part 1: The first things to try... If an error occurs, you will see a message like this one: Error: variable make-tkoen is not bound. Type (debug) to enter the debugger. > At this point, (DEBUG) will enter the debugger. Some errors may automatically drop you into the debugger; I'm not sure just which ones. Once in the debugger, enter ? to get a list of possible debugger commands. The most useful ones are e to exit and i (inspect) to inspect the return stack. A sample inspector session may be found below. There are several ways to get information from a running program. One is to trace procedures. > (define fact ; recursive factorial (lambda (n) (if (<= n 1) 1 (* n (fact (- n 1)))))) > (fact 3) ; (fact 3) = 6 6 > (trace fact) ; start tracing the procedure fact (fact) > (fact 3) (fact 3) ; printed by the tracer | (fact 2) ; indenting shows recursive depth | | (fact 1) | | 1 ; results are also printed | 2 6 ; final result printed by tracer 6 ; final result printed when returned > (untrace fact) ; stop tracing fact (fact) > LAMBDA can be replaced by TRACE-LAMBDA. This is useful for LAMBDA's that are internal to other procedures. > (define fact (trace-lambda fact2 (n) ; fact2 is what the tracer will print out (if (<= n 1) 1 (* n (fact (- n 1)))))) > (fact 3) (fact2 3) ; same as before. | (fact2 2) | | (fact2 1) | | 1 | 2 6 6 > Finally, you can always print out your own debugging information. This is useful when procedures take large arguments. For example, many of the procedures in the scanner take an automaton as an argument, and tracing them results in the automaton being printed out on every call. Use printf to print debugging information. printf is much like printf in C, except that it uses ~ instead of %. > (define ifact (lambda (n r) (printf "ifact: n = ~S r = ~S~%" n r) (if (<= n 1) r (ifact (- n 1) (* n r))))) > (ifact 3 1) ifact: n = 3 r = 1 ifact: n = 2 r = 3 ifact: n = 1 r = 6 6 > Here are some of the format directives: ~S prints the argument ~D displays the argument (strings are printed without quotation marks) ~% prints a newline See the Dybvig book for more details. **************************************************************** Part 2: Using the debugger and inspector. I don't use the debugger much-- I prefer to use the facilities above. But some people may like stack-based debuggers. Here's a transcript of a sample session with the debugger. The debugger itself doesn't do much-- mostly it's used as a gateway to the inspector. The inspector will let you look at the stack and give you at least a rough idea of where you were when things broke. My comments on the transcript are in <<....>> brackets. Chez Scheme Version 4.1 Copyright (c) 1991 Cadence Research Systems > (define fact (lambda (n) (if (<= n 1) (/ n 0) <> (* n (fact (- n 1)))))) > (fact 3) Error in /: undefined for 0. Type (debug) to enter the debugger. > (debug) debug> ? Type e to exit interrupt handler and continue <> r to reset scheme a to abort scheme <> n to enter new cafe i to inspect current continuation s to display statistics <> debug> i # : sf 0: # 1: # 2: # 3: # 4: # # : s <> continuation: # free variables: 0: (0) 1: "undefined for ~s" 2: / 3: # <> # : d # : s continuation: # free variables: 0: 0 1: 1 2: / 3: # <> # : d # : s continuation: # procedure code: (lambda (n) (if (<= n 1) (/ n 0) (* n (fact (...))))) call code: (fact (- n 1)) free variables: 0. n: 2 <> # : d # : s continuation: # procedure code: (lambda (n) (if (<= n 1) (/ n 0) (* n (fact (...))))) call code: (fact (- n 1)) free variables: 0. n: 3 # : d # : q <> debug> r > **************** Now, what did all that mean? The inspector allows you to inspect an object (initially the continuation (stack frame) where the error occurred. Typing "?" gives you commands pertinent to the kind of object you're looking at. 1. For a continuation (stack frame), the choices include: show(s) ............. show code and free variables ref(r) .............. inspect [nth] frame element down(d) ............. inspect [nth] next frame call ................ inspect the expanded code for the pending call code(c) ............. inspect the expanded code for the pending procedure show-frames(sf) ..... show the next [n] frames So "d" enables you to explore the continuation of the current frame, "r0" inspects the 0-th variable, etc. When you are done looking at an object, "u" [up] gets you back to the preceding object. "sf" shows you a summary of the entire continuation stack (starting at the current continuation). Typical printout might be: # : sf 0: # 1: # 2: # 3: # 4: # 5: # You can then say "d4" to look at frame #4, and go "d" and "u" the stack from there. 2. Looking at a list structure, the commands are: print(p) ............ pretty-print object <> car ................. inspect car of pair cdr ................. inspect cdr of pair ref(r) .............. inspect [nth] car tail ................ inspect [nth] cdr show(s) ............. show [n] elements of list length(l) ........... display list length 3. For closures (procedures), the commands are: show(s) ............. show code and free variables code(c) ............. inspect the expanded code for the procedure ref(r) .............. inspect [nth] free variable length(l) ........... display number of free variables 4. There may be other inspector modes, for other data types, that I haven't found yet. 5. In addition to these object-specific commands, there are general navigation commands, which you can list with the command "??". These are: up(u) ............... return to [nth] previous level top(t) .............. return to initial object forward(f) .......... move to [nth] next expression back(b) ............. move to [nth] previous expression => .................. send object to procedure mark(m) ............. mark location [with symbolic mark] goto(g) ............. go to marked location [mark] new-cafe(n) ......... enter a new cafe quit(q) ............. exit inspector help(h) ............. help Happy hacking!