25.1. Top Level Loop [sec_25-1-1]

25.1.1. User-defined Commands

The debugger may be invoked through the functions INVOKE-DEBUGGER, BREAK, SIGNAL, ERROR, CERROR, WARN. The stepper is invoked through the macro STEP. Debugger and stepper execute subordinate read-eval-print loop (called break loops) which are similar to the main read-eval-print loop except for the prompt and the set of available commands. Commands must be typed literally, in any case, without surrounding quotes or whitespace. Each command has a keyword abbreviation, indicated in the second column.

Table 25.1. Commands common to the main loop, the debugger and the stepper

commandabbreviationoperation
help:hprint a list of available commands
LocalSymbols:lsprint the list of SYMBOLs INTERNed in a given PACKAGE.

Table 25.2. Commands common to the debugger and the stepper

commandabbreviationoperation
Abort:aabort to the next most recent read-eval-print loop
Unwind:uwabort to the next most recent read-eval-print loop
Quit:qquit to the top read-eval-print loop

The stack is organized into frames and other stack elements. Usually every invocation of an interpreted function and every evaluation of an interpreted form corresponds to one stack frame. Special forms such as LET, LET*, UNWIND-PROTECT and CATCH produce special kinds of stack frames.

In a break loop there is a current stack frame, which is initially the most recent stack frame but can be moved using the debugger commands Up and Down.

Evaluation of forms in a break loop occurs in the lexical environment of the current stack frame and at the same time in the dynamic environment of the debugger's caller. This means that to inspect or modify a lexical variable all you have to do is to move the current stack frame to be just below the frame that corresponds to the form or the function call that binds that variable.

Stack Printing Mode. There is a current stack mode which defines in how much detail the stack is shown by the stack-related debugger commands (backtrace et al):

  1. All the stack elements are considered. This mode works fine for debugging compiled functions.
  2. All the frames are considered.
  3. Only lexical frames (frames that correspond to special forms that modify the lexical environment) are considered.
  4. Only EVAL and APPLY frames are considered. Every evaluation of a form in the interpreter corresponds to an EVAL frame. This is the default.
  5. Only APPLY frames are considered. Every invocation of an interpreted function corresponds to one APPLY frame.

Table 25.3. Commands common to the debugger and the stepper

commandabbreviationoperation
Error:eprint the last error object.
Inspect:iINSPECT the last error object.
Where:wshow the current stack frame.
Up:ugo up one frame, i.e., to the caller if in mode-5
Down:ddo down one frame, i.e., to the callee if in mode-5
Top:tgo to top frame, i.e., to the top-level form if in mode-4
Bottom:bgo to bottom (most recent) frame, i.e., most probably to the form or function that caused the debugger to be entered.
Mode stack-mode:m stack-modeset the current stack printing mode
Frame-limit l:flset the frame-limit: this many frames will be printed by backtrace at most.
backtrace [stack-mode [l]]:bt [stack-mode [l]]list the stack in the given stack-mode, bottom frame first, top frame last; at most l frames are printed; calls EXT:SHOW-STACK.

If the current stack frame is an EVAL or APPLY frame, the following commands are available as well:

Table 25.4. Commands specific to EVAL/APPLY

commandabbreviationoperation
Break+:br+set a breakpoint in the current frame. When the corresponding form or function will be left, the debugger will be entered again, with the variable EXT:*TRACE-VALUES* containing a list of its values.
Break-:br-remove a breakpoint from the current frame.
Redo:rdre-evaluate the corresponding form or function call. This command can be used to restart parts of a computation without aborting it entirely.
Return value:rt valueleave the current frame, returning the given value.

Table 25.5. Commands specific to the debugger

commandabbreviationoperation
Continue:ccontinue evaluation of the program.

Table 25.6. Commands specific to the stepper

commandabbreviationoperation
Step:sstep into a form: evaluate this form in single step mode
Next:nstep over a form: evaluate this form at once
Over:ostep over this level: evaluate at once up to the next return
Continue:cswitch off single step mode, continue evaluation

The stepper is usually used like this: If some form returns a strange value or results in an error, call (STEP form) and navigate using the commands Step and Next until you reach the form you regard as responsible. If you are too fast (execute Next once and get the error), there is no way back; you have to restart the entire stepper session. If you are too slow (stepped into a function or a form which certainly is OK), a couple of Next commands or one Over command will help.

25.1.1. User-defined Commands

You can set CUSTOM:*USER-COMMANDS* to a list of FUNCTIONs, each returning a LIST of bindings, i.e., either a

STRING
the help string printed by help in addition to the standard CLISP help
CONS (STRING . FUNCTION)
the actual binding: when the user types the string, the function is called on the remainder of the string, i.e., the part of the string after the command.

E.g.,

(setq CUSTOM:*USER-COMMANDS*
      (list (lambda () (list (format nil "~2%User-defined commands:")))
            (lambda ()
              (flet ((panic (argline)
                       (format t "don't panic~@[ because of ~A~], ~D~%"
                               (and (plusp (length argline)) argline)
                               (random 42))))
                (list (format nil "~%panic   :p    hit the panic button!")
                      (cons "panic" #'panic)
                      (cons ":p" #'panic))))
            (lambda ()
              (let ((curses #("ouch" "yuk" "bletch")))
                (flet ((swear (argline)
                         (format t "~A: ~A!~%" argline
                                 (aref curses (random (length curses))))))
                  (list (format nil "~%swear   :e    curse")
                        (cons "swear" #'swear)
                        (cons ":e" #'swear)))))))

These notes document CLISP version 2.49.93+Last modified: 2018-02-19