[m-rev.] for review: allow dd answers to be revised

Mark Brown dougl at cs.mu.OZ.AU
Mon Nov 11 11:32:15 AEDT 2002


Hi,

This is that change that I mentioned in a recent meeting I was working
on.  The change overcomes what (IMHO) is the biggest drawback of using
the declarative debugger -- the fact that if you give an answer to a
question, it is imperative that the answer is correct.  Currently
answers are never revisited, so if an incorrect answer is given the
user generally needs to start the debugging session from scratch and any
effort made so far will have been wasted.  After this change inconsistencies
will be detected, and the user will be given the chance to correct any
answers whose incorrectness impedes the diagnosis.

The reason this change is so significant is that it allows users to be a
lot more cavalier when it comes to answering questions, because the cost
of getting an answer wrong is greatly reduced.  For example, a typical
scenario is that the user is shown a correct node which contains some
large data structure.  The user may have a strong intuition that the data
structure has nothing to do with the bug, say, 90 percent certainty, but
in order to say the node is definitely correct the user really needs to
browse the whole of it, which may take a long time.  After this change,
however, the user may act on that intuition because the cost of getting an
answer wrong and having to revise it is now much more likely to be less
than the cost of ensuring the answer is correct in the first place.

This is a major change to the declarative debugger, so I wasn't planning
to commit it for the current release.  I'll hold off committing it until
after the freeze ends, assuming it passes review.

Cheers,
Mark.

Estimated hours taken: 60
Branches: main

Allow users of the declarative debugger to revise answers that they
have given previously.  We do this by modifying the user interface
to allow a default answer to be shown as part of the question; the
default answer will always be some answer the user has given previously,
which they can choose to either change or accept as is.  Initially no
questions will be candidates for revision, but if the user ever rejects
a diagnosis, some or all of the questions leading directly to the bug in
question will be asked again.

Add an empty command to the user_command type, for when the user just
presses return.  If there is a default answer, the empty command is
interpreted as that answer.  If there is no default answer, the empty
command is interpreted as the skip command, which allows the user to
cycle through all the available questions by repeatedly pressing return.

browser/declarative_debugger.m:
	Define the type decl_evidence which represents the evidence
	collected against a particular suspect.

	Pass the evidence to the oracle as required.

	Ensure the analyser is updated after the user rejects a diagnosis.

browser/declarative_analyser.m:
	Collect the evidence against the prime suspect as the answers are
	processed, and include this evidence when the analyser response
	is a bug.

	Export the predicate revise_analysis/4 which updates the
	analyser state after the user has rejected a diagnosis.

	Pass the IO action map to prime_suspect_get_evidence so that
	edt_root_question can be called.

browser/declarative_oracle.m:
	When the user rejects a bug, retract from the oracle's knowledge
	base any of the evidence which implicated that bug.  Rather than
	throw this information away, we assert it in a secondary knowledge
	base which is consulted when we want to know if there should be
	a default answer provided to the user.

	Update the oracle_state to reflect the above change, and remove
	all the get_* and set_* predicates for the oracle state.  That
	functionality is provided by labelled fields, so maintaining the
	get_* and set_* predicates is no longer worth the trouble.

	Add the predicate retract_oracle_kb/3 to remove information from
	a knowledge base.

	Use the correct (equivalence) type for exceptions.

browser/declarative_user.m:
	Add the type user_question, which may be a plain decl_question or
	may be a decl_question with a default answer.  Use this type in
	query_user* instead of decl_question.

	Write the command handling switch as a separate predicate.  This
	makes it easier for one command to emulate others (e.g. the empty
	command).

	If the question has a default answer, print it as part of the
	prompt.

	Parse the empty command.

doc/user_guide.texi:
	Update the documentation to reflect the changes.

library/list.m:
	Add a cc_multi version of list__map.

tests/debugger/declarative/Mmakefile:
tests/debugger/declarative/empty_command.exp:
tests/debugger/declarative/empty_command.inp:
tests/debugger/declarative/empty_command.m:
tests/debugger/declarative/revise.exp:
tests/debugger/declarative/revise.inp:
tests/debugger/declarative/revise.m:
tests/debugger/declarative/revise_2.exp:
tests/debugger/declarative/revise_2.inp:
tests/debugger/declarative/revise_2.m:
	Test cases for the new features.

Index: browser/declarative_analyser.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_analyser.m,v
retrieving revision 1.13
diff -u -r1.13 declarative_analyser.m
--- browser/declarative_analyser.m	13 Sep 2002 04:17:39 -0000	1.13
+++ browser/declarative_analyser.m	3 Nov 2002 05:43:42 -0000
@@ -100,9 +100,10 @@
 			%
 	--->	no_suspects
 	
-			% A suspect who is guilty.
+			% A suspect who is guilty, along with the evidence
+			% against the suspect.
 			%
-	;	bug_found(decl_bug)
+	;	bug_found(decl_bug, decl_evidence(T))
 
 			% The analyser desires answers to any of a list
 			% of queries.
@@ -136,6 +137,12 @@
 	analyser_response(T)::out, analyser_state(T)::in,
 	analyser_state(T)::out) is det <= mercury_edt(S, T).
 
+	% Revise the current analysis.  This is done when a bug determined
+	% by the analyser has been overruled by the oracle.
+	%
+:- pred revise_analysis(S::in, analyser_response(T)::out, analyser_state(T)::in,
+	analyser_state(T)::out) is det <= mercury_edt(S, T).
+
 	% Return information within the analyser state that is intended for
 	% debugging the declarative debugger itself.
 	%
@@ -277,6 +284,48 @@
 		Analyser = Analyser2
 	).
 
