This section describe the commands available at the debugger prompt in the debugger’s command line interface (for the graphical user interface, please refer to the online documentation).
Commands are entered by typing the corresponding key (without newline), the case of the letters is significant. The action of some of them is immediate, others require additional parameters to be typed afterwards. Since the ECLiPSe debugger has the possibility to display not only the goal that is currently being executed (the current goal or procedure), but also its ancestors, some of the commands may work on the displayed procedure whatever it is, and others on the current one.
Some debugger commands accept a counter (a small integer number) before the command letter (e.g., c, i.e., creep). The number is just prefixed to the command and terminated by the command letter itself. If a counter is given for a command that doesn’t accept a counter, it is ignored.
When a counter is used and is valid for the command, the command is repeated, decrementing the counter until zero. When repeating the command, the command and the remaining counter value is printed after the debugger prompt instead of waiting for user input.
Some commands prompt for a parameter, e.g., the j (jump) command asks for the number of the level to which to jump. Usually the parameter has a sensible default value (which is printed in square backets). If just a newline is typed, then the default value is taken. If a valid parameter value is typed, followed by newline, this value is taken. If an illegal letter is typed, the command is aborted.
All commands in this section continue program execution. They difference between them is the condition under which execution will stop the next time. When execution stops again, the next trace line is printed and a new command is accepted.
[eclipse 3]: p. (1) 1 CALL p %> skip (1) 1 FAIL p %> query culprit failure culprit was (3) - rerun and type q to jump there %> nodebug? [y] No (0.00s cpu) [eclipse 4]: p. (1) 1 CALL p %> query culprit failure culprit was (3) - jump to invoc: [3]? (3) 3 CALL r(1) %> creep (3) 3 FAIL r(...) %> creep (2) 2 FAIL q %> creep (1) 1 FAIL p %> creep No (0.01s cpu)
[eclipse 4]: [X, Y] :: 1..9, X #>= Y, Y#>1. (1) 1 CALL [X, Y] :: 1..9 %> var/term spy? [y] Var/term spy set up with invocation number (2) %> jump to invoc: [1]? 2 (2) 3 MODIFY [X{[1..9]}, Y{[2..9]}] :: 1..9 %> jump to invoc: [2]? (2) 4 MODIFY [X{[2..9]}, Y{[2..9]}] :: 1..9 %> jump to invoc: [2]?Note that these monitors can also be set up from within the program code using one of the built-ins spy_var/1 or spy_term/2.
This group of commands cause some useful information to be displayed.
[eclipse 5]: [X, Y] :: 1..9, X #>= Y, Y #>= X. (1) 1 CALL [X, Y] :: 1..9 %> creep (1) 1 EXIT [X{[1..9]}, Y{[1..9]}] :: 1..9 %> creep (2) 1 CALL X{[1..9]} - Y{[1..9]}#>=0 %> creep (3) 2 DELAY X{[1..9]} - Y{[1..9]}#>=0 %> creep (2) 1 EXIT X{[1..9]} - Y{[1..9]}#>=0 %> creep (4) 1 CALL Y{[1..9]} - X{[1..9]}#>=0 %> creep (5) 2 DELAY Y{[1..9]} - X{[1..9]}#>=0 %> delayed goals with prio: [all]? ------- delayed goals ------- (3) <2> X{[1..9]} - Y{[1..9]}#>=0 (5) <2> Y{[1..9]} - X{[1..9]}#>=0 ------------ end ------------ (5) 2 DELAY Y{[1..9]} - X{[1..9]}#>=0 %>
[eclipse 13]: [X,Y,Z]::1..9, X#>Z, Y#>Z, Z#>1. (1) 1 CALL [X, Y, Z] :: 1..9 %> creep (1) 1 EXIT [X{[1..9]}, Y{[1..9]}, Z{[1..9]}] :: 1..9 %> creep (2) 1 CALL X{[1..9]} - Z{[1..9]}+-1#>=0 %> creep (3) 2 DELAY X{[2..9]} - Z{[1..8]}#>=1 %> creep (2) 1 EXIT X{[2..9]} - Z{[1..8]}+-1#>=0 %> creep (4) 1 CALL Y{[1..9]} - Z{[1..8]}+-1#>=0 %> creep (5) 2 DELAY Y{[2..9]} - Z{[1..8]}#>=1 %> creep (4) 1 EXIT Y{[2..9]} - Z{[1..8]}+-1#>=0 %> creep (6) 1 CALL 0 + Z{[1..8]}+-2#>=0 %> creep (3) 2 RESUME X{[2..9]} - Z{[2..8]}#>=1 %> scheduled goals with prio: [all]? ------ scheduled goals ------ (5) <2> Y{[2..9]} - Z{[2..8]}#>=1 ------------ end ------------ (3) 2 RESUME X{[2..9]} - Z{[2..8]}#>=1 %>
(230) 4 CALL check_word(what, _5824) %> write source lines Source file: /homes/user/EclipseTests/Chatq/newtop 241 :- mode check_words(+,-). 242 243 check_words([],[]). 244 check_words([Word|Words],[RevWord|RevWords]) :- 245> check_word(Word,RevWord), 245 check_words(Words,RevWords). 246 247 :- mode check_word(+,-). 248 %>
The listing shows the line numbers for the source lines, with a > marking the line with the current goal. Note it is the actual body goal that is shown, rather than the predicate definition as in the . command. An optional numeric argument can be given before the command, specifying the number of lines surrounding (i.e., before and after) the current goal that should be listed:
%> 2write source lines Source file: /homes/user/EclipseTests/Chatq/newtop 243 check_words([],[]). 244 check_words([Word|Words],[RevWord|RevWords]) :- 245> check_word(Word,RevWord), 245 check_words(Words,RevWords). 246 %>
Source is only shown if the source information is available—that is, the code has to be compiled debuggable from a file, and not all goals have source information; for example, goals in meta-calls (e.g., those inside a call/1). Also, source context cannot be shown at a RESUME port.
While the debugger waits for commands, program execution is always stopped at some port of some predicate invocation box, or goal. Apart from this current goal, two types of other goals are also active. These are the ancestors of the current goal (the enclosing, not yet exited boxes in the box model) and the delayed goals. The debugger allows to navigate among these goals and inspect them.
This family of commands allow the subterms in the goal displayed at the port to be inspected. The ability to inspect subterms is designed to help overcome two problems when examining a large goal with the normal display of the goal at a debug port:
With inspect subterm commands, the user is able to issue commands to navigate through the subterms of the current goal and examine them. A current subterm of the goal is maintained, and this is printed after each inspect subterm command, instead of the entire goal. Initially, the current subterm is set to the goal, but this can then be moved to the subterms of the goal with navigation commands.
Once inspect subterm is initiated by an inspect subterm command, the debugger enters into the inspect subterm mode. This is indicated in the trace line by INSPECT instead of the name of the port, and in addition, the goal is not shown on the trace line:
INSPECT (length/2) %>
Instead of showing the goal, a summary of the current subterm—generally its functor and arity if the subterm is a structure—is shown in brackets.
#
, which causes the
debugger to prompt for a number. In both cases, the number specifies the
argument number to move down to.
In the following example, the #
style of the command is used to move
to the first argument, and the number style of the command to move to the
third argument:(1) 1 CALL foo(a, g(b, [1, 2]), X) %> inspect arg #: 1<NL> a INSPECT (atom) %>
(1) 1 CALL foo(a, g(b, [1, 2]), X) %> 3<NL> X INSPECT (var) %>
The new current subterm is printed, followed by the INSPECT trace line. Notice that the summary shows the type of the current subterm, instead of Name/Arity, since in both cases the subterms are not structures.
If the current subterm itself is a compound term, then it is possible to recursively navigate into the subterm:
(1) 1 CALL foo(a, g(b, [1, 2]), X) %> 2<NL> g(b, [1, 2]) INSPECT (g/2) %> 2<NL> [1, 2] INSPECT (list 1-head 2-tail) %> 2<NL> [2] INSPECT (list 1-head 2-tail) %>
Notice that lists are treated as a structure with arity 2, although the functor (./2) is not printed.
In addition to compound terms, it is also possible to navigate into the attributes of attributed variables:
[eclipse 21]: suspend(foo(X), 3, X->inst), foo(X).<NL> (1) 1 DELAY foo(X) %> <NL> creep (2) 1 CALL foo(X) %> 1<NL> X INSPECT (attributes 1-suspend 2-fd ) %>1<NL> suspend(['SUSP-1-susp'|_218] - _218, [], []) INSPECT (struct suspend/3) %>
The variable X is an attributed variable in this case, and when it is the current subterm, this is indicated in the trace line. The debugger also shows the user the currently available attributes, and the user can then select one to navigate into (fd is available in this case because the finite domain library was loaded earlier in the session. Otherwise, it would not be available as a choice here).
Note that the suspend/3 summary contains a struct before it. This is because the suspend/3 is a predefined structure with field names (see section 5.1). It is possible to view the field names of such structures using the . command in inspect mode.
If the number specified is larger than the number of the arguments of the current subterm, then an error is reported and no movement is made:
foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %> 4<NL> Out of range..... foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %>
An optional argument can preceded the uparrow keystroke, which indicates the number of levels to move up. The default is 1:
(1) 1 CALL foo(a, g(b, [1, 2]), 3) %> 2<NL> g(b, [1, 2]) INSPECT (g/2) %> 1<NL> b INSPECT (atom) %> up subterm g(b, [1, 2]) INSPECT (g/2) %> 1up subterm foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %>
The debugger prints up subterm when the uparrow key is typed. The current subterm moves back up the structure to its parent for each level it moves up, and the above move can be done directly by specifying 2 as the levels to move up:
b INSPECT (atom) %> 2up subterm foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %>
If the number of levels specified is more than the number of levels that can be traversed up, the current subterm stops at the toplevel:
(1) 1 CALL foo(a, g(b, [1, 2]), 3) %> 2<NL> g(b, [1, 2]) INSPECT (g/2) %> 2<NL> [1, 2] INSPECT (list 1-head 2-tail) %> 5up subterm foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %>
(1) 1 CALL foo(a, g(b, [1, 2]), 3) %> 2<NL> g(b, [1, 2]) INSPECT (g/2) %> 2<NL> [1, 2] INSPECT (list 1-head 2-tail) %> 2<NL> [2] INSPECT (list 1-head 2-tail) %> 2<NL> [] INSPECT (atom) %> 0<NL> foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %>
Moving to the top can also be done by the #
command, and not giving
any argument (or notation0) when prompted for the argument.
foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %> 3<NL> 3 INSPECT (integer) %> 2left subterm a INSPECT (atom) %>
If the leftward movement specified would move the argument position before the first argument of the parent term, then the movement will stop at the first argument:
foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %> 3<NL> 3 INSPECT (integer) %> 5left subterm a INSPECT (atom) %>
In the above example, the current subterm was at the third argument, thus trying to move left by 5 argument positions is not possible, and the current subterm stopped at leftmost position—the first argument.
foo(a, g(b, [1, 2]), 3) INSPECT (integer) %> 2left subterm a INSPECT (atom) %>
If the rightward movement specified would move the argument position beyond the last argument of the parent term, then the movement will stop at the last argument:
foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %> 3<NL> 3 INSPECT (integer) %> right subterm 3 INSPECT (integer) %>
In the above example, the current subterm was at the third (and last) argument, thus trying to move to the right (by the default 1 position in this case) is not possible, and the current subterm remains at the third argument.
foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %> 2<NL> g(b, [1, 2]) INSPECT (list 1-head 2-tail) %> 3down subterm 2 for 3 levels [] INSPECT (atom) %>
In the above example, the user moves down into the second argument, and then use the down-arrow key to move down into the second argument for 2 levels—the numeric argument typed before the arrow key specified the number of levels that the current subterm was moved down by. The command moves into the second argument because it was at the second argument position when the command was issue.
However, there is not always an argument position for the current sub-term. For example, when the current sub-term is at the toplevel of the goal or if it is at an attribute. In these cases, the default for the argument position to move down into is the first argument:
INSPECT (atom) %> 0<NL> foo(a, g(b, [1, 2]), 3) INSPECT (foo/3) %> down subterm 1 for 1 levels a INSPECT (atom) %>
In the above example, the down-arrow key is typed at the top-level, and thus the argument position chosen for moving down is first argument, with the default numeric argument for the
If the argument position to move into is beyond the range of the current subterm’s number of arguments, then no move is performed:
(1) 1 CALL foo(a, b, c(d, e)) %> 3<NL> c(d, e) INSPECT (c/2) %> Out of range after traversing down arg... c(d, e) INSPECT (c/2) %>
In this case, the down-arrow key was typed in the second trace line, which had the current subterm at the third argument of its parent term, and thus the command tries to move the new current subterm to the third argument of the current sub-term, but the structure does not have a third argument and so no move was made. In the case of moving down multiple levels, then the movement will stop as soon as the argument position to move down to goes out of range.
Moving down is particularly useful for traversing lists. As discussed, lists are really structures with arity two, so the #N command would not move to the Nth element of the list. With the down-arrow command , it is possible to move into the Nth position in one command:
[eclipse 30]: foo([1,2,3,4,5,6,7,8,9]). (1) 1 CALL foo([1, 2, 3, ...]) %> 1<NL> [1, 2, 3, 4, ...] INSPECT (list 1-head 2-tail) %> 2<NL> [2, 3, 4, 5, ...] INSPECT (list 1-head 2-tail) %> 6down subterm 2 for 6 levels [8, 9] INSPECT (list 1-head 2-tail) %>
In order to move down a list, we repeatedly move into the tail of the list—the second argument position. In order to do this with the down-arrow command, we must be at the second argument position first, and this is done in the second trace line. Once this is done, then it is possible to move arbitrarily far down the list in one go, as is shown in the example.
:- local struct(capital(city,country)). ..... (1) 1 CALL f(capital(london, C)) %> 1<NL> capital(london, C) INSPECT (struct capital/2) %> structure definition: 1=city 2=country %>
In this example, a structure definition was made for capital/2. When this structure is the current subterm in the inspect mode, the struct in the summary for the structure indicates that it has a structure definition. For such structures, the field names are printed by the structure definition command.
If the command is issued for a term that does not have a structure definition, an error would be reported:
INSPECT (f/1) %> structure definition: No struct definition for term f/1@eclipse. %>
(1) 1 CALL foo(a, g(b, [1, 2]), 3) %> 2<NL> g(b, [1, 2]) INSPECT (g/2) %> 2<NL> [1, 2] INSPECT (list 1-head 2-tail) %> 1<NL> 1 INSPECT (integer) %> p Subterm path: 2, 2, 1 %>
The subterm path shows the argument positions taken at each level of the toplevel term to reach the current subterm, starting from the top.
Extra information (in addition to the numeric argument position) will be printed if the subterm at a particular level is either a structure with field names or an attributed variable. For example:
:- local struct(capital(city,country)). ..... [eclipse 8]: suspend(capital(london, C), 3 ,C -> inst), f(capital(london, C)). .... (2) 1 CALL f(capital(london, C)) %> 1<NL> capital(london, C) INSPECT (struct capital/2) %> 2<NL> C INSPECT (attributes 1-suspend ) %> 1<NL> suspend(['SUSP-1-susp'|_244] - _244, [], []) INSPECT (struct suspend/3) %> 1<NL> ['SUSP-1-susp'|_244] - _244 INSPECT (-/2) %> Subterm path: 1, country of capital (2), attr: suspend, inst of suspend (1) %>
In this example, except for the toplevel argument, all the other positions are either have field names or are attributes. This is reflected in the path, for example, country of capital (2) shows that the field name for the selected argument position (2, shown in brackets) is country, and the structure name is capital. For the “position” of the selected attribute (suspend) of the attributed variable C, the path position is shown as attr: suspend.
The debugger commands that affect the print formats in the debugger also affects the printed current subterm. Thus, both the print depth and output mode of the printed subterm can be changed.
The changing of the output modes can have a significant impact on the inspect mode. This is because for terms which are transformed by write macros before they are printed (see chapter 13), different terms can be printed depending on the settings of the output modes. In particular, output transformation is used to hide many of the implementation related extra fields and even term names of many ECLiPSe data structures (such as those used in the finite domain library). For the purposes of inspect subterms, the term that is inspected is always the printed form of the term, and thus changing the output mode can change the term that is being inspected.
Consider the example of looking at the attribute of a finite domain variable:
A{[4..10000000]} INSPECT (attributes 1-suspend 2-fd ) %> 2<NL> [4..10000000] INSPECT (list 1-head 2-tail) %> 1<NL> 4..10000000 INSPECT (../2) %> 2up subterm A{[4..10000000]} INSPECT (attributes 1-suspend 2-fd ) %> <o> current output mode is "QPm", toggle char: T new output mode is "TQPm". A{[4..10000000]} INSPECT (attributes 1-suspend 2-fd ) %> 2<NL> fd(dom([4..10000000], 9999997), [], [], []) INSPECT (struct fd/4) %> 1<NL> dom([4..10000000], 9999997) INSPECT (dom/2) %>
After selecting the output mode T, which turns off any output macros, the internal form of the attribute is shown. This allows previously hidden fields of the attribute to be examined by the subterm navigation. Note that if the current subterm is inside a structure which will be changed by a changed output mode (such as inside the fd attribute), and the output mode is changed, then until the current subterm is moved out of the structure, the existing subterm path is still applicable.
Also, after a change in output modes, the current subterm will still be examining the structure that it obtained from the parent subterm. Consider the finite domain variable example again:
4..10000000 INSPECT (../2) %> up subterm [4..10000000] ***** printed structure 1 INSPECT (list 1-head 2-tail) %> <o> current output mode is "QPm", toggle char: T new output mode is "TQPm". [4..10000000] INSPECT (list 1-head 2-tail) %> up subterm A{[4..10000000]} INSPECT (attributes 1-suspend 2-fd ) %> 2 fd(dom([4..10000000], 9999997), [], [], []) INSPECT (struct fd/4) %> <o> current output mode is "QPmT", toggle char: T new output mode is "QPm". fd(4..10000000, [], [], []) ***** printed structure 2 INSPECT (struct fd/4) %>
Printed structures 1 and 2 in the above example are at the same position (toplevel of the finite domain structure), and printed with the same output mode (QPm), but are different because the structure obtained from the parent subterm is different—in printed structure 2, the output mode was not changed until after the fd/4 structure was the current subterm.
The following commands allow to change the parameters which influence the way the tracing information is displayed or processed.
...
.
Note that the debugger has a private print_depth setting with
default 5, which is different from the global setting obtained from
get_flag/2.(1) 1 CALL true %> show module (1) 1 CALL eclipse : true %>
(1) 1 CALL X is length([1, 2, ...]) %> current output mode is "QPm", toggle char: V new output mode is "VQPm". (1) 1 CALL X_72 is length([1, 2, ...]) %> current output mode is "QVPm", toggle char: O new output mode is "OQVPm". (1) 1 CALL is(X_72, length([1, 2, ...])) %> current output mode is "OQVPm", toggle char: . new output mode is ".OQVPm". (1) 1 CALL is(X_72, length(.(1, .(2, .(...))))) %>
Note that the debugger does not check for spy points that occur inside skipped procedures or during the execution of any other skip command than the leap command l.