4

I'm using CCL on Mac (1.8.1 -- the latest available at this writing), and wondering if there's any sort of debugging tutorial available.

The thing I'm particularly interested in is setting a breakpoint somewhere in my code, then poking & prodding various values, then stepping over the next line of code, checking more values, etc.

EDIT: I've read the debugging section of the CCL manual (18.3 and thereabouts), but can't quite make sense of it. I'm coming from a C/Java/etc. background and IDE-based source level debuggers, with just a little exposure to gdb.

So I guess what I'm looking for is an introduction/tutorial that walks me through a few of the simpler steps.

(I'm new to Lisp (and CCL, of course) so, if I'm asking completely the wrong question or going about things completely the wrong way, feel free to let me know.)

Thanks!

Olie
  • 24,597
  • 18
  • 99
  • 131

3 Answers3

9

I am sure a CCL user might point you to the Debugging section in the CCL manual, but, in fact, the ANSI Common Lisp standard includes excellent debugging facilities, including break and step you asked about (except for step's granularity is not based on a line of code but rather a form).

In fact, the whole Condition System is worth examining.

There are a few tutorials too.

The most important thing to remember that the debugging tools give you the normal Lisp REPL (Read-Eval-Print Loop) where you can do just about anything you can do with the initial REPL: define functions and variables, examine the existing variable (including those defined in the functions in which the debugger was entered) et al. Additionally, you might be able to issue additional commands, like step and next (often abbreviated :s and :n) in the stepper or continue (often abbreviated :c) in a continuable error.

One difference you need to watch for is that in gdb you examine a variable x using print x (abbreviated p x) while in Lisp you just type x and it is evaluated.

Here are some simple examples:

Step

Here ? gives help on available commands; try help or :h if your lisp barfs.

> (defun factorial (n) (if (zerop n) 1 (* n (factorial (1- n)))))
FACTORIAL
> (step (factorial 3))
step 1 --> (FACTORIAL 3)
Step 1 > ?

Commands may be abbreviated as shown in the second column.
COMMAND        ABBR     DESCRIPTION
Help           :h, ?    print this command list
Error          :e       print the last error message
Inspect        :i       inspect the last error
Abort          :a       abort to the next recent input loop
Unwind         :uw      abort to the next recent input loop
Reset          :re      toggle *PACKAGE* and *READTABLE* between the
                          local bindings and the sane values
Quit           :q       quit to the top-level input loop
Where          :w       inspect this frame
Up             :u       go up one frame, inspect it
Top            :t       go to top frame, inspect it
Down           :d       go down one frame, inspect it
Bottom         :b       go to bottom (most recent) frame, inspect it
Mode mode      :m       set stack mode for Backtrace: 1=all the stack elements
             2=all the frames                         3=only lexical frames
             4=only EVAL and APPLY frames (default)   5=only APPLY frames
Frame-limit n  :fl      set the frame-limit for Backtrace. This many frames
                          will be printed in a backtrace at most.
Backtrace [mode [limit]] :bt  inspect the stack
Break+         :br+     set breakpoint in EVAL frame
Break-         :br-     disable breakpoint in EVAL frame
Redo           :rd      re-evaluate form in EVAL frame
Return value   :rt      leave EVAL frame, prescribing the return values
Step           :s       step into form: evaluate this form in single step mode
Next           :n       step over form: evaluate this form at once
Over           :o       step over this level: evaluate at once up to the next return
Continue       :c       switch off single step mode, continue evaluation
-- Step-until :su, Next-until :nu, Over-until :ou, Continue-until :cu --
           same as above, specify a condition when to stop
Step 1 > :s
step 2 --> 3
Step 2 > :n
step 2 ==> value: 3
step 2 --> (IF (ZEROP N) 1 (* N (FACTORIAL #)))
Step 2 > :s
step 3 --> (ZEROP N)
Step 3 > :n
step 3 ==> value: NIL
step 3 --> (* N (FACTORIAL (1- N)))
Step 3 > :s
step 4 --> N
Step 4 > :n
step 4 ==> value: 3
step 4 --> (FACTORIAL (1- N))
Step 4 > :s
step 5 --> (1- N)
Step 5 > :n
step 5 ==> value: 2
step 5 --> (IF (ZEROP N) 1 (* N (FACTORIAL #)))
Step 5 > :c
step 5 ==> value: 2
step 4 ==> value: 2
step 3 ==> value: 6
step 2 ==> value: 6
step 1 ==> value: 6
6

Note that the prompt inside the stepper is step <level> where level is the nesting level.

Break

> (defun assert-0 (x) (unless (eql x 0) (break "Bad x: ~S" x)) 0)
ASSERT-0
> (assert-0 0)
0
> (assert-0 'assert-0)

** - Continuable Error
Bad x: ASSERT-0
If you continue (by typing 'continue'): Return from BREAK loop
The following restarts are also available:
ABORT          :R1      Abort main loop
Break 1 > x
ASSERT-0
Break 1 > :c
0

Here the prompt is Break <level>.

Assert

> (defun my+1 (x) (assert (numberp x) (x) "must be a number: ~S" x) (1+ x))
MY+1
> (my+1 5)
6
> (my+1 'my+1)

** - Continuable Error
must be a number: MY+1
If you continue (by typing 'continue'): Input a new value for X.
The following restarts are also available:
ABORT          :R1      Abort main loop
Break 1 > :c
New X> 'foo

** - Continuable Error
must be a number: FOO
If you continue (by typing 'continue'): Input a new value for X.
The following restarts are also available:
ABORT          :R1      Abort main loop
Break 1 > :c
New X> 6
7

assert uses the same prompt as break.

sds
  • 58,617
  • 29
  • 161
  • 278
  • The CCL manual and Hyperspec are both excellent reference material, but I'm looking for a bit more hand-holding, which is why I'm asking for a tutorial. Thanks! – Olie Aug 07 '13 at 14:19
  • +1 for an excellently detailed answer. However, when I type `(step (factorial 3))` into my CCL (both 1.8 and 1.9), I get the respose `6` (the answer to 3!) -- no stepping. – Olie Aug 08 '13 at 22:39
  • @Olie: it is best to ask this CCL-specific question on a dedicated CCL mailing list. My guess is that either CCL supports stepping only on interpreted functions and your `factorial` is compiled or this is a bug in CCL. – sds Aug 08 '13 at 22:56
  • 2
    CCL does not support STEP. According to this SO: http://stackoverflow.com/questions/9415000/step-macro-does-not-work-in-clozure-cl/13211050#13211050 – Juanito Fatas Aug 09 '13 at 01:31
  • This answer above should be deleted as it is misleading. STEP is not supported by CCL –  Sep 01 '17 at 16:03
  • If CCL does not support STEP, it is a standard compliance bug and should be reported as such. – sds Sep 03 '17 at 03:18
  • @sds maybe it should be reported as a bug (but in fact it is already well known that CCL does not support STEP), however the OP's question was focused on CCL and your answer, although very useful generally, did not specifically address the OP's concern. –  Feb 15 '20 at 15:56
4

The simple answer you are looking for is given by juanitofatas. Unfortunately CCL does not support step and hence is weak in debugging. Until now the best implementation to debug is CLISP.

  • CCL does not support step. The down-vote was given to me out of spite and not based on evidence. the answer below which got 6 up-votes is simply wrong. –  Mar 12 '17 at 11:21
0

in ccl, you can use cl-stepper:step instead of cl:step.

(ql:quickload "com.informatimago.common-lisp.lisp.stepper")

sds
  • 58,617
  • 29
  • 161
  • 278
shawwp
  • 1
  • 2