+revise_analysis(Store, Response, Analyser0, Analyser) :-
+	IoActionMap = Analyser0 ^ io_action_map,
+	(
+		Analyser0 ^ maybe_prime = yes(Prime0)
+	->
+		prime_suspect_get_suspect(Prime0, Suspect0),
+		edt_root_question(IoActionMap, Store, Suspect0, Question)
+	;
+		throw(internal_error("revise_analysis", "no prime suspect"))
+	),
+	Previous0 = Analyser0 ^ previous,
+	(
+		Previous0 = [],
+		Previous = [],
+		MaybePrime = no,
+		SuspectRoots = [Question],
+		SuspectParents = [],
+		PrioritySuspects = []
+	;
+		Previous0 = [MostRecent | Previous],
+		create_prime_suspect(MostRecent, Prime),
+		MaybePrime = yes(Prime),
+		(
+			edt_children(Store, MostRecent, Children)
+		->
+			list__map(edt_root_question(IoActionMap, Store),
+				Children, SuspectRoots),
+			SuspectParents = []
+		;
+			SuspectRoots = [],
+			SuspectParents = [MostRecent]
+		),
+		PrioritySuspects = [Question]
+	),
+	Analyser = ((((Analyser0
+			^ maybe_prime := MaybePrime)
+			^ previous := Previous)
+			^ suspect_roots := SuspectRoots)
+			^ suspect_parents := SuspectParents)
+			^ priority_suspects := PrioritySuspects,
+	decide_analyser_response(Store, Analyser, Response).
+
 %-----------------------------------------------------------------------------%
 
 :- pred assert_suspect_is_correct(S::in, T::in, analyser_state(T)::in,
@@ -288,7 +337,8 @@
 	Analyser1 = Analyser0 ^ suspect_roots := Suspects,
 	PrioritySuspects0 = Analyser1 ^ priority_suspects,
 	delete_suspect(PrioritySuspects0, Suspect, PrioritySuspects),
-	Analyser = Analyser1 ^ priority_suspects := PrioritySuspects.
+	Analyser2 = Analyser1 ^ priority_suspects := PrioritySuspects,
+	add_correct_evidence(Suspect, Analyser2, Analyser).
 
 :- pred assert_suspect_is_wrong(S::in, T::in, analyser_state(T)::in,
 	analyser_state(T)::out) is det <= mercury_edt(S, T).
@@ -349,7 +399,9 @@
 			IoActionMap = Analyser ^ io_action_map,
 			prime_suspect_get_e_bug(IoActionMap, Store, Prime,
 				EBug),
-			Response = bug_found(e_bug(EBug))
+			prime_suspect_get_evidence(IoActionMap, Store, Prime,
+				Evidence),
+			Response = bug_found(e_bug(EBug), Evidence)
 		;
 			Response = no_suspects
 		)
@@ -384,6 +436,21 @@
 		),
 	list__filter(Filter, Suspects0, Suspects).
 
+:- pred add_correct_evidence(T, analyser_state(T), analyser_state(T)).
+:- mode add_correct_evidence(in, in, out) is det.
+
+add_correct_evidence(Suspect, Analyser0, Analyser) :-
+	MaybePrime0 = Analyser0 ^ maybe_prime,
+	(
+		MaybePrime0 = yes(Prime0),
+		prime_suspect_add_evidence(Prime0, Suspect, yes, Prime),
+		MaybePrime = yes(Prime)
+	;
+		MaybePrime0 = no,
+		MaybePrime = no
+	),
+	Analyser = Analyser0 ^ maybe_prime := MaybePrime.
+
 %-----------------------------------------------------------------------------%
 
 :- type prime_suspect(T)
@@ -425,14 +492,16 @@
 	prime_suspect_get_suspect(Prime, Suspect),
 	edt_root_e_bug(IoActionMap, Store, Suspect, EBug).
 
-	% Get all the suspects who are children of the prime suspect,
-	% and who are deemed correct or inadmissible.  Maybe get
-	% the earliest inadmissible child (if there was one).
+	% Get the evidence that implicates the prime suspect.
 	%
-:- pred prime_suspect_get_evidence(prime_suspect(T), list(T), maybe(T)).
-:- mode prime_suspect_get_evidence(in, out, out) is det.
-
-prime_suspect_get_evidence(prime_suspect(_, E, M), E, M).
+:- pred prime_suspect_get_evidence(io_action_map, S, prime_suspect(T),
+	decl_evidence(T)) <= mercury_edt(S, T).
+:- mode prime_suspect_get_evidence(in, in, in, out) is det.
+
+prime_suspect_get_evidence(IoActionMap, Store, Prime, Evidence) :-
+	Prime = prime_suspect(Node, Children, _),
+	Pred = edt_root_question(IoActionMap, Store),
+	list__map(Pred, [Node | Children], Evidence).
 
 	% Add to the evidence against the prime suspect a child who
 	% is deemed correct or inadmissible.
Index: browser/declarative_debugger.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_debugger.m,v
retrieving revision 1.33
diff -u -r1.33 declarative_debugger.m
--- browser/declarative_debugger.m	3 Oct 2002 07:34:25 -0000	1.33
+++ browser/declarative_debugger.m	3 Oct 2002 07:36:12 -0000
@@ -147,6 +147,12 @@
 			%
 	;	suspicious_subterm(T, arg_pos, term_path).
 
+	% The evidence that a certain node is a bug.  This consists of the
+	% smallest set of questions whose answers are sufficient to
+	% diagnose that bug.
+	%
+:- type decl_evidence(T) == list(decl_question(T)).
+
 	% Extract the EDT node from a question.
 	%
 :- func get_decl_question_node(decl_question(T)) = T.
@@ -333,10 +339,10 @@
 handle_analyser_response(_, no_suspects, _, no_bug_found, D, D) -->
 	io__write_string("No bug found.\n").
 
-handle_analyser_response(_, bug_found(Bug), _, Response, Diagnoser0,
-		Diagnoser) -->
+handle_analyser_response(Store, bug_found(Bug, Evidence), _, Response,
+	Diagnoser0, Diagnoser) -->
 
-	confirm_bug(Bug, Response, Diagnoser0, Diagnoser).
+	confirm_bug(Store, Bug, Evidence, Response, Diagnoser0, Diagnoser).
 
 handle_analyser_response(Store, oracle_queries(Queries), MaybeOrigin, Response,
 		Diagnoser0, Diagnoser) -->
@@ -389,25 +395,40 @@
 handle_oracle_response(_, abort_diagnosis, no_bug_found, D, D) -->
 	io__write_string("Diagnosis aborted.\n").
 
-:- pred confirm_bug(decl_bug::in, diagnoser_response::out,
-	diagnoser_state(R)::in, diagnoser_state(R)::out,
-	io__state::di, io__state::uo) is cc_multi.
+:- pred confirm_bug(S::in, decl_bug::in, decl_evidence(T)::in,
+	diagnoser_response::out, diagnoser_state(R)::in,
+	diagnoser_state(R)::out, io__state::di, io__state::uo) is cc_multi
+	<= annotated_trace(S, R).
 
-confirm_bug(Bug, Response, Diagnoser0, Diagnoser) -->
+confirm_bug(Store, Bug, Evidence, Response, Diagnoser0, Diagnoser) -->
 	{ diagnoser_get_oracle(Diagnoser0, Oracle0) },
