The Maple Debugger
The Maple debugger is a tool that you can use to help find errors in your procedures. Using this facility, you can follow step-by-step execution of your code to determine why it is not producing the results that you expect.
You can use the command-line Maple debugger or the debugger available in the standard interface. The same functionality is available through both interfaces.
For command-line usage, see the following Description section.
For usage in the standard interface, see the Interactive Maple Debugger help page.
Note: Both the command-line and standard-interface debugger can use the Commands listed in this help page.
Statement and Line Numbers
When the Debugger is invoked, it displays an expression (unless the previous debugger command was terminated by a colon), the next statement to be executed, and a debugging prompt (or a prompt in a debugging window).
If the Debugger was invoked by a breakpoint (as set by stopat), or the result of executing one of the debugger commands next, step, into, outfrom, or return, the displayed expression is the result of the last statement executed.
If it was invoked by a watchpoint on a variable (as set by stopwhen or stopwhenif), the expression is an equation, the left-hand side of which is the name of the variable that was being watched, and the right-hand side of which shows the value that was assigned to the variable.
If it was invoked by a watchpoint on an error message (as set by stoperror), the expression is the error message.
Large rtables are displayed by the debugger in an abbreviated form (the data stored in the rtable is elided). This is done for rtables of more than two dimensions, or any dimension of more than interface(rtablesize) elements.
Debugging is generally carried out in terms of procedures and statement numbers, although a few of the commands listed below can also work in terms of files and line numbers.
Statement numbers correspond to the individual Maple statements within a procedure, regardless of the line or lines of a source file the statements were individually written. Statement numbers within a procedure begin with 1, and increase sequentially as the statement structure is traversed depth-first.
The statements typically encountered in procedures are: assignment, if...then...elif...else...end if, for...while...do...end do, break, next, try...catch...finally...end try, error, and return. Any stand-alone expression appearing only for its side-effects, such as a function call or a result to be implicitly returned, is also considered to be a statement. (Additionally, read, save, and quit are also statements but are rarely used within procedures. Likewise, uses and use...in...end use are statements, but are factored out during procedure simplification, and thus are never encountered while debugging.)
The following example shows a simple procedure, along with the statement numbers corresponding to each statement:
f := proc(x, y)
1 if x < y then
2 printf("x < y\n");
3 return x
elif y < x then
4 return y
5 printf("x = y: (%a)\n",x)
The first statement begins with the if, whereas the second and third statements are within the first branch of the if statement. Notice that elif and else are not separate statements, but are parts of the if statement, and thus do not have their own statement numbers.
Source Files and Line Numbers
Line numbers refer to sequential lines within a text file when a procedure was written in such a file (instead of having been entered on the command line). There is no correlation between line numbers and statement numbers. For example, depending on the author's coding style preferences, the procedure illustrated above may have appeared in a file named "MyFunctions.mpl" on lines 123 to 135 like this (the line numbers are shown for reference, and are not actually part of the file):
123 f := proc( x, y )
124 # If x <> y, return the smaller of the two values.
125 if x < y then print("x < y\n");
126 return x;
127 elif y < x then return y;
129 # If x = y, print the value.
130 printf("x = y: (%a)\n",
132 end if;
Notice that statements 1 and 2 appear together on line 125, and that statement 5 is split over lines 130 and 131. Similarly, statement 4 on line 127 is on the same line as elif, which is not itself a statement.
The Maple debugger generally works with procedures and statement numbers rather than files and line numbers because the latter is not always available. A user may be debugging procedures for which she does not have the original source code (for example, Maple's own library procedures), or the procedure may have originated somewhere other than a file (for example, it was entered on the command line or in a code edit region in the graphical user interface, or it was constructed programmatically during the execution of another procedure).
Some debugger commands are able to work with files and line numbers in those cases where the files are available.
At the debugging prompt, the following commands are available. Items shown in square brackets are optional, and the square brackets themselves are not part of the item (i.e. they are not Maple lists).
Control Flow Commands
Continues execution until another breakpoint or watchpoint is encountered, or until execution terminates normally. If an optional positive integer N was specified, execution continues until the Nth next breakpoint is encountered.
Executes the next statement at the current nesting level. If the statement is a control structure (for example, if...then...else...end if), it is executed in its entirety before execution stops again. Likewise, if the statement contains function calls, these are executed in their entirety as well. After executing the statement, control returns to the Debugger as though a breakpoint had been set. If an optional positive integer N was specified, execution continues for N statements at the current nesting level.
Executes the next statement at any level. Execution stops before the following statement, regardless of whether it is at the current nesting level, in the body of a control structure (for example, while...do...end do), or in a called function. If an optional positive integer N was specified, execution continues for N statements at any level.
Halfway between next and step. Executes the next statement. Execution stops before the following statement within the current function, regardless of whether it is at the current nesting level or in the body of a control structure. Execution will not stop in a called function. If an optional positive integer N was specified, execution continues for N statements at any level within the current function.
Execution continues until the current statement sequence has finished executing, or until a breakpoint or watchpoint is encountered. If the outfrom command is executed while stopped in a loop, execution continues until just before the first statement to be executed after the closing end do. Note that if the same breakpoint that caused execution to stop in the loop is encountered again in a subsequent iteration of the loop, execution will stop again. If the outfrom command is executed while stopped in the body of an if statement, execution continues until just before the first statement to be executed after the closing end if. If an optional positive integer N was specified, execution continues until N levels of nested statements have finished executing.
Execution continues until the currently executing procedure returns, and then stops at the next statement to be executed in the calling procedure. If an optional positive integer N was specified, execution continues until N procedures have finished executing.
The following example illustrates the function of each of the previously described control flow commands. It is assumed that computation was started by calling proc1, and that the line marked <START> is where execution is currently stopped. The other lines of the form <command> show where execution would stop again if the respective command were issued from that point:
proc3 := proc()
proc2 := proc()
if 1 < 2 then
<START> if proc3() then
proc1 := proc()
In the above example, the cont command would cause execution to continue to completion.
Similar to return, except that execution stops at the next statement to be executed in any procedure after the currently executing procedure returns. This can be used, for example, while debugging expressions such as f(g(x)) or seq(f(i),i=1..10), to continue debugging procedure f after having stopped in procedure g.
quit, done, or stop
Execution is terminated entirely, and the user is returned to the top level of Maple (that is, the Maple command prompt).
Displays a list of all procedures containing breakpoints, all watchpoints, and all error watchpoints. If source code is available for any procedures containing breakpoints, the source file names are also displayed.
stopat [procName] [statNumber] [condition]
stopat [fileName] [lineNumber] [condition]
In the first form, a breakpoint is set in the specified procedure (the currently stopped procedure by default) at the specified statement number (the first statement by default). The optional condition causes execution to stop at the breakpoint only if the condition is met. If a condition is specified, the procedure name and statement number must be specified.
The second form is only permitted if source code is available, and sets a breakpoint at the statement appearing on the specified line of the specified file (whose name is specified as a string). That line must appear within the code of a procedure for the breakpoint to be effective. If the line does not correspond directly to a statement within the procedure (e.g., the comment before the statement), the breakpoint is set on the first statement appearing after that line.
The optional condition can be a Boolean expression, a positive integer, or a range of positive integers. If a Boolean expression is given, execution stops only if the condition is true. If an integer, N, is given, execution stops only the Nth time that the breakpoint is encountered. If a range, M..N, is given, execution stops from the Mth to the Nth time that the breakpoint is encountered.
unstopat [procName] [statNumber]
The specified breakpoint (all breakpoints by default) in the specified procedure (the currently stopped procedure by default) is removed.
stopwhen [procName locOrGlobVar]
Sets a watchpoint on the specified local or global variable, and displays the current list of watchpoints. If no variable is specified, the current list of watchpoints is displayed.
stopwhenif globVar value
Sets a conditional watchpoint on the specified global variable, and displays the current list of all watchpoints.
unstopwhen [procName locOrGlobVar]
Clears the watchpoint on the specified local or global variable and displays the current list of watchpoints. If no variable is specified, all watchpoints are cleared.
Sets a watchpoint on the specified error, and returns the current list of watchpoints. If no error is specified, the current list of watchpoints is displayed. If passed the name "all", execution stops and the Debugger is invoked when any untrapped error occurs. If passed the name "traperror", execution stops when any error is trapped. For more details on using stoperror, see stoperror.
Clears the watchpoints on the specified error and displays the current list of watchpoints. If no error is specified, all error watchpoints are cleared.
Displays the value of lasterror or lastexception at the time the Debugger was invoked. The displayed value is enclosed in a list; the enclosing list is not part of the actual value.
Execution State Display Commands
Shows a stack of the procedure calls leading to where execution is currently stopped. If a number of levels is specified, only that number of levels is shown (the deepest levels are shown). The topmost level is shown first.
Each level begins with a horizontal line containing the level number enclosed in angle brackets, with 0 denoting the top level. For each level, the calling procedure and the statement within it are shown, followed by a list on the next line giving the arguments that were passed.
If the where command was terminated with a colon (":"), the arguments are not shown.
where? [numLevels] (or showstack [numLevels])
Shows an abbreviated stack of the procedure calls leading to where execution is currently stopped. Only the names of the procedures in the call chain are listed.
Commands to Display Procedures and Expressions
showstat [procName] [statNumber[..statNumber]]
Displays the specified procedure (the currently stopped procedure by default) with statement numbers. If a specific statement number or range of statement numbers is given, only those statements are displayed. The elided statements are represented by "..." in the output.
The output generated by showstat is not the original source code, but a canonical reconstruction of the procedure, with at most one statement per line, and with statement numbers preceding each line corresponding to a statement (or the beginning of a multi-line statement). The output also indicates any breakpoints set on the displayed statements, as well as the location where execution is currently stopped.
showsource [procName] [statNumber[..statNumber]]
Similar to showstat, except that if source code is available, the lines of the source file corresponding to the specified statement numbers are displayed instead of the reconstructed statements. Each line is preceded by a line number, and if the line corresponds to a statement, a statement number too. If source code is not available, showsource issues a warning, and then produces the same output as showstat instead.
list [procName] [statNumber[..statNumber]]
Similar to showstat or showsource, except that if no arguments are given, the previous five statements, the current statement, and the next statement are shown. This is an easy way to see some context in the procedure. The list command shows source code if it is available, or reconstructed statements otherwise.
procinfo Displays the procedure name, parameter declarations, and local variables of the procedure in which execution is currently stopped.
edit [procName] [statNumber]
editsource [procName] [statNumber]
If source code is available, edit or editsource (the two are equivalent) opens the file containing the procedure, and positions the cursor at the line corresponding to the specified statement number. If source code is not available, edit displays a warning and does nothing.
The invocation of the text editor is controlled by the global variable `debugger/editor`. This should be set to a string specifying a shell command that will open the editor. The string should contain "%s" to indicate where the file name should appear in the command, and "%d" to indicate the line number. For example, the following string will cause edit to use "gvim" (the graphics version of "vim") on most Linux installations:
`debugger/editor` := "gvim +%d '%s'";
If you usually use a non-graphical editor (one that runs in a terminal window), a command like this will be more appropriate:
`debugger/editor` := "xterm -e vim +%d '%s' &";
The editor command should be one that opens the editor in a separate window and then returns immediately to the calling process, otherwise the Maple debugger prompt will not reappear until the editor is closed. The second example above uses "&" to put the opened terminal in the background (this was not necessary for the first example because "gvim" does this automatically).
Any Maple Expression
The expression is evaluated in the context of the stopped procedure and the result is displayed. The semantics of variable names and evaluation are exactly the same as they would be if the expression had originally appeared within the procedure (except that using a variable as the control variable of seq() will not make that variable local if it is not already local). Because the Debugger runs in its own environment, the expressions lasterror and lastexception do not refer to the error that may have caused the Debugger to be invoked. Use the showerror or showexception commands instead.
Similar to the above, except the expression is evaluated in a global context and the result is displayed. The keyword statement must precede the Maple expression.
inspect stackLevel name
inspect [stackLevel [statNumber[..statNumber]]]
In the first form, inspect displays the value of a parameter or local variable of any procedure currently active on the calling stack. The stackLevel refers to the level numbers displayed by the where command described above. The level can also be specified as a negative number, where -1 refers to the procedure that called the currently stopped procedure, -2 the one that called that one, and so on.
If the parameter or local variable being inspected has an indexable value (e.g. a table, rtable, module, list, etc.), the name may be followed by an index enclosed in square brackets to select one or more elements of the value. All normal Maple indexing operations are supported, except that the index expression must be one that can be evaluated at the current level. That is, inspect -3 A[i] will not work if i is meant to refer to the value of i in the procedure three levels up the stack. In cases like these, one can first use inspect -3 i to obtain the value of i, and then inspect -3 A[...] with "..." replaced by that value.
In the second form, the inspect command is similar to list, except for any procedure currently on the calling stack. The optional statNumber range has the same meaning as it does in the showstat, showsource, and list commands.
Issuing an inspect command with no arguments is equivalent to list with no arguments.
When inspect displays a procedure, the statement from which that procedure called the one below it is indicated by a ">" character after the statement number.
lvalue := expression
The expression is evaluated in the context of the stopped procedure, and the result is assigned to the expression on the left-hand side, which can refer to global variables, environment variables, or local variables of the stopped procedure. A space must precede the assignment operator for it to be recognized.
In the Standard interface, opens this help page. In the Command-line interface, displays a short summary of all the debugger commands. If a commandPrefix is specified, only those commands beginning with that prefix are shown. If commandPrefix is gdb, a cross reference from GNU debugger to Maple debugger commands is shown.
Maple statements that are not expressions (for example, if, while, and so on) are not permitted at the Debugger prompt.
If the global variable debugger/max_width is set to a positive integer value, expressions and error messages displayed by the Debugger are truncated to that width.
The Debugger is implemented as a Maple procedure which is invoked automatically by Maple when a breakpoint or watchpoint is encountered, or when the DEBUG function is executed. The Debugger procedure should not be invoked by the user.
Note: These examples illustrate the use of these debugger commands in Maple's command-line interface. In the standard (graphical) interface, the debugger runs in its own window, with controls for most of the common commands. Commands may also be typed in this window. See Interactive Maple Debugger for details.
f := proc(x,y) local a; global b;
if x < y then
a := x; b := y + a;
a := y; b := x + a;
a + b + x + y
1* if x < y then
DBG> stopwhen b
b := 5
f := proc(x, y)
2 a := x;
3 b := y+a
4 a := y;
5 b := x+a
6 ! a+b+x+y
Warning, computation interrupted
The help and retstep debugger commands are new in Maple 2020.
Interactive Maple Debugger
Download Help Document