5.5 Commands Available during Debugging

This section describes the particular commands that are available when the system prompts you after printing out a debugging message. All the commands are one or two letter mnemonics, among which some can be optionally followed by an argument. They are read from the standard input stream with any blanks being completely ignored up to the end of the line (<RET>).

While you are typing commands at a given port, the debugger maintains a notion of current frame of the ancestor stack. The “current goal”, referred to by many commands, is the goal of the current frame. The current frame is initially at the bottom of the ancestor stack, but can be moved by certain commands. If the current frame is above the bottom of the stack, the port indicator, displayed in front of the current goal, is replaced by the word Ancestor.

The only command that you really have to remember is ‘h’ (followed by <RET>). This provides help in the form of the following list of available commands.

         RET   creep            c      creep
         l     leap             z      zip
         s     skip             s <i>  skip i
         o     out              o <n>  out n
         q     q-skip           q <i>  q-skip i
         r     retry            r <i>  retry i
         f     fail             f <i>  fail i
         j<p>  jump to port     j<p><i>jump to port i
         d     display          w      write
         p     print            p <n>  print partial
         g     ancestors        g <n>  ancestors n
         t     backtrace        t <n>  backtrace n
         [     frame up         ]      frame down
         [ <i> frame i          ] <i>  frame i
         v     variables        v <i>  variables i
         &     blocked goals    & <n>  nth blocked goal
         n     nodebug          =      debugging
         +     spy this         *      spy conditionally
         -     nospy this       \ <i>  remove brkpoint
         D <i> disable brkpoint E <i>  enable brkpoint
         a     abort            b      break
         @     command          u      unify
         e     raise exception  .      find this
         <     reset printdepth < <n>  set printdepth
         ^     reset subterm    ^ <n>  set subterm
         ?     help             h      help
c
<RET>
creep causes the debugger to single-step to the very next port and print a message. Then if the port is leashed (see Basic Debug), the user is prompted for further interaction. Otherwise, it continues creeping. If leashing is off, creep is the same as leap (see below) except that a complete trace is printed on the standard error stream.
l
leap causes the debugger to resume running your program, only stopping when a spypoint is reached (or when the program terminates). Leaping can thus be used to follow the execution at a higher level than exhaustive tracing. All you need to do is to set spypoints on an evenly spread set of pertinent predicates, and then follow the control flow through these by leaping from one to the other. Debugging information is collected while leaping, so when a spypoint is reached, it is possible to inspect the ancestor goals, or creep into them upon entry to Redo ports.
z
zip is like leap, except no debugging information is being collected while zipping, resulting in significant savings in memory and execution time.
s
skip is only valid for Call and Redo ports. It skips over the entire execution of the predicate. That is, you will not see anything until control comes back to this predicate (at either the Exit port or the Fail port). Skip is particularly useful while creeping since it guarantees that control will be returned after the (possibly complex) execution within the box. If you skip, no message at all will appear until control returns. This includes calls to predicates with spypoints set; they will be masked out during the skip. No debugging information is being collected while skipping.

If you supply an integer argument, this should denote an invocation number of an ancestral goal. The system tries to get you to the Exit or Fail port of the invocation box you have specified.

o
out is a shorthand for skipping to the Exit or Fail port of the immediate ancestor goal. If you supply an integer argument n, it denotes skipping to the Exit or Fail port of the nth ancestor goal.
q
quasi-skip is like a combination of zip and skip: execution stops when either control comes back to this predicate, or a spypoint is reached. No debugging information is being collected while quasi-skipping.

An integer argument can be supplied as for skip.

r
retry can be used at any port (although at the Call port it has no effect). It transfers control back to the Call port of the box. This allows you to restart an invocation when, for example, you find yourself leaving with some weird result. The state of execution is exactly the same as when you originally called, (unless you use side-effects in your program; i.e. asserts etc. will not be undone). When a retry is performed the invocation counter is reset so that counting will continue from the current invocation number regardless of what happened before the retry. This is in accord with the fact that you have, in executional terms, returned to the state before anything else was called.