-	oracle_confirm_bug(Bug, Confirmation, Oracle0, Oracle),
-	{ diagnoser_set_oracle(Diagnoser0, Oracle, Diagnoser) },
-	{
-		Confirmation = confirm_bug,
-		decl_bug_get_event_number(Bug, Event),
-		Response = bug_found(Event)
+	oracle_confirm_bug(Bug, Evidence, Confirmation, Oracle0, Oracle),
+	{ diagnoser_set_oracle(Diagnoser0, Oracle, Diagnoser1) },
+	(
+		{ Confirmation = confirm_bug },
+		{ decl_bug_get_event_number(Bug, Event) },
+		{ Response = bug_found(Event) },
+		{ Diagnoser = Diagnoser1 }
 	;
-		Confirmation = overrule_bug,
-		Response = no_bug_found
+		{ Confirmation = overrule_bug },
+		overrule_bug(Store, Response, Diagnoser1, Diagnoser)
 	;
-		Confirmation = abort_diagnosis,
-		Response = no_bug_found
-	}.
+		{ Confirmation = abort_diagnosis },
+		{ Response = no_bug_found },
+		{ Diagnoser = Diagnoser1 }
+	).
+
+:- pred overrule_bug(S::in, diagnoser_response::out, diagnoser_state(R)::in,
+	diagnoser_state(R)::out, io__state::di, io__state::uo) is cc_multi
+	<= annotated_trace(S, R).
+
+overrule_bug(Store, Response, Diagnoser0, Diagnoser) -->
+	{ Analyser0 = Diagnoser0 ^ analyser_state },
+	{ revise_analysis(wrap(Store), AnalyserResponse, Analyser0, Analyser) },
+	{ Diagnoser1 = Diagnoser0 ^ analyser_state := Analyser },
+	{ debug_analyser_state(Analyser, MaybeOrigin) },
+	handle_analyser_response(Store, AnalyserResponse, MaybeOrigin,
+		Response, Diagnoser1, Diagnoser).
 
 %-----------------------------------------------------------------------------%
 
Index: browser/declarative_oracle.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_oracle.m,v
retrieving revision 1.18
diff -u -r1.18 declarative_oracle.m
--- browser/declarative_oracle.m	15 Oct 2002 07:40:40 -0000	1.18
+++ browser/declarative_oracle.m	3 Nov 2002 02:02:11 -0000
@@ -56,11 +56,13 @@
 	oracle_state::in, oracle_state::out, io__state::di, io__state::uo)
 	is cc_multi.
 
-	% Confirm that the node found is indeed an e_bug or an i_bug.
+	% Confirm that the node found is indeed an e_bug or an i_bug.  If
+	% the bug is overruled, force the oracle to forget everything
+	% it knows about the evidence that led to that bug.
 	%
-:- pred oracle_confirm_bug(decl_bug::in, decl_confirmation::out,
-	oracle_state::in, oracle_state::out, io__state::di, io__state::uo)
-	is cc_multi.
+:- pred oracle_confirm_bug(decl_bug::in, decl_evidence(T)::in,
+	decl_confirmation::out, oracle_state::in, oracle_state::out,
+	io__state::di, io__state::uo) is cc_multi.
 
 %-----------------------------------------------------------------------------%
 
@@ -69,74 +71,118 @@
 :- import_module bool, std_util, set.
 
 query_oracle(Questions, Response, Oracle0, Oracle) -->
-	{ get_oracle_kb(Oracle0, KB0) },
-	{ query_oracle_kb_list(KB0, Questions, Answers) },
+	{ query_oracle_kb_list(Oracle0 ^ kb_current, Questions, Answers) },
 	(
 		{ Answers = [] }
 	->
-		{ get_oracle_user(Oracle0, User0) },
-		query_user(Questions, UserResponse, User0, User),
-		{
-			UserResponse = user_answer(Question, Answer),
-			assert_oracle_kb(Question, Answer, KB0, KB),
-			Response = oracle_answers([Answer])
-		;
-			UserResponse = no_user_answer,
-			Response = no_oracle_answers,
-			KB = KB0
-		;
-			UserResponse = exit_diagnosis(Node),
-			Response = exit_diagnosis(Node),
-			KB = KB0
-		;
-			UserResponse = abort_diagnosis,
-			Response = abort_diagnosis,
-			KB = KB0
-		},
-		{ set_oracle_kb(Oracle0, KB, Oracle1) },
-		{ set_oracle_user(Oracle1, User, Oracle) }
+		{ list__map(make_user_question(Oracle0 ^ kb_revised),
+			Questions, UserQuestions) },
+		query_oracle_user(UserQuestions, Response, Oracle0, Oracle)
 	;
 		{ Response = oracle_answers(Answers) },
 		{ Oracle = Oracle0 }
 	).
 
-oracle_confirm_bug(Bug, Confirmation, Oracle0, Oracle) -->
-	{ get_oracle_user(Oracle0, User0) },
+:- pred make_user_question(oracle_kb::in, decl_question(T)::in,
+	user_question(T)::out) is cc_multi.
+
+make_user_question(Revised, DeclQuestion, UserQuestion) :-
+	query_oracle_kb(Revised, DeclQuestion, MaybeDeclAnswer),
+	(
+		MaybeDeclAnswer = yes(truth_value(_, DeclTruth))
+	->
+		UserQuestion = question_with_default(DeclQuestion, DeclTruth)
+	;
+		UserQuestion = plain_question(DeclQuestion)
+	).
+
+:- pred query_oracle_user(list(user_question(T))::in, oracle_response(T)::out,
+	oracle_state::in, oracle_state::out, io__state::di, io__state::uo)
+	is cc_multi.
+
+query_oracle_user(Questions, OracleResponse, Oracle0, Oracle) -->
+	{ User0 = Oracle0 ^ user_state },
+	query_user(Questions, UserResponse, User0, User),
+	{
+		UserResponse = user_answer(Question, Answer),
+		OracleResponse = oracle_answers([Answer]),
+		Current0 = Oracle0 ^ kb_current,
+		Revised0 = Oracle0 ^ kb_revised,
+		retract_oracle_kb(Question, Revised0, Revised),
+		assert_oracle_kb(Question, Answer, Current0, Current),
+		Oracle1 = (Oracle0
+				^ kb_current := Current)
+				^ kb_revised := Revised
+	;
+		UserResponse = no_user_answer,
+		OracleResponse = no_oracle_answers,
+		Oracle1 = Oracle0
+	;
+		UserResponse = exit_diagnosis(Node),
+		OracleResponse = exit_diagnosis(Node),
+		Oracle1 = Oracle0
+	;
+		UserResponse = abort_diagnosis,
+		OracleResponse = abort_diagnosis,
+		Oracle1 = Oracle0
+	},
+	{ Oracle = Oracle1 ^ user_state := User }.
+
+oracle_confirm_bug(Bug, Evidence, Confirmation, Oracle0, Oracle) -->
+	{ User0 = Oracle0 ^ user_state },
 	user_confirm_bug(Bug, Confirmation, User0, User),
