By now I'm sure all of you have manage to drop into the LCL debugger. You can do something as simple as:
> car
>>>Error: The symbol CAR has no global value
SYMBOL-VALUE:
Required arg 0 (S): CAR
:C 0: Try evaluating CAR again
:A 1: Abort to Lisp Top Level
->
Note that the Listener's cursor has changed from being '>' to '->' .
This means that you have entered the debugger and are at "break level" one.
If you where to type car again you would end up at "break level" two, '-->'.
2 > :a
Meaning, if you were to enter ':a' at this point you would drop back
to level one.
It is not uncommon to wander the lab and see people at "break level" 23 or some such. This isn't really a good idea since there is a bunch of stuff on the "Stack" waiting for you to resolve the breaks. Unfortunately, ( or not depending on your point of view) you can type in anything at the break prompt that you could type in at the '>' prompt.
LCL's debugger has numerous commands. To get a short listing of the possible commands type ':h' which will produce the following list:
<N> Invoke debugger option:A Abort to most recent Abort Restart. :A :T Abort to earliest recent Abort Restart (usually Top Level). :C Continue, invoking most recent Continue Restart. :N Go down one frame (towards the caller). :N k Go down k frames. :P Go up one frame. :P k Go up k frames. :> Go to the bottom of the stack (towards Lisp Top Level). :< Go to the top of the stack. :B Backtrace to the bottom of the stack. :D Display current frame and show options. :V Verbosely display current frame, showing up to 32 local variables. :L k Print local variable numbered k and set * to its value. :F Retry execution of the current frame. :R Return a value to the caller of the current frame. Expressions that are not debugger commands will be evaluated and printed. For additional help on the full set of debugger commands use :??.
Typing :?? will produce a much longer list. I'm not even going to touch the commands displayed on that list. Actually I'm only going to explain a few commands on the short list.
The first item on this short list says that you can choose any item on the list of options the debugger gives you by just typing that number at the debugger prompt. For example
SYMBOL-VALUE:
Required arg 0 (S): BAR
:C 0: Try evaluating BAR again
:A 1: Abort to Debugger Level 2
2: Try evaluating FOO again
3: Abort to Debugger Level 1
4: Try evaluating CAR again
5: Abort to Lisp Top Level
->->->
Here I've managed to drop three levels deep into the debugger. If I wished
to jump back up to Level 1 , I need only enter a 3 at the prompt. Entering
':a :t' always jumps to back to Lisp Top Level.
> (defun debug-me ( int num-times result )
(declare ( notinline debug-me ) )
(cond ((= num-times 0 ) result )
((= num-times 2 ) (break "Help this doesn't work" )
(debug-me int num-times ( + int result)))
( t (debug-me int (- num-times 1 ) (+ int result ) ) ) ) )
If you now invoke (debug-me 3 5 0 ) the function will run until
num-times is equal to 2 and then drop into the debugger. The message
that you pass to break is optional [ break takes an optional format string
and args for the format string if any ].
At this point you can enter ':c" to continue evaluation.
eval for example)got called the type ':b eval'.
The command ':d' will display the
same message you got when you dropped into the debugger at the current
frame.
You can look at the local variable bindings by typing the following( colon L ):
-> :n ; move up the stack from the break.
-> :l num-times
2
-> :l 1 ; the second arg to this function. nums start at
; zero.
You could temporarly fix this by calling
-> :s num-times 1
or equivalently
-> (setf num-times 1 ) ; but we're not suppose to use setf. :-)
and then typing
-> :c
At which point the functions exits "normally". If you reinvoke that
function again and call up the stack backtrace you can examine
the previous invocations. You can go up to the top of the stack by typing
':p' and back down ( towards the initial caller ) by typing ':n'. If you are
looking at the stack backtrace just think of the emacs and 'p' to go to
previous ( up ) and 'n' to go to next (down).
(break) in your code can be a pain since your have to re-evaluate
the function to great the compiler to remove the "breakpoint". However,
this recompilation process is quite fast. Or you can try to use the
trace facility more effectively. See the trace minitutorial for more
info.