If you supply an integer argument, this should denote an invocation number of an ancestral goal. The system tries to get you to the Call port of the box you have specified. It does this by continuously failing until it reaches the right place. Unfortunately this process cannot be guaranteed: it may be the case that the invocation you are looking for has been cut out of the search space by cuts (!) in your program. In this case the system fails to the latest surviving Call port before the correct one.

f
fail can be used at any of the four ports (although at the Fail port it has no effect). It transfers control to the Fail port of the box, forcing the invocation to fail prematurely.

If you supply an integer after the command, this is taken as specifying an invocation number and the system tries to get you to the Fail port of the invocation box you have specified. It does this by continuously failing until it reaches the right place. Unfortunately this process cannot be guaranteed: it may be the case that the invocation you are looking for has been cut out of the search space by cuts (!) in your program. In this case the system fails to the latest surviving Fail port before the correct one.

j<p>
jump to port transfers control back to the prescribed port <p>. Here, <p> is one of: ‘c’, ‘e’, ‘r’, ‘f’, standing for Call, Exit, Redo and Fail ports. Takes an optional integer argument, an invocation number.

Jumping to a Call port is the same as retrying it, i.e. ‘jc’ is the same as the ‘r’ debugger command; and similarly ‘jf’ is the same as ‘f’.

The ‘jejump to Exit port command transfers control back to the Exit port of the box. It can be used at a Redo or an Exit port (although at the latter it has no effect). This allows you to restart a computation following an Exit port, which you first leapt over, but because of its unexpected failure you arrived at the Redo port. If you supply an integer argument, this should denote an exact invocation number of an exited invocation present in the backtrace, and then the system will get you to the specified Exit port. The debugger requires here an exact invocation number so that it does not jump too far back in the execution (if an Exit port is not present in the backtrace, it may be be a better choice to jump to the preceding Call port, rather than to continue looking for another Exit port).

The ‘jrjump to Redo port command transfers control back to the Redo port of the box. It can be used at an Exit or a Redo port (although at the latter it has no effect). This allows you to force the goal in question to try to deliver another solution. If you supply an integer argument, this should denote an exact invocation number of an exited invocation present in the backtrace, and then the system will get you to the specified Redo port.

d
display goal displays the current goal using display/1. See Write (below).
p
print goal displays the current goal using print/1. An argument will override the default printdepth, treating 0 as infinity.
w
write goal displays the current goal using writeq/1.
g
print ancestor goals provides you with a list of ancestors to the current goal, i.e. all goals that are hierarchically above the current goal in the calling sequence. You can always be sure of jumping to the Call or Fail port of any goal in the ancestor list (by using retry etc). If you supply an integer n, only that number of ancestors will be printed. That is to say, the last n ancestors will be printed counting back from the current goal. Each entry is displayed just as they would be in a trace message, except the current frame is indicated by a @ in front of the invocation number.
t
print backtrace is the same as the above, but also shows any goals that have exited nondeterminately and their ancestors. This information shows where there are outstanding choices that the program could backtrack to. If you supply an integer n, only that number of goals will be printed.

Ancestors to the current goal are annotated with the ‘Call:’ port, as they have not yet exited, whereas goals that have exited are annotated with the ‘Exit:’ port. You can always be sure of jumping to the Exit or Redo port of any goal shown to be exited in the backtrace listing.

The backtrace is a tree rather than a stack: to find the parent of a given goal with depth indicator d, look for the closest goal above it with depth indicator d-1.

[
frame up: moves the frame up one step. If you supply an argument, it should denote an invocation number of an existing goal.


]
frame down: moves the frame down one step. If you supply an argument, it should denote an invocation number of an existing goal.


v
print variable bindings endeavors to print the variable bindings of the clause containing the current goal. This is available for both compiled and interpreted code, if the source code was originally loaded with the source_info Prolog flag switched on. The coverage is usually better for compiled code. If you supply an argument, it should denote an invocation number of an existing goal.

Just like the top-level, the debugger displays variable bindings as well as any goals that are blocked on a variable found among those bindings, and prompts for the same one-letter commands as the top-level does; see Queries. To return to the debugger, simply type RET.


