[m-dev.] for review: debugging oracle II

Mark Anthony BROWN dougl at cs.mu.OZ.AU
Thu Aug 19 19:27:55 AEST 1999


Hi,

This is a relative diff which addresses most of lee's comments.
See my previous post for an explanation of what things haven't
been addressed yet.

Cheers,
Mark.


Estimated hours taken: 55

This change adds a more sophisticated oracle to the declarative
debugger.  The oracle now tries to remember previous answers and uses
them if available, and only asks the user if there is no other
information.

browser/declarative_oracle.m:
	- Add the type "oracle_assumption", which identifies an
	  internal assumption of the oracle.
	- Add the type "oracle_answer", which the oracle returns to the
	  caller.  This holds either the truth value, or a reason why
	  the truth value cannot be given yet.
	- Implement a knowledge base to store the previous answers.
	  This data structure is designed to be able to store arbitrary
	  assertions, although at this stage only one kind of assertion
	  is used.
	- Where possible, use the KB to answer questions, instead of
	  asking the user.
	- Update comments.

browser/declarative_debugger.m:
	- Use the new interface to the oracle.  Handle "don't know"
	  answers in a simple way: either save the question and ask it
	  later or return without finding any bug.
	- Move the debugger_command type to this module.
	- Move the UI stuff to a new module.

browser/declarative_user.m:
	New module to handle interaction between the debugger/oracle
	and the user.

tests/debugger/declarative/Mmakefile:
tests/debugger/declarative/oracle_db.{m,inp,exp}
	Add a test case for the new feature.

--- ../../../oracle/mercury/browser/browser_library.m	Mon Apr 12 14:11:40 1999
+++ browser_library.m	Thu Aug 19 16:21:26 1999
@@ -13,7 +13,8 @@
 :- implementation.
 
 :- import_module browse, frame, help, parse, util.
-:- import_module debugger_interface, declarative_debugger, declarative_oracle.
+:- import_module debugger_interface.
+:- import_module declarative_debugger, declarative_oracle, declarative_user.
 :- import_module interactive_query, dl, name_mangle.
 
 % See library/library.m for why we implement this predicate this way.
--- ../../../oracle/mercury/browser/declarative_debugger.m	Wed Aug 11 17:43:39 1999
+++ declarative_debugger.m	Thu Aug 19 18:37:10 1999
@@ -36,7 +36,7 @@
 	%
 	% Values of this type represent EDT nodes.  This representation
 	% is used by the front end (in this module), as well as the
-	% oracle (in browser/declarative_oracle.m).
+	% oracle and user interface.
 	%
 	% There will be nodes other than wrong_answer in future, such
 	% as for missing answer analysis.
@@ -50,11 +50,17 @@
 	--->	wrong_answer(string, list(univ)).
 
 	%
-	% Display the node in user readable form on the current
-	% output stream.
+	% These are the responses the user can give.
 	%
-:- pred write_node(edt_node, io__state, io__state).
-:- mode write_node(in, di, uo) is det.
+:- type debugger_command
+	--->	yes			% The node is correct.
+	;	no			% The node is incorrect.
+	;	inadmissible		% The node is inadmissible.
+	;	do_not_know		% The user has no answer.
+	;	browse			% Browse the data before answering.
+	;	tree			% Browse the EDT.
+	;	help			% Request help before answering.
+	;	illegal_command.	% None of the above.
 
 	%
 	% See comments above.
@@ -75,6 +81,7 @@
 
 :- implementation.
 :- import_module require, int, char.
+:- import_module declarative_user.
 
 	%
 	% This section defines the Mercury instance of the evaluation
@@ -249,18 +256,14 @@
 	{ edt_root(EDT, RootNode) },
 	query_oracle(RootNode, Answer, Oracle0, Oracle1),
 	(
-		%
-		% XXX We don't record the assumption used.  It is not
-		% used by the back end anyway.
-		%
-		{ Answer = known(yes, _) },
+		{ Answer = truth_value(yes) },
 		{ Bug = not_found },
 		{ Oracle = Oracle1 }
 	;
-		{ Answer = known(no, _) },
+		{ Answer = truth_value(no) },
 		analyse_edt_2(EDT, Bug, Oracle1, Oracle)
 	;
-		{ Answer = not_known },
+		{ Answer = deferred(_) },
 		{ Bug = not_found },
 		{ Oracle = Oracle1 }
 	),
