Artifact 227f70b01c9d8bf0e678c5feaa555dfded9e525670a9a40a76c2a28e416fc50f:
- File
r36/help/rdebug.tex
— part of check-in
[152fb3bdbb]
at
2011-10-17 17:58:33
on branch master
— svn:eol-style, svn:executable and line endings for files
in historical/r36 treegit-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1480 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: schoepf@users.sourceforge.net, size: 12627) [annotate] [blame] [check-ins using] [more...]
\begin{document} \begin{Introduction}{Debugging} The package \name{RDEBUG} helps you to find bugs in algebraic REDUCE programs by making the functions of the PSL package \name{DEBUG} available for algebraic mode. The following facilities are available: Entry-exit trace (\nameref{tr}, \nameref{untr}): visualize every call of explicitly declared functions, printing their arguments and results. Assignment trace (\nameref{trst}, \nameref{untrst}): report all assignments which are executed inside explicitly declared functions. This facility is not available for compiled functions. Breakpoint (\nameref{br}, \nameref{unbr}): interrupt the program execution at entry and exit of explicitly declared functions, invoking a \nameref{breakloop}. Conditional trace (\nameref{trwhen}, \nameref{untrwhen}) or break (\nameref{brwhen},\nameref{unbrwhen}). Rule trace (\nameref{trrl}, \nameref{untrrl}): report the arguments and results of a rule whenever it fires. You can control the debug output using the operator \nameref{trout} and the variable \nameref{trlimit}. \end{Introduction} %============================================================= \begin{Concept}{breakloop} \index{debug} A \name{break loop} is an interrupt of the program execution where control is given temporarily to the terminal for entering commands in a standard command - evaluate - print loop. When a break occurs, you can inspect the current environment or even alter it, and the interrupted computation may be terminated or continued. A break can be caused - by an internal error when the switch \nameref{break} is on, - by an explicit call of \name{lisp break()}, - at entry and exit time of a procedure which has been declared by \nameref{br}. In a break situation the evaluation is stopped temporarily and the control returns to the terminal with a special prompt: \name{break[1]1:}. The number in square brackets counts the break level - it is increased when a break occurs inside a break; the normal REDUCE statement counter follows. Each break loop supports its own statement numbers and input and output buffers. After terminating of a break loop the previous statement counters and buffers are restored. In a break loop all REDUCE commands can be entered. Additionally, there is a set of single character commands which allow you to control the break environment. All these begin with an underscore character: \name{\_a;} terminate break and return to the top REDUCE level \name{\_c;} continue execution of interrupted procedure \name{\_i;} print a backtrace (list of procedures in the call hierarchy) \name{\_l} \meta{var}; (local) read the content of the local variable \meta{var} \name{\_m;} print the last (LISP-) error message \name{\_q;} terminate the break loop and return to the next higher level. Global variables can be accessed as usual in the REDUCE language. They can also be set to different values in the break loop. The inspect values assigned to dummy arguments and scalar variables of procedures in the actual call hierarchy, you need a special command \name{\_l}. These values cannot be altered in the break loop. \begin{Examples} procedure p1(x); \\ begin scalar y1; y1:=x^2; return p2(y1); end;\\ procedure p2(q); q^2;\\ br p2;\\ x:=22;\\ p1(alpha);\\ p2 being entered\\ q: alpha**2$\\ Break before entering `p2'\\ break[1]1: x; & 22\\ break[1]2: _l x; & alpha\\ break[1]3: _l y1; & alpha^2 \\ break[1]4: _l q;& alpha^2 \\ break[1]6: _c;\\ Break after call `p2', value `(expt (expt alpha 2) 2)'\\ break[1]1: _c;\\ &alpha^4\\ \end{Examples} In the corresponding break loop caused by calling \name{p2} indirectly via \name{p1}, you can access the global \name{x}, the locals \name{x} and \name{y1} of \name{p1} and the \name{q} of \name{p2}. \end{Concept} %========================================================= \begin{Operator}{tr} \index{trace}\index{debug} The command \name{tr} puts one or several procedures to under trace. Every time such a function is executed, a message is printed during the procedure entry and another one is generated at the return time. The entry message records the actual procedure arguments equated to the dummy parameter names, and at the exit time the procedure value is printed. Recursive calls are marked by an indentation and a level number. \begin{Syntax} \name{tr}\meta{proc1},\meta{proc2},...,\meta{procn}; \end{Syntax} Here \meta{proc1},\meta{proc2},...,\meta{procn} are names of procedures to be added to the set of traced procedures. See also \nameref{trst},\nameref{trwhen}. \end{Operator} \begin{Operator}{untr} \index{trace}\index{debug} Tracing is stopped for one or several functions by the command \name{untr}: \begin{Syntax} \name{untr}\meta{proc1},\meta{proc2},...,\meta{procn}; \end{Syntax} \end{Operator} %======================================================== \begin{Operator}{trst} \index{trace}\index{assignment-trace}\index{debug} Sometimes one needs detailed information about the inner behavior of a procedure, especially if it is a longer piece of code. For a procedure declared in a \name{trst} command an extended trace is performed: all executed explicit assignments and all passed labels are reported at run time. \begin{Syntax} \name{trst}\meta{proc1},\meta{proc2},...,\meta{procn}; \end{Syntax} Here \meta{proc1},\meta{proc2},...,\meta{procn} are names of procedures to be added to the set of traced procedures. When your program contains a \nameref{for} loop, REDUCE translates this to a sequential piece of LISP instructions. When using \name{trst}, the printout is driven by the unfolded code. When the code contains a \name{for-each-in} statement, the name of the control variable is internally used to keep the remainder of the list during the loop control, and you will see the corresponding assignments in the printout rather than the individual values in the loop steps. \end{Operator} \begin{Operator}{untrst} \index{trace}\index{assignment-trace}\index{debug} Extended tracing is stopped for one or several functions by the command \name{untrst}: \begin{Syntax} \name{untrst}\meta{proc1},\meta{proc2},...,\meta{procn}; \end{Syntax} \end{Operator} %========================================================= \begin{Operator}{trwhen} \index{trace}\index{debug} The trace output can be tunrned on or off automatically by a boolean expression which is linked to a traced procedure by the command \name{trwhen}: \begin{Syntax} trwhen \meta{name},\meta{booleanexpr}; \end{Syntax} The boolean expression must follow standard REDUCE syntax. It may contain references to global values and to the actual parameters of the procedure. As long as the procedure is not compiled, the original names of the dummy arguments are used. For a compiled procedure the original names are not available; instead the names \name{a1}, \name{a2}, ... must be used. Example: the following procedure produces trace output only if the main variable of its argument is \name{x}: \begin{Examples} procedure hugo(u); otto(u);\\ tr hugo;\\ trwhen hugo,mainvar(u)=x;\\ \end{Examples} Note: for a symbolic procedure, the \name{trwhen} command must be given in symbolic mode or with prefix $symbolic$. \end{Operator} \begin{Operator}{untrwhen} \index{trace}\index{debug} Conditional trace is stopped for a procedure by calling \begin{Syntax} untrwhen \meta{name}; \end{Syntax} \end{Operator} %======================================================== \begin{Switch}{break} \index{debug} When the switch \name{break} is set on, every evaluation error causes a \nameref{breakloop}. Most of these breaks are non-continuable; however, you have the opportunity to read the actual values of local variables in the environment which caused the error. \end{Switch} %========================================================= \begin{Operator}{br} \index{break}\index{debug} The command \name{br} declares one or several procedures as breakpoints. When executing such a function, the computation is interrupted by a \nameref{breakloop} at function enter and return times. \begin{Syntax} \name{br}\meta{proc1},\meta{proc2},...,\meta{procn}; \end{Syntax} Here \meta{proc1},\meta{proc2},...,\meta{procn} are names of procedures to be added to the set of break points. See also \nameref{brwhen}. \end{Operator} \begin{Operator}{unbr} \index{break}\index{debug} The break property can be removed by the command \name{unbr}: \begin{Syntax} \name{unbr}\meta{proc1},\meta{proc2},...,\meta{procn}; \end{Syntax} \end{Operator} % ============================================================= \begin{Operator}{brwhen} \index{break}\index{debug} The break point (see \nameref{br}) can be tunrned on or off automatically by a boolean expression which is linked to a breakpoint procedure by the command \name{brwhen}: \begin{Syntax} brwhen \meta{name},\meta{booleanexpr}; \end{Syntax} The boolean expression must follow standard REDUCE syntax. It may contain references to global values and to the actual parameters of the procedure. As long as the procedure is not compiled, the original names of the dummy arguments are used. For a compiled procedure the original names are not available; instead the names \name{a1}, \name{a2}, ... must be used. Example: the following procedure is broken only if the main variable of its argument is \name{x}: \begin{Examples} procedure hugo(u); otto(u);\\ br hugo;\\ brwhen hugo,mainvar(u)=x;\\ \end{Examples} Note: for a symbolic procedure, the \name{brwhen} command must be given in symbolic mode or with prefix $symbolic$. \end{Operator} \begin{Operator}{unbrwhen} \index{break}\index{debug} Conditional break is removed for a procedure by calling \begin{Syntax} unbrwhen \meta{name}; \end{Syntax} \end{Operator} % ============================================================== \begin{Operator}{trrl} \index{debug}\index{rule}\index{ruleset} The command \name{trrl} allows you to trace individual rules or rule sets when they fire. \begin{Syntax} trrl \meta{rs1},\meta{rs2},...,\meta{rsn}; \end{Syntax} where each of the \meta{rsi} is - a rule or a rule set, - a name of a rule or rule set (that is a non--indexed variable which is bound to a rule or rule list), - an operator name, representing the rules assigned to this operator. The specified rules are (re-) activated in REDUCE in a style that each of them prints a report every time if fires. The report is composed of the name or the rule or the name of the rule set plus the number of the rule in the set, the form matching the left hand side and the resulting right hand side. For an explicitly given rule, \name{trrl} assigns a generated name. \end{Operator} \begin{Operator}{untrrl} \index{debug}\index{rule}\index{ruleset} With \name{untrrl} you can remove the tracing from rules \begin{Syntax} untrrl \meta{rs1},\meta{rs2},...,\meta{rsn}; \end{Syntax} The rules are reactivated in their original form. Alternatively you can use the command \nameref{clearrules} to remove the rules totally from the system. Please do not modify the rules between \name{trrl} and \name{untrrl} -- the result may be unpredictable. \end{Operator} %============================================================== \begin{Operator}{trout} \index{debug}\index{io} The trace output can be redirected to a separate file by using the command \name{trout}, followed by a file name in string quotes. A second call of \name{trout} closes the actual output file and assigns a new one. The file name NIL (without string quotes) causes the trace output to be redirected to the standard output device. Remark: under Windows a file name starting with "win:" causes a new window to be opened which receives the complete output of the debugging services. \end{Operator} %============================================================== \begin{Variable}{trlimit} \index{debug}\index{io} The integer valued share variable \name{trlimit} defines an upper limit for the number of items printed in formula collections. The initial value is 5. A different value can be assigned to increase or lower the output size. \begin{Examples} trlimit:=7;\\ \end{Examples} \end{Variable} %============================================================== \begin{Variable}{trprinter} \index{debug}\index{io} If you want to select LISP style printing instead of algebraic printing during trace, set \name{trprinter!*} to \name{printx}: \begin{Syntax} lisp(trprinter!* := 'printx); \end{syntax} \end{Variable}