REDUCE

13.1 The Debug Module

debug is a loadable option. This module provides a basic debugging tool which provides a breakpoint function, and functions for breaking and tracing functions and methods selected by the user. debug is loaded automatically if one of the functions tr, trst or br is called.

13.1.1 Overview of Functionality

The function breakpoint allows the user to set a breakpoint anywhere within his code. Whenever a breakpoint is called a continuable break loop is entered. This allows the user to examine or modify variables, view a backtrace, and continue execution.

Tracing gives a record of the sequence of calls made to a set of functions specified by the user. When a traced function is entered a message is printed giving the function name, level of recursion, and values of any arguments. Upon function exit another message is printed, giving the value returned by the function.

Breaking a function means that the system enters a continuable break loop both before and after evaluation of the body of the function. Within the break loop the user may inspect and change values of parameters and non-local variables, and then continue execution. A break on entry occurs after the function’s formal parameters have been bound to the actual arguments but before any of the forms in the function body have been evaluated. The break on exit occurs after the body of the broken function has been evaluated.

13.1.2 Using Break and Trace

(tr [NAME: id]): list macro
If no arguments are given then a list is returned which indicates which functions are currently being traced. Otherwise, each argument is treated as a reference to a function, and if possible, the function is set up for tracing. The list which is returned represents the functions which have been added to the set of functions being traced.

(trst [NAME: id]): list macro
If no arguments are given then a list is returned which indicates which functions are currently being traced. Otherwise, each argument is treated as a reference to a function, and if possible, the function is set up for tracing. The list which is returned represents the functions which have been added to the set of functions being traced. Trst can be used only for functions which are not compiled. Additionally to the entry and exit messages, for each setq assignment inside the function the variable name and the value are printed.

(br [NAME: id, method-specification]): list macro
If no arguments are given then a list is returned which indicates which functions are currently broken. NAME is treated as a reference to a function, and if possible, the function is set up for breaking. Subsequent arguments will be processed. The list which is returned represents the functions which have been added to the set of broken functions.

(untr [NAME:id]): list macro
If no arguments are given then tracing is removed for each traced function. NAME is treated as a reference to a function, and if possible, tracing is disabled for this function. Subsequent arguments will be processed. The list which is returned contains the names of the functions for which tracing has been removed.

(unbr [NAME:id,]): list macro
If no arguments are given then breaking is turned off for each broken function. NAME is treated as a reference to a function, and if possible, breaking is disabled for this function. The list which is returned contains the names of the functions for which breaking has been removed.

13.1.3 Sample Session

Trace and break printout goes to the standard output channel. Because multiple nested calls are usually shown, indentation and vertical bars are used to line up function entry and return messages for the same function.

(de add3 (a1 a2 a3)  
  (+ a1 (add2 a2 a3)))

(de add2 (a1 a2)  
  (+ a1 a2))

(de fact (n)  
  (cond ((zerop n) 1)  
        (t (times n (fact (sub1 n))))))

1 lisp> (br add3)  
In a break, t prints backTrace; c Continues;  
q Quits a level; a Aborts to top.  
(ADD3)  
2 lisp> (tr 'add3)  
⋆⋆⋆⋆⋆ (QUOTE ADD3) is not a valid method-specification.  
NIL  
3 lisp> (tr add3 add2)  
(ADD2 ADD3)  
4 lisp> (add3 5 6 7)  
ADD3 entry:  
|     A1: 5  
|     A2: 6  
|     A3: 7  
|  ADD3 entry BREAK:  
|  NMODE Break loop  
5 lisp break (1)> c     % Continue  
|  |  ADD2 entry:  
|  |  |     A1: 6  
|  |  |     A2: 7  
|  |  ADD2 value = 13  
|  ADD3 exit BREAK, value = 18:  
|  NMODE Break loop  
6 lisp break (1)> c  
ADD4 value = 18  
18

1 lisp> (tr fact)  
(FACT)  
2 lisp> (fact 4)  
FACT entry:  
|     N: 4  
|  FACT reentry (# 2):  
|  |        % (# 2) represents the depth of recursion  
|  |     N: 3  
|  |  FACT reentry (# 3):  
|  |  |     N: 2  
|  |  |  FACT reentry (# 4):  
|  |  |  |     N: 1  
|  |  |  |  FACT reentry (# 5):  
|  |  |  |  |     N: 0  
|  |  |  |  FACT value (# 5) = 1  
|  |  |  FACT value (# 4) = 1  
|  |  FACT value (# 3) = 2  
|  FACT value (# 2) = 6  
FACT value = 24  
24  
3 lisp> (trace)  
(FACT ADD2 ADD3 ADD4)  
4 lisp> (untrace)  
(ADD4 ADD3 ADD2 FACT)  
5 lisp> (restr)  
T

Tracing a macro will happen at macroexpand time. The value returned will be the macroexpanded form, and thus is quite useful in determining if your macro expanded properly. Note that when code is complied the application of a macro is expanded and this expansion replaces the the application.

1 lisp> (trace plus)  
(PLUS)  
2 lisp> (plus 2 9 -3 7 8)  
PLUS entry:  
|     ARG1 :(PLUS 2 9 -3 7 ...)  
PLUS value = (PLUS2 2 (PLUS2 9 (PLUS2 -3 (PLUS2 7 8))))  
23

(de fact (n)  
  (cond ((zerop n) 1)  
        (t (breakpoint "Fact; n<>0 branch of cond, n=%p" n)  
           (times n (fact (sub1 n))))))

1 lisp> (fact 2)  
User Breakpoint: Fact; n<>0 branch of cond, n=2  
NMODE Break loop  
2 lisp break (1)> c  
User Breakpoint: Fact; n<>0 branch of cond, n=1  
NMODE Break loop  
3 lisp break (1)> c  
2

13.1.4 Redefining a Broken or Traced Function

The basic definition of a function is the definition without any of the break or tracing side effects. This basic definition may be accessed by the function getd. The basic definition may also be redefined by using the function putd without interfering with the break/trace side effects, as long as the parameter list stays the same. If you intend to change the number or order of parameters you should first remove the break/trace wrappers from it with untrace and/or unbr.