@@ -292,17 +295,13 @@
 	{ edt_root(Child, ChildNode) },
 	query_oracle(ChildNode, Answer, Oracle0, Oracle1),
 	(
-		%
-		% XXX we currently don't record the assumption used.
-		% See comment above.
-		%
-		{ Answer = known(yes, _) },
+		{ Answer = truth_value(yes) },
 		analyse_children(Children, Bug0, Bug, Oracle1, Oracle)
 	;
-		{ Answer = known(no, _) },
+		{ Answer = truth_value(no) },
 		analyse_edt_2(Child, Bug, Oracle1, Oracle)
 	;
-		{ Answer = not_known },
+		{ Answer = deferred(_) },
 		{ append(Children, [Child], NewChildren) },
 		analyse_children(NewChildren, Bug0, Bug, Oracle1, Oracle)
 	).
@@ -349,31 +348,5 @@
 
 write_root_node(EDT) -->
 	{ edt_root(EDT, RootNode) },
-	write_node(RootNode).
-
-
-write_node(Node) -->
-	{ Node = wrong_answer(Name, Args) },
-	io__write_string(Name),
-	(
-		{ Args = [Arg1 | Args0] }
-	->
-		io__write_char('('),
-		io__print(Arg1),
-		write_args_rest(Args0),
-		io__write_char(')')
-	;
-		[]
-	).
-
-
-:- pred write_args_rest(list(univ), io__state, io__state).
-:- mode write_args_rest(in, di, uo) is det.
-
-write_args_rest([]) -->
-	[].
-write_args_rest([Arg | Args]) -->
-	io__write_string(", "),
-	io__print(Arg),
-	write_args_rest(Args).
+	write_edt_node(RootNode).
 
--- ../../../oracle/mercury/browser/declarative_oracle.m	Wed Aug 11 17:58:12 1999
+++ declarative_oracle.m	Thu Aug 19 19:00:52 1999
@@ -11,16 +11,15 @@
 % information about the intended interpretation of the program being
 % debugged.
 %
-% The module has two sub-components, the knowledge base and the user
-% interface.  The knowledge base is a cache for all the assumptions
-% that the oracle is currently making.  When the oracle is queried,
-% it first checks the KB to see if an answer is available there.
+% The module has a knowledge base as a sub-component.  This is a cache
+% for all the assumptions that the oracle is currently making.  When
+% the oracle is queried, it first checks the KB to see if an answer
+% is available there.
 %
-% The user interface is the means by which a query can be forwarded
-% to the user.  If no answer is available in the KB, then the oracle
-% uses the UI to get the required answer from the user.  Before
-% returning the answer, the new knowledge is added to the KB so the
-% user will not be asked the same question twice.
+% If no answer is available in the KB, then the oracle uses the UI 
+% (in browser/declarative_user.m) to get the required answer from the
+% user.  If any new knowledge is obtained, it is added to the KB so
+% the user will not be asked the same question twice.
 %
 
 :- module declarative_oracle.
@@ -35,17 +34,13 @@
 :- type oracle_state.
 
 	%
-	% The identifier of an assumption used by the oracle.
-	%
-:- type oracle_assumption.
-
-	%
-	% A response that the oracle gives to the caller.  If the
-	% answer is known, the assumption used is also returned.
+	% A response that the oracle gives to the caller.  This is
+	% a truth value, if available, or else an indication of why
+	% the query cannot be answered yet.
 	%
 :- type oracle_answer
-	--->	known(edt_truth, oracle_assumption)
-	;	not_known.
+	--->	truth_value(edt_truth)
+	;	deferred(debugger_command).
 
 	%
 	% Query the oracle about the program being debugged.  The first
@@ -67,7 +62,7 @@
 
 :- implementation.
 :- import_module bool, list, char, require, std_util, string, map.
