next up previous
Next: About this document ...

A Minimal Guide to Using the ACL Debugger

Daniel M. Gaines

The debugger is an extremely useful tool when developing code. The Lisp debugger is automatically started whenever Lisp encounters an error in your code or you can invoke the debugger by inserting break statements in your code.

When you are in the debugger, a number in brackets will appear before the normal Lisp prompt. This number indicates what error level you are it. For example, if you make an error at the top level you get a debugger at level 1:
USER(1): (car 2)
Error: Attempt to take the car of 5 which is not listp.
[condition type: SIMPLE-ERROR]
[1] USER(2):

If you make an error here, you are at error level 2:
[1] USER(2): (/ 2 0)
Error: Attempt to divide 2 by zero.
[condition type: DIVISION-BY-ZERO]
[2] USER(3):

When you are sitting at the debugger prompt, you are essentially in the Lisp read-eval-print loop. So you can evaluate expressions like:
[2] USER(3): (+ 1 2)
3

You can also issue commands to the debugger. Debugger commands begin with a colon (:). You can get help using :help
[3] USER(4): :help

COMMAND   ABBR DESCRIPTION
aliases   ali  print all command aliases
args      arg  save arguments before calls
arrest    arr  arrest a process for debugging
boe            Mark frame to break when exitted.
bottom    bo   Zoom at the oldest frame on the stack.
bt             Zoom in a very brief manner.
cd             change into another directory
cf             compile a file
cload     cl   compile and load a file
continue  cont continue from a continuable error
current   cur  return the expression given by the current stack frame
dirs      di   print the Allegro directory stack
dn             move down the stack `n' frames, default 1
edit      ed   edit the source for the current stack frame
EOF            either :pop or :exit
error     err  print the last error message
evalmode  eval examine or set evaluation mode
exit      ex   exit and return to the shell
find      fin  find the stack frame calling the function `func'
focus     fo   focus the top level on a process
frame     fr   print info about current frame
function  fun  print and set * to the function object of this frame
help      he   print this text -- use `:help cmd-name' for more info
hide      hid  hide functions or types of stack frames
history   his  print the most recently typed user inputs
inspect   i    inspect a lisp object
kill      ki   kill a process
ld             load one or more files
local     loc  print the value of a local (interpreted or compiled) variable
macroexpand ma call macroexpand on the argument, and pretty print it
optimize  opt  interactively set compiler optimizations
package   pa   go into a package
pop            pop up `n' (default 1) break levels
popd           cd into the previous entry on directory stack
printer-variables pri Interactively set printer control variables
processes pro  List all processes
prt            pop-and-retry the last expression which caused an error
pushd     pu   cd to a directory, pushing the directory on to the stack
pwd       pw   print the process current working directory
reset     res  return to the top-most break level
restart   rest restart the function in the current frame
return    ret  return values from the current frame
scont     sc   step `n' forms before stopping
set-local set-l  set the value of a local variable
sover     so   eval the current step form, with stepping turned off
step      st   turn on or off stepping
top       to   Zoom at the newest frame on the stack.
trace     tr   trace the function arguments
unarrest  unar revoke the debugging arrest reason on a process
unhide    unh  unhide functions or types of stack frames
untrace   untr stop tracing some or all functions
up             move up `n' (default 1) stack frames
who-binds who-b find bindings of a variable
who-calls who-c find callers of a function
who-references who-r find references to a variable
who-sets  who-s find setters of a variable
who-uses  who-u find references, bindings and settings of a variable
zoom      zo   print the runtime stack

To get additional help on a command use :help command-name
[3] USER(5): :help :zo

    Zoom prints a portion of the evaluation stack, and takes the following
keyword arguments:

:top      start at the newest frame
:bottom   start at the oldest frame
:brief    print just the frame's name. This option sticks.
:moderate print the frame's name and arguments (the default).  This option
          sticks.
:verbose  print lots of info about a frame.  This option sticks.
:specials this is used to set (not bind) the variable
          top-level:*zoom-print-special-bindings* before doing the :zoom.
          This option sticks.
