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) |
(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
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
Other useful commands for debugging include: break, trace, untrace and step. Consult your favorite Lisp manual for information about using these functions.