-	{ set_oracle_user(Oracle0, User, Oracle) }.
+	{ Oracle1 = Oracle0 ^ user_state := User },
+	{
+		Confirmation = overrule_bug
+	->
+		list__foldl(revise_oracle, Evidence, Oracle1, Oracle)
+	;
+		Oracle = Oracle1
+	}.
+
+:- pred revise_oracle(decl_question(T)::in, oracle_state::in, oracle_state::out)
+	is cc_multi.
+
+revise_oracle(Question, Oracle0, Oracle) :-
+	Current0 = Oracle0 ^ kb_current,
+	query_oracle_kb(Current0, Question, MaybeAnswer),
+	(
+		MaybeAnswer = yes(Answer),
+		retract_oracle_kb(Question, Current0, Current),
+		Revised0 = Oracle0 ^ kb_revised,
+		assert_oracle_kb(Question, Answer, Revised0, Revised),
+		Oracle = (Oracle0
+				^ kb_revised := Revised)
+				^ kb_current := Current
+	;
+		MaybeAnswer = no,
+		Oracle = Oracle0
+	).
 
 %-----------------------------------------------------------------------------%
 		
 :- type oracle_state
 	--->	oracle(
-			oracle_kb,		% Knowledge base.
-			user_state		% User interface.
+			kb_current	:: oracle_kb,
+				% Current information about the intended
+				% interpretation.  These answers have been
+				% given, but have not since been revised.
+
+			kb_revised	:: oracle_kb,
+				% Old information about the intended
+				% interpretation.  These answers were given
+				% and subsequently revised, but new answers
+				% to the questions have not yet been given.
+
+			user_state	:: user_state
+				% User interface.
 		).
 
 oracle_state_init(InStr, OutStr, Oracle) :-
+	oracle_kb_init(Current),
+	oracle_kb_init(Old),
 	user_state_init(InStr, OutStr, User),
-	oracle_kb_init(KB),
-	Oracle = oracle(KB, User).
-
-:- pred get_oracle_kb(oracle_state, oracle_kb).
-:- mode get_oracle_kb(in, out) is det.
-
-get_oracle_kb(oracle(KB, _), KB).
-
-:- pred set_oracle_kb(oracle_state, oracle_kb, oracle_state).
-:- mode set_oracle_kb(in, in, out) is det.
-
-set_oracle_kb(oracle(_, UI), KB, oracle(KB, UI)).
-
-:- pred get_oracle_user(oracle_state, user_state).
-:- mode get_oracle_user(in, out) is det.
-
-get_oracle_user(oracle(_, UI), UI).
-
-:- pred set_oracle_user(oracle_state, user_state, oracle_state).
-:- mode set_oracle_user(in, in, out) is det.
-
-set_oracle_user(oracle(KB, _), UI, oracle(KB, UI)).
+	Oracle = oracle(Current, Old, User).
 
 %-----------------------------------------------------------------------------%
 
@@ -179,8 +225,8 @@
 
 :- type known_exceptions
 	--->	known_excp(
-			set_cc(univ),		% Possible exceptions.
-			set_cc(univ)		% Impossible exceptions.
+			set_cc(decl_exception),	% Possible exceptions.
+			set_cc(decl_exception)	% Impossible exceptions.
 		).
 
 :- pred oracle_kb_init(oracle_kb).
@@ -340,4 +386,33 @@
 	),
 	tree234_cc__set(Map0, Call, known_excp(Possible, Impossible), Map),
 	set_kb_exceptions_map(KB0, Map, KB).
+
+:- pred retract_oracle_kb(decl_question(T), oracle_kb, oracle_kb).
+:- mode retract_oracle_kb(in, in, out) is cc_multi.
+
+retract_oracle_kb(wrong_answer(_, FinalAtom), KB0, KB) :-
+	Map0 = KB0 ^ kb_ground_map,
+	tree234_cc__delete(Map0, FinalAtom, Map),
+	KB = KB0 ^ kb_ground_map := Map.
+
+retract_oracle_kb(missing_answer(_, InitAtom, _), KB0, KB) :-
+	CompleteMap0 = KB0 ^ kb_complete_map,
+	tree234_cc__delete(CompleteMap0, InitAtom, CompleteMap),
+	KB = KB0 ^ kb_complete_map := CompleteMap.
+
+retract_oracle_kb(unexpected_exception(_, InitAtom, Exception), KB0, KB) :-
+	ExceptionsMap0 = KB0 ^ kb_exceptions_map,
+	tree234_cc__search(ExceptionsMap0, InitAtom, MaybeKnownExceptions0),
+	(
+		MaybeKnownExceptions0 = yes(known_excp(Possible0, Impossible0))
+	->
+		set_cc__delete(Possible0, Exception, Possible),
+		set_cc__delete(Impossible0, Exception, Impossible),
+		KnownExceptions = known_excp(Possible, Impossible),
+		tree234_cc__set(ExceptionsMap0, InitAtom, KnownExceptions,
+			ExceptionsMap)
+	;
+		ExceptionsMap = ExceptionsMap0
+	),
+	KB = KB0 ^ kb_exceptions_map := ExceptionsMap.
 
Index: browser/declarative_user.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_user.m,v
retrieving revision 1.23
diff -u -r1.23 declarative_user.m
--- browser/declarative_user.m	1 Nov 2002 07:44:58 -0000	1.23
+++ browser/declarative_user.m	3 Nov 2002 05:45:02 -0000
@@ -17,6 +17,10 @@
 :- import_module mdb__declarative_debugger.
 :- import_module list, io.
 
+:- type user_question(T)
+	--->	plain_question(decl_question(T))
+	;	question_with_default(decl_question(T), decl_truth).
+
 :- type user_response(T)
 	--->	user_answer(decl_question(T), decl_answer(T))
 	;	no_user_answer