-:- import_module util, browse.
+:- import_module declarative_user, util, browse.
 
 :- type oracle_state
 	--->	oracle(
@@ -91,25 +86,23 @@
 
 query_oracle(Node, Answer, Oracle0, Oracle) -->
 	(
-		{ query_oracle_kb(Node, Oracle0, KBTruth, KBAssumption) }
+		{ query_oracle_kb(Node, Oracle0, KBTruth, _KBAssumption) }
 	->
-		{ Answer = known(KBTruth, KBAssumption) },
+		{ Answer = truth_value(KBTruth) },
 		{ Oracle = Oracle0 }
 	;
-		query_user(Node, MaybeTruth),
+		query_user(Node, Answer),
 		{
-			MaybeTruth = yes(Truth),
+			Answer = truth_value(Truth),
 			%
 			% We don't need to check the consistency of this
 			% assertion because we only get here if the KB
 			% didn't know the answer already.
 			%
-			add_oracle_assumption(Node, Truth, Assumption,
-					Oracle0, Oracle),
-			Answer = known(Truth, Assumption)
+			add_oracle_assumption(Node, Truth, _Assumption,
+					Oracle0, Oracle)
 		;
-			MaybeTruth = no,
-			Answer = not_known,
+			Answer = deferred(_),
 			Oracle = Oracle0
 		}
 	).
@@ -179,106 +172,4 @@
 oracle_kb_init(oracle_kb(NodeMap)) :-
 	map__init(NodeMap).
 
-
-%-----------------------------------------------------------------------------%
-
-	%
-	% This section 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.
-	%
-
-	%
-	% These are the responses the user can give.
-	%
-:- type debugger_command
-	--->	yes			% The node is valid.
-	;	no			% The node is invalid.
-	;	do_not_know		% The user has no answer.
-	;	browse			% Browse the data before answering.
-	;	tree			% Browse the EDT.
-	;	help			% Request help before answering.
-	;	illegal_command.	% None of the above.
-
-
-:- pred query_user(edt_node, maybe(edt_truth), io__state, io__state).
-:- mode query_user(in, out, di, uo) is det.
-
-query_user(Node, MaybeTruth) -->
-	write_node(Node),
-	io__nl,
-	get_command("Valid? ", Command),
-	(
-		{ Command = yes },
-		{ MaybeTruth = yes(yes) }
-	;
-		{ Command = no },
-		{ MaybeTruth = yes(no) }
-	;
-		{ Command = do_not_know },
-		{ MaybeTruth = no }
-	;
-		{ Command = browse },
-		io__write_string("Sorry, not implemented.\n"),
-		query_user(Node, MaybeTruth)
-	;
-		{ Command = tree },
-		io__write_string("Sorry, not implemented.\n"),
-		query_user(Node, MaybeTruth)
-	;
-		{ Command = help },
-		io__write_strings([
-			"According to the intended interpretation",
-			" of the program, answer one of:\n",
-			"\ty\tyes\n",
-			"\tn\tno\n",
-			"\td\tdon't know\n",
-%			"\tb\tbrowse the atom arguments (not yet)\n",
-%			"\tt\tprint the evaluation tree (not yet)\n",
-			"\th, ?\tthis help message\n"
-		]),
-		query_user(Node, MaybeTruth)
-	;
-		{ Command = illegal_command },
-		io__write_string("Unknown command, 'h' for help.\n"),
-		query_user(Node, MaybeTruth)
-	).
-
-
-:- pred get_command(string, debugger_command, io__state, io__state).
-:- mode get_command(in, out, di, uo) is det.
-
-get_command(Prompt, Command) -->
-	util__trace_getline(Prompt, Result),
-	( { Result = ok(String) },
-		{ string__to_char_list(String, Line) },
-		{
-			command_chars(Line, Command0)
-		->
-			Command = Command0
-		;
-			Command = illegal_command
-		}
-	; { Result = error(Error) },
-		{ io__error_message(Error, Msg) },
-		io__write_string(Msg),
-		io__nl,
-		get_command(Prompt, Command)
-	; { Result = eof },
-		% XXX this should definitely be handled better.
-		{ Command = illegal_command }
-	).
-
-
-:- pred command_chars(list(char), debugger_command).
-:- mode command_chars(in, out) is semidet.
-
-command_chars(['y' | _], yes).
-command_chars(['n' | _], no).
-command_chars(['d' | _], do_not_know).
-command_chars(['b' | _], browse).
-command_chars(['t' | _], tree).
-command_chars(['h' | _], help).
-command_chars(['?' | _], help).


New file: browser/declarative_user.m

%-----------------------------------------------------------------------------%
% Copyright (C) 1999 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.
%-----------------------------------------------------------------------------%
% File: declarative_user.m
% Author: Mark Brown
% Purpose:
% 	This module performs all the user interaction of the front
% end of the declarative debugger.  It is responsible for displaying
% edt_nodes in a human-readable format, and for getting responses to
% debugger queries from the user.
%

:- module declarative_user.
:- interface.
:- import_module declarative_debugger, declarative_oracle.

	%
	% 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.
	%

:- pred query_user(edt_node, oracle_answer, io__state, io__state).
:- mode query_user(in, out, di, uo) is det.

	%
	% Display the node in user readable form on the current
	% output stream.
	%
:- pred write_edt_node(edt_node, io__state, io__state).
:- mode write_edt_node(in, di, uo) is det.

%-----------------------------------------------------------------------------%

:- implementation.
:- import_module util.
:- import_module std_util, io, bool, list, char, string.

query_user(Node, Answer) -->
	write_edt_node(Node),
	io__nl,
	get_command("Valid? ", Command),
	(
		{ Command = yes },
		{ Answer = truth_value(yes) }
	;
		{ Command = no },
		{ Answer = truth_value(no) }
	;
		{ Command = inadmissible },
		io__write_string("Sorry, not implemented.\n"),
		query_user(Node, Answer)
	;
		{ Command = do_not_know },
		{ Answer = deferred(do_not_know) }
	;
		{ Command = browse },
		io__write_string("Sorry, not implemented.\n"),
		query_user(Node, Answer)
	;
		{ Command = tree },
		io__write_string("Sorry, not implemented.\n"),
		query_user(Node, Answer )
	;
		{ Command = help },
		io__write_strings([
			"According to the intended interpretation",
			" of the program, answer one of:\n",
			"\ty\tyes\n",
			"\tn\tno\n",
%			"\ti\tinadmissible (not yet)\n",
			"\td\tdon't know\n",
%			"\tb\tbrowse the atom arguments (not yet)\n",
%			"\tt\tprint the evaluation tree (not yet)\n",
			"\th, ?\tthis help message\n"
		]),
		query_user(Node, Answer )
	;
		{ Command = illegal_command },
		io__write_string("Unknown command, 'h' for help.\n"),
		query_user(Node, Answer)
	).


:- pred get_command(string, debugger_command, io__state, io__state).
:- mode get_command(in, out, di, uo) is det.

get_command(Prompt, Command) -->
	util__trace_getline(Prompt, Result),
	( { Result = ok(String) },
		{ string__to_char_list(String, Line) },
		{
			command_chars(Line, Command0)
		->
			Command = Command0
		;
			Command = illegal_command
		}
	; { Result = error(Error) },
		{ io__error_message(Error, Msg) },
		io__write_string(Msg),
		io__nl,
		get_command(Prompt, Command)
	; { Result = eof },
		% XXX this should definitely be handled better.
		{ Command = illegal_command }
	).


:- pred command_chars(list(char), debugger_command).
:- mode command_chars(in, out) is semidet.

command_chars(['y' | _], yes).
command_chars(['n' | _], no).
command_chars(['i' | _], inadmissible).
command_chars(['d' | _], do_not_know).
command_chars(['b' | _], browse).
command_chars(['t' | _], tree).
command_chars(['h' | _], help).
command_chars(['?' | _], help).


write_edt_node(Node) -->
	{ Node = wrong_answer(Name, Args) },
	io__write_string(Name),
	(
		{ Args = [Arg1 | Args0] }
	->
		io__write_char('('),
		io__print(Arg1),
		write_args_rest(Args0),
		io__write_char(')')
	;
		[]
	).


:- pred write_args_rest(list(univ), io__state, io__state).
:- mode write_args_rest(in, di, uo) is det.

write_args_rest([]) -->
	[].
write_args_rest([Arg | Args]) -->
	io__write_string(", "),
	io__print(Arg),
	write_args_rest(Args).

-- 
Mark Brown, PhD student            )O+  |  "Another of Fortran's breakthroughs
(m.brown at cs.mu.oz.au)                   |  was the GOTO statement, which was...
Dept. of Computer Science and Software  |  uniquely simple and understandable"
Engineering, University of Melbourne    |              -- IEEE, 1994
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list