[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Q interpreter includes a simple symbolic debugger which can be used to trace the reductions performed during an expression evaluation. In order to use this tool successfully, you should be familiar with the way the Q interpreter evaluates expressions; see, in particular, Performing Reductions on a Stack.
The debugger is subject to activation when one of the following conditions arises:
-d
option, or the user
has activated debugging using the debug on
command (see
Using Q).
break
function on the
right-hand side of a rule (see Exception Handling).
Ctl-C
(see Error Handling).
throw
or through a trapped signal, see Exception Handling.
break
command, see below), and the interpreter is about to invoke a
user-defined rule for evaluating an application of that function.
In the first case, the debugger is always invoked as soon as an
evaluation is started. In the remaining cases the debugger is
only invoked if the break
flag is on
. The
break
flag is an internal flag of the interpreter which can be
controlled with the break
command, cf. Command Language. If
break
is off
then all kinds of exceptions normally cause
evaluation to be aborted immediately with an appropriate error message,
and invocations of the break
function are simply ignored. (The
break
flag is off
by default, so you must set it to
on
before you can catch any break points with the debugger.) Also
note that if there is a pending catch
(see Exception Handling) then the debugger will only be invoked for a call to the
break
function, if the break
flag is on
.
The break
command can also be invoked with a list of function
symbols as arguments, which sets breakpoints on the given symbols. When
a breakpoint has been set on a function symbol, the debugger will be
invoked, just as if the break
function had been called, whenever
the interpreter is about to reduce an application of that function
employing a user-defined rule. When invoked without arguments,
break
prints the current status of the break
flag and a
list of currently active breakpoints. You can use the clear
command to delete a breakpoint on the given function symbols (or all
breakpoints if no argument is specified). Moreover, there also is a
tbreak
command which sets temporary breakpoints on the given
symbols which will be removed automatically once they are hit. (In the
breakpoint list produced with break
, such temporary breakpoints
are signaled by a trailing `*'.) All these commands can be used
either from the debugger or on the interpreter's command line.
When active, the debugger prints each reduction by a built-in or user-defined rule performed during evaluation in the following format:
** left-hand-side ==> right-hand-side |
"Tail reductions" (see Tail Recursion) are signaled by a leading `++' instead of `**', global and local variable bindings (cf. Free Variables, and Local Variables) with a leading `--'.
Whenever a new rule is activated, and also after processing a qualifier, the debugger interrupts the evaluation and displays the current rule together with the corresponding source file name and line number in the following format:
level> source-file, line line-number: left-hand-side ==> right-hand-side qualifier |
(To remove clutter, the debugger only prints one qualifier at a time, namely the condition or local definition which is currently being processed.)
The level number printed in front of the rule indicates the position of the printed rule on the reduction stack (the topmost rule is at level 0). At the `:' prompt, you may then enter one of the following commands:
?, help
Print a short help message which lists the debugger commands.
help options
Print a help message which briefly describes debugger options that can be set with the `.' command.
break [on|off|function …], tbreak function …, clear [function …]
Change the break
flag and list, set or remove breakpoints (see above).
. [arg …]
Reprint the current rule (if invoked without arguments), or set debugger options.
l [offs] [lines]
List source lines of the current rule. You may specify the number of
lines to be listed (the default is 1), as well as an offset taken
relative to the line number of the current rule (this must be a signed
number, with the default being +0
).
p [arg]
Print stacked rules.
m
Print memory usage.
v
List the local variables of the current rule.
u [arg], d [arg]
Move up or down on the rule stack.
t, b
Move to the top or bottom of the stack.
<CR>
Step into the current reduction.
n
Next: step over the current reduction.
c
Continue: resume evaluation.
h
Halt: abort evaluation.
q, <EOF>
Quit: exit from the interpreter.
All other input is interpreted as an expression to be evaluated in the context of the current rule, with local variables bound to their current values. This lets you inspect the values of local variables and perform arbitrary calculations with these values. Note that debugging mode is suspended while the expression is evaluated, so only the result (or an error message) will be printed. As on the interpreter's main command line, you can use `? expression' to escape an expression which looks like a debugger command.
When evaluating an expression, the result is printed with custom pretty-printing (cf. Views) enabled, just like when evaluating an expression on the interpreter's command line. All other expressions are printed in the debugger with custom pretty-printing disabled, so that you can see exactly the "raw" data processed by the interpreter.
Command line editing works in the debugger as usual. Note, however, that the debugger maintains its own command history which is not remembered across different invocations of the interpreter.
With the debugger being activated, you can simply keep on hitting the carriage return key to go through an evaluation step by step. The `n' ("next" a.k.a. "step over") command causes the interpreter to finish the current rule and also step over any tail reductions; it then leaves you in the context from which the current rule was invoked (which might be the interpreter's command prompt, if you just stepped over the toplevel rule).
The `p' command can be used to print the stack of active rules. The optional integer argument of this command sets the maximum number of stacked rules to print. The `u', `d', `t' and `b' commands let you move around on the reduction stack; `u' and `d' move up and down the given number of levels (default: 1), while `t' and `b' take you to the top (i.e., topmost rule) and bottom (active rule) of the stack, respectively.
The `l' command lists the source of the current rule. By default, only the line at which the rule starts is printed. You can specify the number of lines to be listed; e.g., `l 5' causes five lines to be printed. To have some context of the rule printed, you can also specify a signed integer denoting the relative offset from the source line; e.g., `l -2 5' causes five lines to be printed, starting two lines above the current rule. (Both the line count and the offset are remembered across different invocations of the `l' command.)
The `v' command lists the local (i.e., "bound") variables of a
rule. This comprises the variables which are bound by the left-hand side
or have already been bound in a where
clause while the rule is
being processed. (Note that in the current implementation only those
variables will be listed whose values are actually used somewhere
on the right-hand side or in the qualifiers of the rule.)
At any point, you can use the `c', `h' and `q' commands to continue evaluation without the debugger, abort an evaluation and return to the interpreter's prompt, or quit the interpreter, respectively. The `m' command prints the current memory usage, i.e., the total number of allocated stack and heap expression cells, along with the corresponding numbers of cells which are actually in use. For the heap, it also prints the number of expression cells in the free list, i.e., temporarily unused expression cells below the current heap top. If limits are set on the maximum number of stack and heap cells, these figures are printed as well.
The current rule can be reprinted using the `.' command. Because Q
expressions can get very large, the debugger usually only prints
expression "outlines"; otherwise you could end up scrolling through
pages and pages of printouts for each reduction and rule. The `.'
command accepts some options which allow you to set the level of detail
you want to see in the printed reductions and rules; these options will
be remembered during an interpreter session. The options are generally
specified in the format option=value
and must not
contain any whitespace (blanks or tabs). Multiple options can be
specified with a single `.' command, separating different options
with whitespace. Option values can also be specified in the same format
on the interpreter's command line, using the debug
command (see
Command Language), or with the interpreter's
--debug-options
option (see Running Compiler and Interpreter). The following options are provided:
. detail=n
Set the maximum depth (a.k.a. levels of nested parentheses, 2 by
default) up to which expressions are displayed. The debugger will omit
all subexpressions below the current level. Level 1 (`. detail=1')
means to just print the toplevel expression, level 2 adds the
first-level parentheses, level 3 all second-level parentheses, etc. All
omitted parts in the expression outline will be represented using an
ellipsis `...'. If you set the level to zero, or specify the
symbolic value all
, all expressions will be printed to arbitrary
depth.
. maxitems=n
Set the maximum number of elements to print for each list or tuple. The
default is 3. A value of 0
or all
causes all list and
tuple elements to be printed.
. maxchars=n
Set the maximum number of characters to print for each string value. The
default is 33. A value of 0
or all
causes all characters
to be printed.
. maxstack=n
Set the number of stack levels to print with the `p' command. The
default is 6. A value of 0
or all
causes the entire rule
stack to be printed. This value is also modified when an argument is
specified with `p'.
. pathnames=y|n
Print full pathnames of scripts (`y' = yes, `n' = no). The default value of this option is `n', i.e., only the basenames of scripts are printed. Change this value to `y' if you want to see the complete path of a script file when a rule is printed.
. options
Print the current settings. This option does not modify any settings, but simply prints all current option values on a single line.
Let us now take a look at a typical session with the debugger. For an
example, we take the definition of the fac
function from
Writing a Script:
fac N = N*fac(N-1) if N>0; = 1 otherwise; |
The commented session with the debugger follows.
==> fac 1 evaluate |
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Albert Gräf on February, 23 2008 using texi2html 1.76.