&
print blocked goals prints a list of the goals that are currently blocked in the current debugging session together with the variable that each such goal is blocked on (see ref-sem-sec). The goals are enumerated from 1 and up. If you supply an integer n, only that goal will be printed. Each entry is preceded by the goal number followed by the variable name.
n
nodebug switches the debugger off. Note that this is the correct way to switch debugging off at a trace point. You cannot use the @ or b commands because they always return to the debugger.
=
debugging outputs information concerning the status of the debugging package. See the built-in predicate debugging/0.
+
spy this sets a plain spypoint on the current goal.
*
spy this conditionally sets a conditional spypoint on the current goal. Prompts for the Conditions, and calls the
          spy(Func, Conditions)

goal, where Func is the predicate spec of the current invocation. For spy/2, see Breakpoint Predicates.

-
nospy this removes all spypoints applicable to the current goal. Equivalent to nospy Func, where Func is the predicate spec of the current invocation.
\
remove this removes the spypoint that caused the debugger to interact at the current port. With an argument n, it removes the breakpoint with identifier n. Equivalent to remove_breakpoints(BID), where BID is the current breakpoint identifier, or the supplied argument (see Breakpoint Predicates).
D
disable this disables the spypoint that caused the debugger to interact at the current port. With an argument n, it disables the breakpoint with identifier n. Equivalent to disable_breakpoints(BID), where BID is the current breakpoint identifier, or the supplied argument (see Breakpoint Predicates).
E
enable this enables all specific spypoints for the predicate at the current port. With an argument n, it enables the breakpoint with identifier n. Equivalent to enable_breakpoints(BID), where BID is the breakpoint identifiers for the current predicate, or the supplied argument (see Breakpoint Predicates).
.
find this outputs information about where the predicate being called is defined.
a
abort causes an abort of the current execution. All the execution states built so far are destroyed and you are put right back at the top-level. (This is the same as the built-in predicate abort/0.)
b
break calls the built-in predicate break/0, thus putting you at a recursive top-level with the execution so far sitting underneath you. When you end the break (^D) you will be reprompted at the port at which you broke. The new execution is completely separate from the suspended one; the invocation numbers will start again from 1 during the break. The debugger is temporarily switched off as you call the break and will be re-switched on when you finish the break and go back to the old execution. However, any changes to the leashing or to spypoints will remain in effect.
@
command gives you the ability to call arbitrary Prolog goals. It is effectively a one-off break (see above). The initial message ‘| :- ’ will be output on the standard error stream, and a command is then read from the standard input stream and executed as if you were at top-level. If the term read is of form Pattern ^ Body, Pattern is unified with the current goal and Body is executed. Please note:
  1. If Body is compound, it should be parenthesized.
  2. If the current goal has a module qualifier, Pattern should not include the module qualifier.


u
unify is available at the Call port and gives you the option of providing a solution to the goal from the standard input stream rather than executing the goal. This is convenient e.g. for providing a “stub” for a predicate that has not yet been written. A prompt will be output on the standard error stream, and the solution is then read from the standard input stream and unified with the goal. If the term read in is of the form Head :- Body, Head will be unified with the current goal, and Body will be executed in its place.
e
raise exception is available at all ports. A prompt will be output on the standard error stream, and an exception term is then read from the standard input stream and raised in the program being debugged.
<
This command, without arguments, resets the printdepth to 10. With an argument of n, the printdepth is set to n, treating 0 as infinity. This command works by changing the value of the debugger_print_options Prolog flag.
^
While at a particular port, a current subterm of the current goal is maintained. It is the current subterm that is displayed, printed, or written when prompting for a debugger command. Used in combination with the printdepth, this provides a means for navigating in the current goal for focusing on the part of interest. The current subterm is set to the current goal when arriving at a new port. This command, without arguments, resets the current subterm to the current goal. With an argument of n (> 0), the current subterm is replaced by its n:th subterm. With an argument of 0, the current subterm is replaced by its parent term. With multiple arguments separated by whitespace, the arguments are applied from left to right.
?
h
help displays the table of commands given above.

The user can define new debugger commands or modify the behavior of the above ones using the user:debugger_command_hook/2 hook predicate, see Breakpoint Predicates.


Send feedback on this subject.