@@ -29,11 +33,11 @@
 :- mode user_state_init(in, in, out) is det.
 
 	% This predicate handles the interactive part of the declarative
-	% debugging process.  The user is presented with an EDT node,
-	% and is asked to respond about the truth of the node in the
-	% intended interpretation.
+	% debugging process.  The user is presented with a question,
+	% possibly with a default answer, and is asked to respond about the
+	% truth of it in the intended interpretation.
 	%
-:- pred query_user(list(decl_question(T))::in, user_response(T)::out,
+:- pred query_user(list(user_question(T))::in, user_response(T)::out,
 	user_state::in, user_state::out, io__state::di, io__state::uo)
 	is cc_multi.
 
@@ -66,101 +70,155 @@
 query_user(Questions, Response, User0, User) -->
 	query_user_2(Questions, [], Response, User0, User).
 
-:- pred query_user_2(list(decl_question(T))::in, list(decl_question(T))::in,
+:- pred query_user_2(list(user_question(T))::in, list(user_question(T))::in,
 	user_response(T)::out, user_state::in, user_state::out,
 	io__state::di, io__state::uo) is cc_multi.
 
 query_user_2([], _, no_user_answer, User, User) -->
 	[].
-query_user_2([Question | Questions], Skipped, Response, User0, User) -->
+query_user_2([UserQuestion | UserQuestions], Skipped, Response, User0, User) -->
+	{ Question = get_decl_question(UserQuestion) },
 	write_decl_question(Question, User0),
-	{ Node = get_decl_question_node(Question) },
-	{ decl_question_prompt(Question, Prompt) },
+	{ user_question_prompt(UserQuestion, Prompt) },
 	get_command(Prompt, Command, User0, User1),
+	handle_command(Command, UserQuestion, UserQuestions, Skipped, Response,
+		User1, User).
+
+:- pred handle_command(user_command::in, user_question(T)::in,
+	list(user_question(T))::in, list(user_question(T))::in,
+	user_response(T)::out, user_state::in, user_state::out,
+	io__state::di, io__state::uo) is cc_multi.
+
+handle_command(yes, UserQuestion, _, _, Response, User, User) -->
+	{ Question = get_decl_question(UserQuestion) },
+	{ Node = get_decl_question_node(Question) },
+	{ Response = user_answer(Question, truth_value(Node, yes)) }.
+
+handle_command(no, UserQuestion, _, _, Response, User, User) -->
+	{ Question = get_decl_question(UserQuestion) },
+	{ Node = get_decl_question_node(Question) },
+	{ Response = user_answer(Question, truth_value(Node, no)) }.
+
+handle_command(inadmissible, UserQuestion, UserQuestions, Skipped, Response,
+		User0, User) -->
+	io__write_string("Sorry, not implemented,\n"),
+	query_user_2([UserQuestion | UserQuestions], Skipped, Response, User0,
+		User).
+
+handle_command(skip, UserQuestion, UserQuestions, Skipped, Response,
+		User0, User) -->
+	query_user_2(UserQuestions, [UserQuestion | Skipped], Response, User0,
+		User).
+
+handle_command(restart, UserQuestion, UserQuestions, Skipped, Response,
+		User0, User) -->
+	{ reverse_and_append(Skipped, [UserQuestion | UserQuestions],
+		RestartedQuestions) },
+	query_user(RestartedQuestions, Response, User0, User).
+
+handle_command(browse_arg(ArgNum), UserQuestion, UserQuestions, Skipped,
+		Response, User0, User) -->
+	{ Question = get_decl_question(UserQuestion) },
+	{ edt_node_trace_atom(Question, TraceAtom) },
+	browse_atom_argument(TraceAtom, ArgNum, MaybeMark, User0, User1),
 	(
-		{ Command = yes },
-		{ Response = user_answer(Question, truth_value(Node, yes)) },
-		{ User = User1 }
+		{ MaybeMark = no },
+		query_user_2([UserQuestion | UserQuestions], Skipped, Response,
+			User1, User)
 	;
-		{ Command = no },
-		{ Response = user_answer(Question, truth_value(Node, no)) },
+		{ MaybeMark = yes(Mark) },
+		{ Which = chosen_head_vars_presentation },
+		{
+			Which = only_user_headvars,
+			ArgPos = user_head_var(ArgNum)
+		;
+			Which = all_headvars,
+			ArgPos = any_head_var(ArgNum)
+		},
+		{ Node = get_decl_question_node(Question) },
+		{ Answer = suspicious_subterm(Node, ArgPos, Mark) },
+		{ Response = user_answer(Question, Answer) },
 		{ User = User1 }
+	).
+
+handle_command(print_arg(From, To), UserQuestion, UserQuestions, Skipped,
+		Response, User0, User) -->
+	{ Question = get_decl_question(UserQuestion) },
+	{ edt_node_trace_atom(Question, TraceAtom) },
+	print_atom_arguments(TraceAtom, From, To, User0),
+	query_user_2([UserQuestion | UserQuestions], Skipped, Response,
+		User0, User).
+
+handle_command(browse_io(ActionNum), UserQuestion, UserQuestions, Skipped,
+		Response, User0, User) -->
+	{ Question = get_decl_question(UserQuestion) },
+	{ edt_node_io_actions(Question, IoActions) },
+	% We don't have code yet to trace a marked I/O action.
+	browse_chosen_io_action(IoActions, ActionNum, _MaybeMark, User0, User1),
+	query_user_2([UserQuestion | UserQuestions], Skipped, Response,
+		User1, User).
+
+handle_command(print_io(From, To), UserQuestion, UserQuestions, Skipped,
+		Response, User0, User) -->
+	{ Question = get_decl_question(UserQuestion) },
+	{ edt_node_io_actions(Question, IoActions) },
+	print_chosen_io_actions(IoActions, From, To, User0),
+	query_user_2([UserQuestion | UserQuestions], Skipped, Response,
+		User0, User).
+
+handle_command(pd, UserQuestion, _, _, Response, User, User) -->
+	{ Question = get_decl_question(UserQuestion) },
+	{ Node = get_decl_question_node(Question) },
+	{ Response = exit_diagnosis(Node) }.
+
+handle_command(abort, _, _, _, Response, User, User) -->
+	{ Response = abort_diagnosis }.
+
+handle_command(help, UserQuestion, UserQuestions, Skipped, Response,
+		User0, User) -->
+	user_help_message(User0),
+	query_user_2([UserQuestion | UserQuestions], Skipped, Response,
+		User0, User).
+
+handle_command(empty_command, UserQuestion, UserQuestions, Skipped, Response,
+		User0, User) -->
+	{
+		UserQuestion = plain_question(_),
+		Command = skip
 	;
-		{ Command = inadmissible },
-		io__write_string("Sorry, not implemented,\n"),
-		query_user_2([Question | Questions], Skipped, Response,
-				User1, User)
-	;
-		{ Command = skip },
-		query_user_2(Questions, [Question | Skipped], Response,
-				User1, User)
-	;
-		{ Command = restart },
-		{ reverse_and_append(Skipped, [Question | Questions],
-				RestartedQuestions) },
-		query_user(RestartedQuestions, Response, User1, User)
-	;
-		{ Command = browse_arg(ArgNum) },
-		{ edt_node_trace_atom(Question, TraceAtom) },
-		browse_atom_argument(TraceAtom, ArgNum, MaybeMark,
-			User1, User2),
+		UserQuestion = question_with_default(_, Truth),
 		(
-			{ MaybeMark = no },
-			query_user_2([Question | Questions], Skipped, Response,
-					User2, User)
+			Truth = yes,
+			Command = yes
 		;
-			{ MaybeMark = yes(Mark) },
-			{ Which = chosen_head_vars_presentation },
-			{
-				Which = only_user_headvars,
-				ArgPos = user_head_var(ArgNum)
-			;
-				Which = all_headvars,
-				ArgPos = any_head_var(ArgNum)
-			},
-			{ Answer = suspicious_subterm(Node, ArgPos, Mark) },
-			{ Response = user_answer(Question, Answer) },
-			{ User = User2 }
+			Truth = no,
+			Command = no
 		)
-	;
-		{ Command = print_arg(From, To) },
-		{ edt_node_trace_atom(Question, TraceAtom) },
-		print_atom_arguments(TraceAtom, From, To, User1),
-		query_user_2([Question | Questions], Skipped, Response,
-			User1, User)
-	;
-		{ Command = browse_io(ActionNum) },
-		{ edt_node_io_actions(Question, IoActions) },
-		% We don't have code yet to trace a marked I/O action.
-		browse_chosen_io_action(IoActions, ActionNum, _MaybeMark,
-			User1, User2),
-		query_user_2([Question | Questions], Skipped, Response,
-			User2, User)
-	;
-		{ Command = print_io(From, To) },
-		{ edt_node_io_actions(Question, IoActions) },
-		print_chosen_io_actions(IoActions, From, To, User1),
-		query_user_2([Question | Questions], Skipped, Response,
-			User1, User)
-	;
-		{ Command = pd },
-		{ Response = exit_diagnosis(Node) },
-		{ User = User1 }
-	;
-		{ Command = abort },
-		{ Response = abort_diagnosis },
-		{ User = User1 }
-	;
-		{ Command = help },
-		user_help_message(User1),
-		query_user_2([Question | Questions], Skipped, Response,
-				User1, User)
-	;
-		{ Command = illegal_command },
-		io__write_string("Unknown command, 'h' for help.\n"),
-		query_user_2([Question | Questions], Skipped, Response,
-				User1, User)
-	).
+	},
+	handle_command(Command, UserQuestion, UserQuestions, Skipped, Response,
+		User0, User).
+
+handle_command(illegal_command, UserQuestion, UserQuestions, Skipped, Response,
+		User0, User) -->
+	io__write_string("Unknown command, 'h' for help.\n"),
+	query_user_2([UserQuestion | UserQuestions], Skipped, Response,
+		User0, User).
+
+:- func get_decl_question(user_question(T)) = decl_question(T).
+
+get_decl_question(plain_question(Q)) = Q.
+get_decl_question(question_with_default(Q, _)) = Q.
+
+:- pred user_question_prompt(user_question(T), string).
+:- mode user_question_prompt(in, out) is det.
+
+user_question_prompt(plain_question(Question), Prompt) :-
+	decl_question_prompt(Question, Prompt).
+
+user_question_prompt(question_with_default(Question, DefaultTruth), Prompt) :-
+	decl_question_prompt(Question, QuestionPrompt),
+	default_prompt(DefaultTruth, DefaultPrompt),
+	string__append(QuestionPrompt, DefaultPrompt, Prompt).
 
 :- pred decl_question_prompt(decl_question(T), string).
 :- mode decl_question_prompt(in, out) is det.
@@ -169,6 +227,12 @@
 decl_question_prompt(missing_answer(_, _, _), "Complete? ").
 decl_question_prompt(unexpected_exception(_, _, _), "Expected? ").
 
+:- pred default_prompt(decl_truth, string).
+:- mode default_prompt(in, out) is det.
+
+default_prompt(yes, "[yes] ").
+default_prompt(no, "[no] ").
+
 :- pred edt_node_trace_atom(decl_question(T)::in, trace_atom::out) is det.
 
 edt_node_trace_atom(wrong_answer(_, FinalDeclAtom),
@@ -346,6 +410,7 @@
 					% this point.
 	;	abort			% Abort this diagnosis session.
 	;	help			% Request help before answering.
+	;	empty_command		% User just pressed return.
 	;	illegal_command.	% None of the above.
 
 :- pred user_help_message(user_state, io__state, io__state).
@@ -397,12 +462,17 @@
 		{ Words = string__words(char__is_whitespace, String) },
 		{
 			Words = [CmdWord | CmdArgs],
-			cmd_handler(CmdWord, CmdHandler),
-			CommandPrime = CmdHandler(CmdArgs)
-		->
-			Command = CommandPrime
+			(
+				cmd_handler(CmdWord, CmdHandler),
+				CommandPrime = CmdHandler(CmdArgs)
+			->
+				Command = CommandPrime
+			;
+				Command = illegal_command
+			)
 		;
-			Command = illegal_command
+			Words = [],
+			Command = empty_command
 		}
 	;
 		{ Result = error(Error) },
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.342
diff -u -r1.342 user_guide.texi
--- doc/user_guide.texi	7 Nov 2002 06:14:11 -0000	1.342
+++ doc/user_guide.texi	9 Nov 2002 11:07:30 -0000
@@ -3334,7 +3334,7 @@
 based on their knowledge of the intended interpretation.
 The debugger provides some help here:
 previous answers are remembered and used where possible,
-so repeat questions are avoided.
+so questions are not repeated unnecessarily.
 Commands are available to provide answers,
 as well as to browse the arguments more closely
 or to change the order in which the questions are asked.
@@ -3366,6 +3366,12 @@
 followed by the exception that was thrown,
 and prints the question @samp{Expected?} for the user to answer.
 
+In some circumstances
+the declarative debugger provides a default answer to the question.
+If this is the case, the default answer will be shown in square brackets
+immediately after the question,
+and simply pressing return is equivalent to giving that answer.
+
 @node Declarative debugging commands
 @subsection Commands
 
@@ -3401,6 +3407,12 @@
 Summarize the list of available commands.
 @end table
 
+It is also legal to press return without specifying a command.
+If there is a default answer (see @ref{Oracle questions}),
+pressing return is equivalent to giving that answer.
+If there is no default answer,
+pressing return is equivalent to the skip command.
+
 @node Diagnoses
 @subsection Diagnoses
 
@@ -3449,17 +3461,25 @@
 After the diagnosis is displayed, the user is asked to confirm
 that the event located by the declarative debugger
 does in fact represent a bug.
-If the user does confirm the diagnosis,
+The user can answer @samp{yes} or @samp{y} to confirm the bug,
+ at samp{no} or @samp{n} to reject the bug,
+or @samp{abort} or @samp{a} to abort the diagnosis.
+
+If the user confirms the diagnosis,
 they are returned to the procedural debugger
 at the event which was found to be the bug event.
 This gives the user an opportunity, if they need it,
 to investigate (procedurally) the events in the neighbourhood of the bug.
-If the user does not confirm the diagnosis,
-which implies that some of their earlier answers must have been mistakes,
+
+If the user rejects the diagnosis,
+which implies that some of their earlier answers may have been mistakes,
+diagnosis is resumed from some earlier point determined by the debugger.
+The user may now be asked questions they have already answered,
+with the previous answer they gave being the default,
+or they may be asked entirely new questions.
+
+If the user aborts the diagnosis,
 they are returned to the event at which the @samp{dd} command was given.
-In the future, users should have the option of
-revising those of their answers which directly led to the diagnosis,
-but the current implementation doesn't do this yet.
 
 @c @node Improving the search
 @c @subsection Improving the search
Index: library/list.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/list.m,v
retrieving revision 1.108
diff -u -r1.108 list.m
--- library/list.m	16 Sep 2002 06:07:45 -0000	1.108
+++ library/list.m	3 Nov 2002 02:07:09 -0000
@@ -433,6 +433,7 @@
 	% to transform the elements of L into the elements of M.
 :- pred list__map(pred(X, Y), list(X), list(Y)).
 :- mode list__map(pred(in, out) is det, in, out) is det.
+:- mode list__map(pred(in, out) is cc_multi, in, out) is cc_multi.
 :- mode list__map(pred(in, out) is semidet, in, out) is semidet.
 :- mode list__map(pred(in, out) is multi, in, out) is multi.
 :- mode list__map(pred(in, out) is nondet, in, out) is nondet.
Index: tests/debugger/declarative/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/declarative/Mmakefile,v
retrieving revision 1.54
diff -u -r1.54 Mmakefile
--- tests/debugger/declarative/Mmakefile	9 Nov 2002 18:49:35 -0000	1.54
+++ tests/debugger/declarative/Mmakefile	9 Nov 2002 18:51:48 -0000
@@ -17,6 +17,7 @@
 	deep_warning		\
 	dependency		\
 	dependency2		\
+	empty_command		\
 	family			\
 	filter			\
 	func_call		\
@@ -37,6 +38,8 @@
 	pd			\
 	propositional		\
 	queens			\
+	revise			\
+	revise_2		\
 	shallow			\
 	small			\
 	solutions		\
@@ -148,6 +151,9 @@
 dependency2.out: dependency2 dependency2.inp
 	$(MDB) ./dependency2 < dependency2.inp > dependency2.out 2>&1
 
+empty_command.out: empty_command empty_command.inp
+	$(MDB) ./empty_command < empty_command.inp > empty_command.out 2>&1
+
 family.out: family family.inp
 	$(MDB) ./family < family.inp > family.out 2>&1
 
@@ -213,6 +219,12 @@
 
 queens.out: queens queens.inp
 	$(MDB) ./queens < queens.inp > queens.out 2>&1
+
+revise.out: revise revise.inp
+	$(MDB) ./revise < revise.inp > revise.out 2>&1
+
+revise_2.out: revise_2 revise_2.inp
+	$(MDB) ./revise_2 < revise_2.inp > revise_2.out 2>&1
 
 shallow.out: shallow shallow.inp
 	$(MDB) ./shallow < shallow.inp > shallow.out 2>&1
Index: tests/debugger/declarative/empty_command.exp
===================================================================
RCS file: tests/debugger/declarative/empty_command.exp
diff -N tests/debugger/declarative/empty_command.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/empty_command.exp	3 Nov 2002 06:16:56 -0000
@@ -0,0 +1,38 @@
+       1:      1  1 CALL pred empty_command:main/2-0 (det) empty_command.m:7
+mdb> echo on
+Command echo enabled.
+mdb> register --quiet
+mdb> break p
+ 0: + stop  interface pred empty_command:p/2-0 (det)
+mdb> continue
+       2:      2  2 CALL pred empty_command:p/2-0 (det) empty_command.m:17 (empty_command.m:8)
+mdb> finish
+       9:      2  2 EXIT pred empty_command:p/2-0 (det) empty_command.m:17 (empty_command.m:8)
+mdb> dd
+p(53, 53)
+Valid? no
+q(53, 53)
+Valid? yes
+r(53, 53)
+Valid? 
+s(53, 53)
+Valid? yes
+r(53, 53)
+Valid? yes
+Found incorrect contour:
+p(53, 53)
+Is this a bug? no
+p(53, 53)
+Valid? [no] 
+q(53, 53)
+Valid? [yes] 
+r(53, 53)
+Valid? [yes] 
+s(53, 53)
+Valid? [yes] 
+Found incorrect contour:
+p(53, 53)
+Is this a bug? yes
+       9:      2  2 EXIT pred empty_command:p/2-0 (det) empty_command.m:17 (empty_command.m:8)
+mdb> continue
+53
Index: tests/debugger/declarative/empty_command.inp
===================================================================
RCS file: tests/debugger/declarative/empty_command.inp
diff -N tests/debugger/declarative/empty_command.inp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/empty_command.inp	3 Nov 2002 06:06:31 -0000
@@ -0,0 +1,18 @@
+echo on
+register --quiet
+break p
+continue
+finish
+dd
+no
+yes
+
+yes
+yes
+no
+
+
+
+
+yes
+continue
Index: tests/debugger/declarative/empty_command.m
===================================================================
RCS file: tests/debugger/declarative/empty_command.m
diff -N tests/debugger/declarative/empty_command.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/empty_command.m	3 Nov 2002 06:16:10 -0000
@@ -0,0 +1,21 @@
+:- module empty_command.
+:- interface.
+:- import_module io.
+:- pred main(io__state::di, io__state::uo) is det.
+:- implementation.
+
+main -->
+	{ p(53, P) },
+	io__write_int(P),
+	io__nl.
+
+:- pred p(int::in, int::out) is det.
+:- pred q(int::in, int::out) is det.
+:- pred r(int::in, int::out) is det.
+:- pred s(int::in, int::out) is det.
+
+p --> q, r, s.
+q --> [].
+r --> [].
+s --> [].
+
Index: tests/debugger/declarative/revise.exp
===================================================================
RCS file: tests/debugger/declarative/revise.exp
diff -N tests/debugger/declarative/revise.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/revise.exp	3 Nov 2002 05:46:59 -0000
@@ -0,0 +1,40 @@
+       1:      1  1 CALL pred revise:main/2-0 (cc_multi) revise.m:8
+mdb> echo on
+Command echo enabled.
+mdb> register --quiet
+mdb> break p
+ 0: + stop  interface pred revise:p/2-0 (multi)
+mdb> continue
+       2:      2  2 CALL pred revise:p/2-0 (multi) revise.m:21 (revise.m:9)
+mdb> finish
+      14:      2  2 EXIT pred revise:p/2-0 (multi) revise.m:21 (revise.m:9)
+mdb> dd
+p("foo", "foo")
+Valid? no
+q("foo", "foo")
+Valid? yes
+r("foo", "foo")
+Valid? no
+a("foo", "foo")
+Valid? yes
+b("foo", "foo")
+Valid? yes
+Found incorrect contour:
+r("foo", "foo")
+Is this a bug? no
+r("foo", "foo")
+Valid? [no] yes
+s("foo", "foo")
+Valid? yes
+Found incorrect contour:
+p("foo", "foo")
+Is this a bug? no
+p("foo", "foo")
+Valid? [no] 
+q("foo", "foo")
+Valid? [yes] no
+Found incorrect contour:
+q("foo", "foo")
+Is this a bug? yes
+       4:      3  3 EXIT pred revise:q/2-0 (det) revise.m:23 (revise.m:21)
+mdb> quit -y
Index: tests/debugger/declarative/revise.inp
===================================================================
RCS file: tests/debugger/declarative/revise.inp
diff -N tests/debugger/declarative/revise.inp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/revise.inp	3 Nov 2002 04:36:56 -0000
@@ -0,0 +1,19 @@
+echo on
+register --quiet
+break p
+continue
+finish
+dd
+no
+yes
+no
+yes
+yes
+no
+yes
+yes
+no
+
+no
+yes
+quit -y
Index: tests/debugger/declarative/revise.m
===================================================================
RCS file: tests/debugger/declarative/revise.m
diff -N tests/debugger/declarative/revise.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/revise.m	3 Nov 2002 03:12:54 -0000
@@ -0,0 +1,31 @@
+:- module revise.
+:- interface.
+:- import_module io.
+:- pred main(io__state::di, io__state::uo) is cc_multi.
+
+:- implementation.
+
+main -->
+	{ p("foo", S) },
+	io__write_string(S),
+	io__nl.
+
+:- pred p(string::in, string::out) is multi.
+:- pred q(string::in, string::out) is det.
+:- pred r(string::in, string::out) is multi.
+:- pred s(string::in, string::out) is det.
+:- pred a(string::in, string::out) is det.
+:- pred b(string::in, string::out) is det.
+:- pred c(string::in, string::out) is det.
+
+p --> q, r, s.
+
+q --> [].
+r --> a, b.
+r --> c.
+s --> [].
+
+a --> [].
+b --> [].
+c --> :=("bar").
+
Index: tests/debugger/declarative/revise_2.exp
===================================================================
RCS file: tests/debugger/declarative/revise_2.exp
diff -N tests/debugger/declarative/revise_2.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/revise_2.exp	3 Nov 2002 06:09:46 -0000
@@ -0,0 +1,27 @@
+       1:      1  1 CALL pred revise_2:main/2-0 (det) revise_2.m:7
+mdb> echo on
+Command echo enabled.
+mdb> register --quiet
+mdb> break p
+ 0: + stop  interface pred revise_2:p/1-0 (det)
+mdb> continue
+       2:      2  2 CALL pred revise_2:p/1-0 (det) revise_2.m:14 (revise_2.m:8)
+mdb> finish
+       3:      2  2 EXIT pred revise_2:p/1-0 (det) revise_2.m:14 (revise_2.m:8)
+mdb> dd
+p(41)
+Valid? no
+Found incorrect contour:
+p(41)
+Is this a bug? no
+p(41)
+Valid? [no] no
+Found incorrect contour:
+p(41)
+Is this a bug? no
+p(41)
+Valid? [no] yes
+No bug found.
+       3:      2  2 EXIT pred revise_2:p/1-0 (det) revise_2.m:14 (revise_2.m:8)
+mdb> continue
+41
Index: tests/debugger/declarative/revise_2.inp
===================================================================
RCS file: tests/debugger/declarative/revise_2.inp
diff -N tests/debugger/declarative/revise_2.inp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/revise_2.inp	3 Nov 2002 06:09:32 -0000
@@ -0,0 +1,12 @@
+echo on
+register --quiet
+break p
+continue
+finish
+dd
+no
+no
+no
+no
+yes
+continue
Index: tests/debugger/declarative/revise_2.m
===================================================================
RCS file: tests/debugger/declarative/revise_2.m
diff -N tests/debugger/declarative/revise_2.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/debugger/declarative/revise_2.m	3 Nov 2002 06:07:40 -0000
@@ -0,0 +1,15 @@
+:- module revise_2.
+:- interface.
+:- import_module io.
+:- pred main(io__state::di, io__state::uo) is det.
+:- implementation.
+
+main -->
+	{ p(X) },
+	io__write_int(X),
+	io__nl.
+
+:- pred p(int::out) is det.
+
+p(41).
+
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list