mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-19 15:54:18 +00:00
Estimated hours taken: 16
Branches: main, release
Implement a new mdb command, "condition", which associates a condition with
an existing breakpoint. The condition is a match between a variable live at
the breakpoint, or a part thereof, and a term provided as part of the condition
command. If execution arrives at the breakpoint but the match doesn't have the
required outcome, execution will continue without stopping.
NEWS:
Mention the new capability.
doc/user_guide.texi:
Document the new capability.
runtime/mercury_trace_term.[ch]:
This new module has facilities for converting strings to a structured
representation of terms. The debugger uses this representation for the
term being matched.
runtime/Mmakefile:
Add the new module to the list of modules in the runtime library.
browser/cterm.m:
This new module tests whether a value in the program being debugged
matches a term represented by the data structure defined in
mercury_trace_term.
browser/mdb.m:
Include the new module in the browser library.
trace/mercury_trace_spy.[ch]:
Change the code that checks for breakpoints to check breakpoints'
conditions.
Fix an old bug: set the number of the most recent breakpoint
even when reusing an existing slot.
trace/mercury_trace_vars.c:
Change the code that checks for breakpoints to also evaluate the
condition, if any.
Provide the facilities required to implement conditions. Besides
exporting some previously private functions, this involved breaking up
two existing functions into two pieces each, because condition checking
wanted to reuse only parts of them.
Modify the implementation of the functions manipulating breakpoints
to handle the new parts of spy point structures.
Modify the way we delete spy point structures to make doubly sure
that we don't free memory twice; it is now MR_delete_spy_point that
sets the spy_exists field to FALSE, after checking it.
Give more meaningful names to some variables.
trace/mercury_trace_internal.[ch]:
Implement the condition command.
Conform to the changes in mercury_trace_vars.c
When the condition of a breakpoint cannot be evaluated, print an error
message.
Extend the command parser to support double quotes, since this is now
needed to allow strings in terms in the condition command.
Flush any error messages resulting from an mdb command immediately
after the command. This was useful in debugging the change.
tests/debugger/cond.{m,inp,exp*}:
Add this new test case to test the new capability.
tests/debugger/Mmakefile:
Include the new test case in the list of test cases.
tests/debugger/completion.exp:
tests/debugger/mdb_command_test.inp:
Update to reflect the new command.
tests/debugger/cmd_quote.exp:
Update the error message.
120 lines
3.2 KiB
Mathematica
120 lines
3.2 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2005 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU Library General
|
|
% Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% This module provides a mechanism for matching terms from the running program
|
|
% against terms specified by debugger commands, which are implemented in C in
|
|
% runtime/mercury_trace_term.[ch].
|
|
%
|
|
% Author: zs
|
|
|
|
:- module mdb.cterm.
|
|
|
|
:- interface.
|
|
|
|
:- import_module bool.
|
|
|
|
:- type cterm.
|
|
:- type cargs.
|
|
|
|
% Succeed if and only if the given term matches the given cterm.
|
|
%
|
|
:- pred match_with_cterm(T::in, cterm::in, bool::out) is cc_multi.
|
|
|
|
% Implement deconstruct for cterms.
|
|
%
|
|
:- pred cterm_deconstruct(cterm::in, string::out, cargs::out) is det.
|
|
|
|
% Decompose a list of arguments into the first element and the rest.
|
|
% Fail if the list is empty.
|
|
%
|
|
:- pred cterm_head_tail(cargs::in, cterm::out, cargs::out) is semidet.
|
|
|
|
:- implementation.
|
|
|
|
:- import_module list.
|
|
:- import_module deconstruct.
|
|
:- import_module std_util.
|
|
|
|
:- pragma foreign_decl(c, "
|
|
#include ""mercury_trace_term.h""
|
|
").
|
|
|
|
:- pragma foreign_type(c, cterm, "MR_CTerm", [can_pass_as_mercury_type]).
|
|
:- pragma foreign_type(c, cargs, "MR_CArgs", [can_pass_as_mercury_type]).
|
|
|
|
:- pragma export(match_with_cterm(in, in, out), "ML_BROWSE_match_with_cterm").
|
|
|
|
% Uncomment these and the unsafe_perform_ios below to debug match_with_cterm
|
|
% and its callers in the trace directory.
|
|
% :- import_module io, unsafe.
|
|
% :- pragma promise_pure(match_with_cterm/3).
|
|
|
|
match_with_cterm(Term, CTerm, Match) :-
|
|
deconstruct(Term, include_details_cc, TermFunctor, _, TermArgs),
|
|
cterm_deconstruct(CTerm, CTermFunctor, CTermArgs),
|
|
% impure unsafe_perform_io(io__write_string("comparing <")),
|
|
% impure unsafe_perform_io(io__write_string(TermFunctor)),
|
|
% impure unsafe_perform_io(io__write_string("> to <")),
|
|
% impure unsafe_perform_io(io__write_string(CTermFunctor)),
|
|
% impure unsafe_perform_io(io__write_string(">\n")),
|
|
( TermFunctor = CTermFunctor ->
|
|
match_with_cterms(TermArgs, CTermArgs, Match)
|
|
; CTermFunctor = "_" ->
|
|
Match = yes
|
|
;
|
|
Match = no
|
|
).
|
|
|
|
:- pred match_with_cterms(list(univ)::in, cargs::in, bool::out) is cc_multi.
|
|
|
|
match_with_cterms(UnivArgs, CArgs, Match) :-
|
|
( cterm_head_tail(CArgs, CHead, CTail) ->
|
|
( UnivArgs = [UnivHead | UnivTail] ->
|
|
Head = univ_value(UnivHead),
|
|
match_with_cterm(Head, CHead, MatchHead),
|
|
(
|
|
MatchHead = no,
|
|
Match = no
|
|
;
|
|
MatchHead = yes,
|
|
match_with_cterms(UnivTail, CTail, Match)
|
|
)
|
|
;
|
|
Match = no
|
|
)
|
|
;
|
|
( UnivArgs = [] ->
|
|
Match = yes
|
|
;
|
|
Match = no
|
|
)
|
|
).
|
|
|
|
:- pragma foreign_proc(c,
|
|
cterm_deconstruct(Term::in, Functor::out, Args::out),
|
|
[will_not_call_mercury, promise_pure],
|
|
"
|
|
if (Term == NULL) {
|
|
MR_fatal_error(""cterm_deconstruct: NULL term"");
|
|
}
|
|
|
|
Functor = Term->term_functor;
|
|
Args = Term->term_args;
|
|
").
|
|
|
|
:- pragma foreign_proc(c,
|
|
cterm_head_tail(Args::in, Head::out, Tail::out),
|
|
[will_not_call_mercury, promise_pure],
|
|
"
|
|
if (Args == NULL) {
|
|
SUCCESS_INDICATOR = MR_FALSE;
|
|
} else {
|
|
Head = Args->args_head;
|
|
Tail = Args->args_tail;
|
|
SUCCESS_INDICATOR = MR_TRUE;
|
|
}
|
|
").
|