The operation of the Mercury debugger ‘mdb’ is based on the following concepts.
The user may associate a break point with some events that occur inside a procedure; the invocation condition of the break point says which events these are. The four possible invocation conditions (also called scopes) are:
The effect of a break point depends on the state of the break point.
Neither of these will happen if the break point is disabled.
Every break point has a print list. Every time execution stops at an event that matches the breakpoint, mdb implicitly executes a print command for each element in the breakpoint’s print list. A print list element can be the word ‘goal’, which causes the goal to the printed as if by ‘print goal’; it can be the word ‘*’, which causes all the variables to the printed as if by ‘print *’; or it can be the name or number of a variable, possibly followed (without white space) by a term path, which causes the specified variable or part thereof to the printed as if the element were given as an argument to the ‘print’ command.
When a debugger command steps over some events without user interaction at those events, the strictness of the command controls whether the debugger will stop execution and resume user interaction at events to which a break point with state ‘stop’ applies. By default, the debugger will stop at such events. However, if the debugger is executing a strict command, it will not stop at an event just because a break point in the stop state applies to it.
If the debugger receives an interrupt (e.g. if the user presses control-C), it will stop at the next event regardless of what command it is executing at the time.
When a debugger command steps over some events without user interaction at those events, the print level controls under what circumstances the stepped over events will be printed.
Regardless of the print level, the debugger will print any event that causes execution to stop and user interaction to start.
The debugger maintains a default print level. The initial value of this variable is ‘some’, but this value can be overridden by the user.
Whenever execution stops at an event, the current environment is reset to refer to the stack frame of the call specified by the event. However, the ‘up’, ‘down’ and ‘level’ commands can set the current environment to refer to one of the ancestors of the current call. This will then be the current environment until another of these commands changes the environment yet again or execution continues to another event.
When browsing or printing a term, you can use "^‘n’" to refer to the nth subterm of that term. If the term’s type has named fields, you can use "^‘fname’" to refer to the subterm of the field named ‘fname’. You can use several of these subterm specifications in a row to refer to subterms deep within the original term. For example, when applied to a list, "^2" refers to the tail of the list (the second argument of the list constructor), "^2^2" refers to the tail of the tail of the list, and "^2^2^1" refers to the head of the tail of the tail, i.e. to the third element of the list. You can think of terms as Unix directories, with constants (function symbols of arity zero) being plain files and function symbols of arity greater than zero being directories themselves. Each subterm specification such as "^2" goes one level down in the hierarchy. The exception is the subterm specification "^..", which goes one level up, to the parent of the current directory.
Normally, the only variables from the program accessible in the debugger are the variables in the current environment at the current program point. However, the user can hold variables, causing their values -or selected parts of their values- to stay available for the rest of the debugger session. All the commands that accept variable names also accept the names of held variables; users can ask for a held variable by prefixing the name of the held variable with a dollar sign.
Besides the builtin set of events, the Mercury debugger also supports events defined by the user. Each event appears in the source code of the Mercury program as a call prefixed by the keyword ‘event’, with each argument of the call giving the value of an event attribute. Users can specify the set of user defined events that can appear in a program, and the names, types and order of the attributes of each kind of user defined event, by giving the name of an event set specification file to the compiler when compiling that program. For more details, see User defined events.
Normally, the only variables from the program accessible in the debugger are the variables in the current environment at the current program point. However, if the current event is a user defined event, then the attributes of that event are also available. All the commands that accept variable names also accept the names of attributes; users can ask for an attribute by prefixing the name of the attribute with an exclamation point.
Some debugger commands, e.g. ‘break’, require a parameter that specifies a procedure. The procedure may or may not be a compiler-generated unify, compare or index procedure of a type constructor. If it is, the procedure specification has the following components in the following order:
For other procedures, the procedure specification has the following components in the following order: