This minitutorial discusses several topics:

Dropping into the Debugger

Every Lisp Environment comes with a debugger builtin. Given the fact that all environments have the capability to function as "dumb" interpreter ( i.e. do not incrementally compile functions on-the-fly ), this really isn't surprising. Most Lisp "Hackers" like environments that allow them to develop code incrementally with maximum opportunity to "explore".

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.

Dropping into the Debugger on purpose...

You can drop into the debugger on purpose if you wish. Now why would you want to do that? Don't you remember debugging with breakpoints with your favorite procedural debugger ( e.g. gdb or dbx on a Unix box )? Sometimes you would like to see how your function is behaving at a certain point in time.
        > (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.
Which will drop you back into the debugger since the invocation on that condition is remiss. You'll stay at "break level" one since you are purposely invoking break. [ Don't abort and go on to next section. ]

Stack Backtrace

Sometimes you land in the debugger and you have NO idea how or why you got there. At this time invoke a Stack Backtrace. You can do this by typing ':b' . This will show all the frames back to the Lisp Top Level. If you just want to see the frames back to where a particular function (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).

What else can I do?

You can go on to the minitutorial on stepping and tracing.
Placing (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.
Back to LCL Tool Time

Last modified: by Lyman S. Taylor(lyman@cc.gatech.edu)
(c) copyright Lyman S. Taylor 1995, All rights reserved