:count    print this many frames (default = 7). This option sticks.
:all      print all frames (regardless of :hide and :unhide).  This option
          sticks.
:function print frames so that the function object is given rather than
          its name.  This option sticks.
:relative print the relative offsets of each frame. This option sticks.
Some of the commands that you will probably use most often include:

:zo prints a runtime stack trace
:up move up a frame in the runtime stack
:dn move down a frame in the runtime stack
:pop pop out of an error level
:loc list variables local to the current stack frame and their bindings
:eval set the evaluation mode (see below)
To get out of the debugger, you can use :pop to pop back to the previous error level. Popping out of the first error level will return you back to the normal Lisp read-eval-print loop. As I said above, you can ask Lisp to evaluation expressions just as if you were in its normal read-eval-print loop. It is important to note that Lisp uses the toplevel environment as the environment in which it evaluates your expressions. For example, let's say we've defined this buggy factorial function at the toplevel:

(defun fact (n)
  (if (/ n 0)
      1
      (* n (fact (- n 1)))))

And then we attempt to compute factorial of 3:
USER(6): (fact 3)
Error: Attempt to divide 3 by zero.
[condition type: DIVISION-BY-ZERO]
[1] USER(7):

At this point, if we try to ask Lisp the value of n we get an error because n is not defined in the toplevel environment:
[1] USER(7): n
Error: Attempt to take the value of the unbound variable `N'.
[condition type: UNBOUND-VARIABLE]

Restart actions (select using :continue):
0: Try evaluating N again.
1: Set the symbol-value of N and use its value.
2: Use a value without setting N.

So pop out of this error:
[2] USER(8): :pop
Previous error: Attempt to divide 3 by zero.
[1] USER(9):

If you want to have Lisp use stack frame that you are currently in as the environment, you need to set the context of evalmode to something other than nil (see :help :eval):
[1] USER(9): :eval :context T
[1] USER(10): n
3
[1] USER(11):

This lets you move about the runtime stack evaluating expressions in the corresponding environments. For example, let's say we have defined the following functions in the toplevel environment:

(defun f (x)
  (g 7))
(defun g (y)
  (h 4))
(defun h (x)
  (break))

The break statement will force us into an error level so we can inspect the state of computation:
USER(12): (f 3)
Break: call to the `break' function.

Restart actions (select using :continue):
0: return from break.

[1c] USER(13): :zo

Evaluation stack:

   (BREAK)
 ->(H 4)
   (G 7)
   (F 3)
   (EVAL (F 3))
   (TPL:TOP-LEVEL-READ-EVAL-PRINT-LOOP)
   (TPL:START-INTERACTIVE-TOP-LEVEL
      #<BIDIRECTIONAL-TERMINAL-STREAM [initial terminal io] fd 0/1 @ #xd81a2>
      #<Function TOP-LEVEL-READ-EVAL-PRINT-LOOP> ...)
[1c] USER(14): :eval :context T
[1c] USER(15): x
4
[1c] USER(16): :dn
\begin{verbatim}Evaluation stack:
\par (BREAK)
(H 4)
->(G 7)
(F 3)
(EVAL (F ...
...d 0/1 @  ...
[1c] USER(221): y
7
[1c] USER(222): :dn
Evaluation stack:

   (BREAK)
   (H 4)
   (G 7)
 ->(F 3)
   (EVAL (F 3))
   (TPL:TOP-LEVEL-READ-EVAL-PRINT-LOOP)
   (TPL:START-INTERACTIVE-TOP-LEVEL
      #<BIDIRECTIONAL-TERMINAL-STREAM [initial terminal io] fd 0/1 @ #xd81a2>
      #<Function TOP-LEVEL-READ-EVAL-PRINT-LOOP> ...)
[1c] USER(223): x
3

Other useful commands for debugging include: break, trace, untrace and step. Consult your favorite Lisp manual for information about using these functions.



 
next up previous
Next: About this document ...
Daniel M. Gaines
1998-08-24