[m-rev.] for review: display the reason why a question was asked in the dd

Ian MacLarty maclarty at cs.mu.OZ.AU
Sat Mar 12 23:15:10 AEDT 2005


For review by anyone.

Estimated hours taken: 14
Branches: main

Include the reason why a question was asked in the information provided by the
`info' command.  This includes the place where a marked subterm was bound if
the user marked a subterm in the previous question.

browser/declarative_analyser.m
	Add a new type to record the reason why a question was asked.  Keep
	this information with the last question asked in the analyser state, in
	case the user issues an `info' command.  Display the reason when the
	user issues an `info' command.

	Change the behaviour of subterm dependency tracking slightly: if the
	binding node was previously skipped then ask about it anyway.

browser/declarative_edt.m
	Add two new methods to the mercury_edt typeclass.  One to get the
	proc_label of a node and the other to convert an arg_pos to a
	user argument number with respect to an atom in a node.  These
	are needed to display the question reason to the user in
	mdb.declarative_analyser.

	Add a new type to record the primitive operation that bound a subterm.

browser/declarative_execution.m
	Add a predicate to convert an arg_pos into a user arg number.

browser/declarative_oracle.m
	Fix a faulty comment.

browser/declarative_tree.m
	Implement the new methods added to the mercury_edt typeclass.

	Return the type of primitive operation that bound a subterm.

doc/user_guide.texi
	Document the fact that the reason is now also displayed when the
	`info' command is issued.

tests/debugger/declarative/info.exp
tests/debugger/declarative/info.inp
tests/debugger/declarative/info.m
	Test the info command more thoroughly.

Index: browser/declarative_analyser.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_analyser.m,v
retrieving revision 1.21
diff -u -r1.21 declarative_analyser.m
--- browser/declarative_analyser.m	12 Mar 2005 04:46:29 -0000	1.21
+++ browser/declarative_analyser.m	12 Mar 2005 11:54:19 -0000
@@ -21,8 +21,10 @@
 :- import_module mdb.declarative_debugger.
 :- import_module mdb.io_action.
 :- import_module mdb.declarative_edt.
+:- import_module mdbcomp.program_representation.
+:- import_module mdbcomp.prim_data.
 
-:- import_module std_util, io.
+:- import_module std_util, io, bool.
 
 :- type analyser_response(T)
 
@@ -49,6 +51,35 @@
 			% this question and then for analysis to continue.
 	;	revise(decl_question(T)).
 
+	% The reason a question was asked.
+	%
+:- type question_reason
+	--->	start 			% The first question.
+	;	top_down
+	;	binding_node(
+			binding_prim_op		:: primitive_op_type,
+			binding_filename	:: string,	
+			binding_line_no		:: int, 	
+			binding_atom_path	:: term_path,
+			binding_proc		:: proc_label,
+			binding_node_eliminated	:: bool
+		)
+	;	subterm_no_proc_rep	% No proc rep when tracking subterm.
+	;	binding_node_eliminated
+	;	binary(
+			binary_reason_bottom	:: int, 
+			binary_reason_top	:: int, 
+			binary_reason_split	:: int
+		)
+	;	divide_and_query(
+			old_weight		:: int,
+			choosen_subtree_weight 	:: int
+		)
+	;	skipped
+	;	revise.
+
+:- func question_reason_to_string(question_reason) = string.
+
 :- type analyser_state(T).
 
 :- type search_mode.
@@ -124,6 +155,7 @@
 :- implementation.
 
 :- import_module mdb.declarative_edt.
+:- import_module mdb.declarative_execution.
 :- import_module mdbcomp.program_representation.
 
 :- import_module exception, counter, array, list, float.
@@ -213,7 +245,7 @@
 	% which is the root of an implicit subtree.
 	% 
 :- type search_response
-	--->	question(suspect_id)
+	--->	question(suspect_id, question_reason)
 	;	require_explicit_subtree(suspect_id)
 	;	require_explicit_supertree
 	;	no_suspects.
@@ -249,7 +281,7 @@
 				% before asking the oracle, so the analyser
 				% knows how to modify the search space when 
 				% it gets an answer.
-			last_search_question	:: maybe(suspect_id),
+			last_search_question	:: maybe(suspect_and_reason),
 
 				% This field allows us to map I/O action
 				% numbers to the actions themselves.
@@ -263,6 +295,9 @@
 			debug_origin		:: maybe(subterm_origin(T))
 	).
 
+:- type suspect_and_reason
+	--->	suspect_and_reason(suspect_id, question_reason).
+
 :- type explicit_tree_type
 
 			% Generate an explicit subtree for the implicit root
@@ -321,7 +356,7 @@
 			!:Analyser = !.Analyser ^ search_space := SearchSpace,
 			topmost_det(SearchSpace, TopMostId),
 			!:Analyser = !.Analyser ^ last_search_question := 
-				yes(TopMostId),
+				yes(suspect_and_reason(TopMostId, start)),
 			edt_question(!.Analyser ^ io_action_map, Store, Node, 
 				Question),
 			Response = revise(Question)
@@ -333,7 +368,8 @@
 
 continue_analysis(Store, Answer, Response, !Analyser) :-
 	(
-		!.Analyser ^ last_search_question = yes(SuspectId),
+		!.Analyser ^ last_search_question = yes(
+			suspect_and_reason(SuspectId, _)),
 		process_answer(Store, Answer, SuspectId, !Analyser)
 	;
 		!.Analyser ^ last_search_question = no,
@@ -413,7 +449,8 @@
 		Response = revise(Question),
 		revise_root(Store, SearchSpace, SearchSpace1),
 		!:Analyser = !.Analyser ^ search_space := SearchSpace1,
-		!:Analyser = !.Analyser ^ last_search_question := yes(RootId),
+		!:Analyser = !.Analyser ^ last_search_question := 
+			yes(suspect_and_reason(RootId, revise)),
 		!:Analyser = !.Analyser ^ search_mode := 
 			!.Analyser ^ fallback_search_mode
 	;
@@ -466,7 +503,8 @@
 	analyser_state(T)::in, analyser_state(T)::out, 
 	analyser_response(T)::out) is det <= mercury_edt(S, T).
 
-handle_search_response(Store, question(SuspectId), !Analyser, Response) :-
+handle_search_response(Store, question(SuspectId, Reason), !Analyser,
+		Response) :-
 	SearchSpace = !.Analyser ^ search_space,
 	Node = get_edt_node(SearchSpace, SuspectId),
 	edt_question(!.Analyser ^ io_action_map, Store, Node,
@@ -493,7 +531,8 @@
 		% incorrectly before.
 		Response = revise(OracleQuestion)
 	),
-	!:Analyser = !.Analyser ^ last_search_question := yes(SuspectId).
+	!:Analyser = !.Analyser ^ last_search_question := 
+		yes(suspect_and_reason(SuspectId, Reason)).
 
 handle_search_response(_, require_explicit_subtree(SuspectId), !Analyser, 
 		Response) :-
@@ -594,14 +633,14 @@
 		SearchSpace1 = !:SearchSpace,
 		(
 			MaybeDescendent = yes(Unknown),
-			Response = question(Unknown)
+			Response = question(Unknown, top_down)
 		;
 			MaybeDescendent = no,
 			(
 				choose_skipped_suspect(!.SearchSpace,
 					SkippedSuspect)
 			->
-				Response = question(SkippedSuspect)
+				Response = question(SkippedSuspect, skipped)
 			;
 				%
 				% Try to extend the search space upwards.  If
@@ -671,22 +710,34 @@
 	find_subterm_origin(Store, SuspectId, ArgPos, TermPath, !SearchSpace,
 		FindOriginResponse),
 	(
-		FindOriginResponse = primitive_op(PrimitiveOpId, _, _),
-		%
-		% XXX In future the filename and line number of the primitive
-		% operation could be printed out if the node in which the
-		% primitive operation occured turned out to be a bug.
-		%
+		FindOriginResponse = primitive_op(PrimitiveOpId, FileName, 
+			LineNo, PrimOpType),
+		ProcLabel = get_proc_label_for_suspect(Store, !.SearchSpace,
+			PrimitiveOpId),
+		BindingNode = get_edt_node(!.SearchSpace, PrimitiveOpId),
+		ArgNum = edt_arg_pos_to_user_arg_num(Store, BindingNode,
+			ArgPos),
 		(
-			suspect_unknown(!.SearchSpace, PrimitiveOpId)
+			% We ask about the binding node even if it was 
+			% previously skipped, since this behaviour is
+			% more preditable from the user's perspective.
+			%
+			( suspect_unknown(!.SearchSpace, PrimitiveOpId)
+			; suspect_skipped(!.SearchSpace, PrimitiveOpId)
+			)
 		->
-			SearchResponse = question(PrimitiveOpId),
-			setup_binary_search(!.SearchSpace,  PrimitiveOpId,
+			SearchResponse = question(PrimitiveOpId, 
+				binding_node(PrimOpType, FileName, LineNo,
+					[ArgNum | TermPath], ProcLabel, no)),
+			setup_binary_search(!.SearchSpace, PrimitiveOpId,
 				NewMode)
 		;
 			(
 				LastUnknown = yes(Unknown),
-				SearchResponse = question(Unknown),
+				Reason = binding_node(PrimOpType, 
+					FileName, LineNo, [ArgNum | TermPath], 
+					ProcLabel, yes),
+				SearchResponse = question(Unknown, Reason),
 				setup_binary_search(!.SearchSpace, 
 					Unknown, NewMode)
 			;
@@ -694,15 +745,15 @@
 				search(Store, !SearchSpace, FallBackSearchMode, 
 					FallBackSearchMode, NewMode, 
 					SearchResponse)
-				)
+			)
 		)
 	;
 		FindOriginResponse = not_found,
 		(
 			LastUnknown = yes(Unknown),
-			SearchResponse = question(Unknown),
-			setup_binary_search(!.SearchSpace,  
-				Unknown, NewMode)
+			SearchResponse = question(Unknown, 
+				subterm_no_proc_rep),
+			setup_binary_search(!.SearchSpace, Unknown, NewMode)
 		;
 			LastUnknown = no,
 			search(Store, !SearchSpace, FallBackSearchMode, 
@@ -745,7 +796,8 @@
 		->
 			(
 				LastUnknown = yes(Unknown),
-				SearchResponse = question(Unknown),
+				SearchResponse = question(Unknown, 
+					binding_node_eliminated),
 				setup_binary_search(!.SearchSpace,
 					Unknown, NewMode)
 			;
@@ -759,7 +811,7 @@
 			% This recursive call will not lead to an infinite loop
 			% because eventually either the sub-term will be bound
 			% (and find_subterm_origin will respond with
-			% primitive_op/2) or there will be insufficient tracing
+			% primitive_op/3) or there will be insufficient tracing
 			% information to continue (and find_subterm_origin will
 			% respond with not_found).
 			%
@@ -844,7 +896,8 @@
 			NewMode = binary(PathArray, NewTop - NewBottom, 
 				UnknownClosestToMiddle),
 			Response = question(PathArray ^ elem(
-				UnknownClosestToMiddle))
+				UnknownClosestToMiddle), binary(NewBottom, 
+					NewTop, UnknownClosestToMiddle))
 		;
 			% No unknown suspects on the path, so revert to
 			% the fallback search mode.
@@ -959,10 +1012,13 @@
 	search_space(T)::out, search_response::out)
 	is det <= mercury_edt(S, T).
 
-find_middle_weight(Store, [], _, MaybeLastUnknown, !SearchSpace, Response) :-
+find_middle_weight(Store, [], TopId, MaybeLastUnknown, !SearchSpace, Response) 
+		:-
 	(
 		MaybeLastUnknown = yes(LastUnknown),
-		Response = question(LastUnknown)
+		Response = question(LastUnknown, divide_and_query(
+			get_weight(!.SearchSpace, TopId), 
+			get_weight(!.SearchSpace, LastUnknown)))
 	;
 		MaybeLastUnknown = no,
 		% This could happen when there were no unknown suspects 
@@ -972,7 +1028,8 @@
 	).
 find_middle_weight(Store, [SuspectId | SuspectIds], TopId, MaybeLastUnknown, 
 		!SearchSpace, Response) :-
-	Target = get_weight(!.SearchSpace, TopId) // 2,
+	TopWeight = get_weight(!.SearchSpace, TopId),
+	Target = TopWeight // 2,
 	%
 	% Find the heaviest suspect:
 	%
@@ -1007,18 +1064,27 @@
 					LastUnknownWeight - Target <
 						Target - MaxWeight
 				->
-					Response = question(LastUnknown)
+					Response = question(LastUnknown, 
+						divide_and_query(TopWeight,
+							LastUnknownWeight))
 				;					
-					Response = question(Heaviest)
+					Response = question(Heaviest,
+						divide_and_query(TopWeight,
+							MaxWeight))
 				)
 			;
 				MaybeLastUnknown = no,
-				Response = question(Heaviest)
+				Response = question(Heaviest, 
+					divide_and_query(TopWeight, MaxWeight))
 			)
 		;
 			(
 				MaybeLastUnknown = yes(LastUnknown),
-				Response = question(LastUnknown)
+				LastUnknownWeight = get_weight(!.SearchSpace, 
+					LastUnknown),
+				Response = question(LastUnknown,
+					divide_and_query(TopWeight,
+						LastUnknownWeight))
 			;
 				MaybeLastUnknown = no,
 				% Look deeper until we find an unknown:
@@ -1045,6 +1111,73 @@
 		NewSuspectId = PrevSuspectId
 	).
 
+question_reason_to_string(start) = "this is the node where the `dd' command "
+	++ "was given.".
+
+question_reason_to_string(binding_node(PrimOpType, FileName, LineNo,
+		TermPath, ProcLabel, Eliminated)) = Str :-
+	PrimOpStr = primitive_op_type_to_string(PrimOpType),
+	TermPathStrings = list.map(int_to_string, TermPath),
+	PathStr = string.join_list("/", TermPathStrings),
+	LineNoStr = int_to_string(LineNo),
+	get_pred_attributes(ProcLabel, SymModule, Name, Arity, 
+		PredOrFunc),
+	(
+		PredOrFunc = function,
+		PredOrFuncStr = "function"
+	;
+		PredOrFunc = predicate,
+		PredOrFuncStr = "predicate"
+	),
+	Module = sym_name_to_string(SymModule),
+	ArityStr = int_to_string(Arity),
+	(
+		Eliminated = yes,
+		EliminatedStr = " That node was, however, previously "
+			++ "eliminated from the bug search."
+	;
+		Eliminated = no,
+		EliminatedStr = ""
+	),
+	Str = "the marked subterm was bound by the " ++ 
+		PrimOpStr ++ " inside the " ++ PredOrFuncStr ++
+		" " ++ Module ++ "." ++ Name ++ "/" ++ ArityStr ++
+		" (" ++ FileName ++ ":" ++ LineNoStr ++ "). " ++
+		"The path to the sub-term in the atom is " ++ PathStr ++ "."
+		++ EliminatedStr.
+		
+question_reason_to_string(top_down) = "this is the next node in the top-down " 
+	++ "search.".
+
+question_reason_to_string(subterm_no_proc_rep) = 
+	"tracking of the marked subterm had to be aborted here, because of "
+	++ "missing tracing information.".
+
+question_reason_to_string(binding_node_eliminated) = 
+	"tracking of the marked subterm was stopped here, because the binding "
+	++ "node lies in a portion of the tree which has been eliminated.".
+
+question_reason_to_string(binary(Bottom, Top, Split)) = Str :-
+	PathLengthStr = int_to_string_thousands(Bottom - Top + 1),
+	SubPath1LengthStr = int_to_string_thousands(Bottom - Split),
+	SubPath2LengthStr = int_to_string_thousands(Split - Top + 1),
+	Str = "this node divides a path of length " ++ PathLengthStr
+		++ " into two paths of length " ++
+		SubPath1LengthStr ++ " and " ++ SubPath2LengthStr ++ ".".
+
+question_reason_to_string(divide_and_query(OldWeight, SubtreeWeight)) = Str :-
+	Weight1Str = int_to_string_thousands(OldWeight - SubtreeWeight),
+	Weight2Str = int_to_string_thousands(SubtreeWeight),
+	Str = "this node divides the suspect area into " ++
+		"two regions of " ++ Weight1Str ++ " and " ++ Weight2Str ++
+		" events each.".
+
+question_reason_to_string(skipped) = "there are no more non-skipped questions "
+	++ "left.".
+
+question_reason_to_string(revise) = "this node is being revised, because of "
+	++ "an unsuccessful previous bug search.".
+
 %-----------------------------------------------------------------------------%
 
 show_info(Store, OutStream, Analyser, Response, !IO) :-
@@ -1056,10 +1189,11 @@
 		% Get the context of the current question.
 		%
 		(
-			Analyser ^ last_search_question = yes(LastQuestionId),
+			Analyser ^ last_search_question = 
+				yes(suspect_and_reason(LastId, Reason)),
 			(
 				edt_context(Store, get_edt_node(SearchSpace, 
-					LastQuestionId), FileName -  LineNo, 
+					LastId), FileName -  LineNo, 
 					MaybeReturnContext)
 			->
 				(
@@ -1122,8 +1256,12 @@
 		InfoMessage = string.format_table([left(!.FieldNames),
 			left(!.Data)], " : ")
 	),
- 	io.format(OutStream, "\n%s\n\n", [s(InfoMessage)], !IO),
-	Node = get_edt_node(SearchSpace, LastQuestionId),
+	ReasonStr = question_reason_to_string(Reason),
+	ReasonSent = "The current question was chosen because " ++ ReasonStr,
+	WrappedReason = string.word_wrap(ReasonSent, 72),
+ 	io.format(OutStream, "\n%s\n%s\n\n", [s(InfoMessage), 
+		s(WrappedReason)], !IO),
+	Node = get_edt_node(SearchSpace, LastId),
 	edt_question(Analyser ^ io_action_map, Store, Node,
 		OracleQuestion),
 	Response = oracle_question(OracleQuestion).
Index: browser/declarative_edt.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_edt.m,v
retrieving revision 1.5
diff -u -r1.5 declarative_edt.m
--- browser/declarative_edt.m	12 Mar 2005 04:46:29 -0000	1.5
+++ browser/declarative_edt.m	12 Mar 2005 11:32:53 -0000
@@ -55,6 +55,7 @@
 :- interface.
 
 :- import_module mdbcomp.program_representation.
+:- import_module mdbcomp.prim_data.
 :- import_module mdb.io_action.
 :- import_module mdb.declarative_debugger.
 
@@ -155,7 +156,16 @@
 		% fail.
 		%
 	pred edt_context(S::in, T::in, pair(string, int)::out, 
-		maybe(pair(string, int))::out) is semidet
+		maybe(pair(string, int))::out) is semidet,
+
+		% Return the proc label for the given node.
+		%
+	func edt_proc_label(S, T) = proc_label,
+
+		% Convert an arg_pos to a user arg number using the
+		% atom of the given node.
+		%
+	func edt_arg_pos_to_user_arg_num(S, T, arg_pos) = int
 ].
 
 :- type subterm_mode
@@ -176,15 +186,25 @@
 	;	input(arg_pos, term_path)
 
 			% Subterm was constructed in the body.  We record
-			% the filename and line number of the primitive
-			% operation (unification or inlined foreign_proc)
-			% that constructed it.
-	;	primitive_op(string, int)
+			% the filename, line number and type of the primitive
+			% operation that constructed it.
+	;	primitive_op(string, int, primitive_op_type)
 
 			% The origin could not be found due to missing
 			% information.
 	;	not_found.
 
+	% The type of primitive operation that bound a subterm that was being
+	% tracked.
+	%
+:- type primitive_op_type
+	--->	foreign_proc
+	;	builtin_call
+	;	untraced_call
+	;	unification.
+
+:- func primitive_op_type_to_string(primitive_op_type) = string.
+
 	% This type defines a search space in which the declarative debugger
 	% can look for bugs.  The search space keeps track of which nodes in
 	% the EDT could contain a bug as well as skipped or ignored nodes.
@@ -314,9 +334,10 @@
 	;	origin(suspect_id, arg_pos, term_path)
 	
 			% The subterm was bound by a primitive operation inside
-			% the suspect.  The arguments are the filename and line
-			% number of primitive op that bound the subterm.
-	;	primitive_op(suspect_id, string, int)
+			% the suspect.  The other arguments are the filename,
+			% line number and type of the primitive operation 
+			% that bound the subterm.
+	;	primitive_op(suspect_id, string, int, primitive_op_type)
 			
 			% The suspect is the root of an implicit subtree and
 			% the origin lies in one of it's children.
@@ -464,6 +485,11 @@
 :- pred check_search_space_consistency(S::in, search_space(T)::in, string::in) 
 	is det <= mercury_edt(S, T).
 
+	% Return the proc_label for the given suspect.
+	%
+:- func get_proc_label_for_suspect(S, search_space(T), suspect_id) = proc_label
+	<= mercury_edt(S, T).
+
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -930,8 +956,9 @@
 		Response) :-
 	edt_dependency(Store, Node, ArgPos, TermPath, _, Origin),
 	(
-		Origin = primitive_op(FileName, LineNo),
-		Response = primitive_op(SuspectId, FileName, LineNo)
+		Origin = primitive_op(FileName, LineNo, PrimOpType),
+		Response = primitive_op(SuspectId, FileName, LineNo, 
+			PrimOpType)
 	;
 		Origin = not_found,
 		Response = not_found
@@ -1844,3 +1871,11 @@
 		get_path(SearchSpace, ParentId, TopId, [BottomId | PathSoFar],
 			Path)
 	).
+
+primitive_op_type_to_string(foreign_proc) = "foreign procedure call".
+primitive_op_type_to_string(builtin_call) = "builtin operation".
+primitive_op_type_to_string(untraced_call) = "untraced call".
+primitive_op_type_to_string(unification) = "unification".
+
+get_proc_label_for_suspect(Store, SearchSpace, SuspectId) = 
+	edt_proc_label(Store, get_edt_node(SearchSpace, SuspectId)).
Index: browser/declarative_execution.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_execution.m,v
retrieving revision 1.39
diff -u -r1.39 declarative_execution.m
--- browser/declarative_execution.m	12 Mar 2005 04:46:29 -0000	1.39
+++ browser/declarative_execution.m	12 Mar 2005 11:13:45 -0000
@@ -392,6 +392,8 @@
 :- pred absolute_arg_num(arg_pos::in, trace_atom::in, int::out)
 	is det.
 
+:- pred user_arg_num(arg_pos::in, trace_atom::in, int::out) is det.
+
 %-----------------------------------------------------------------------------%
 	
 :- implementation.
@@ -1479,9 +1481,17 @@
 	head_var_num_to_arg_num(Args, N, 1, ArgNum).
 absolute_arg_num(any_head_var_from_back(M), atom(_, Args), length(Args)-M+1).
 
+user_arg_num(user_head_var(ArgNum), _, ArgNum).
+user_arg_num(any_head_var(AnyArgNum), atom(_, Args), ArgNum) :-
+	arg_num_to_head_var_num(Args, AnyArgNum, 1, ArgNum).
+user_arg_num(any_head_var_from_back(AnyArgNumFromBack), atom(_, Args), ArgNum) 
+		:-
+	arg_num_to_head_var_num(Args, 
+		list.length(Args) - AnyArgNumFromBack + 1, 1, ArgNum).
+
 :- pred head_var_num_to_arg_num(list(trace_atom_arg)::in, int::in, int::in,
 	int::out) is det.
-
+	
 head_var_num_to_arg_num([], _, _, _) :-
 	throw(internal_error("head_var_num_to_arg_num",
 		"nonexistent head_var_num")).
@@ -1499,5 +1509,27 @@
 		;
 			head_var_num_to_arg_num(Args, SearchUserHeadVarNum - 1,
 				CurArgNum + 1, ArgNum)
+		)
+	).
+
+:- pred arg_num_to_head_var_num(list(trace_atom_arg)::in, int::in, int::in,
+	int::out) is det.
+
+arg_num_to_head_var_num([], _, _, _) :-
+	throw(internal_error("arg_num_to_head_var_num",
+		"nonexistent arg num")).
+arg_num_to_head_var_num([Arg | Args], ArgNum, CurArgNum, UserArgNum) :-
+	Arg = arg_info(UserVis, _, _),
+	(
+		UserVis = no,
+		arg_num_to_head_var_num(Args, ArgNum - 1, CurArgNum,
+			UserArgNum)
+	;
+		UserVis = yes,
+		( ArgNum = 1 ->
+			UserArgNum = CurArgNum
+		;
+			arg_num_to_head_var_num(Args, ArgNum - 1,
+				CurArgNum + 1, UserArgNum)
 		)
 	).
Index: browser/declarative_oracle.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_oracle.m,v
retrieving revision 1.40
diff -u -r1.40 declarative_oracle.m
--- browser/declarative_oracle.m	12 Mar 2005 04:46:29 -0000	1.40
+++ browser/declarative_oracle.m	12 Mar 2005 09:55:49 -0000
@@ -67,11 +67,9 @@
 	%
 :- pred trust_standard_library(oracle_state::in, oracle_state::out) is det.
 
-	% remove_trusted(N, !Oracle).
-	% Removes the (N-1)th trusted object from the set of trusted objects.
-	% Fails if there are fewer than N-1 trusted modules (or N < 0).
-	% The trusted set is turned into a sorted list before finding the
-	% (N-1)th element.
+	% remove_trusted(Id, !Oracle).
+	% Removes the trusted object with the given Id from the set of trusted
+	% objects.
 	%
 :- pred remove_trusted(int::in, oracle_state::in, oracle_state::out)
 	is semidet.
Index: browser/declarative_tree.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/declarative_tree.m,v
retrieving revision 1.22
diff -u -r1.22 declarative_tree.m
--- browser/declarative_tree.m	12 Mar 2005 04:46:29 -0000	1.22
+++ browser/declarative_tree.m	12 Mar 2005 05:12:07 -0000
@@ -66,7 +66,10 @@
 		pred(edt_same_nodes/3) is trace_same_event_numbers,
 		pred(edt_topmost_node/2) is trace_topmost_node,
  		pred(edt_weight/4) is trace_weight,
- 		pred(edt_context/4) is trace_context
+ 		pred(edt_context/4) is trace_context,
+		func(edt_proc_label/2) is trace_node_proc_label,
+		func(edt_arg_pos_to_user_arg_num/3) is
+			trace_arg_pos_to_user_arg_num
 	].
 
 %-----------------------------------------------------------------------------%
@@ -426,6 +429,21 @@
 	call_node_from_id(Store, Ref, CallNode),
 	CallNode ^ call_at_max_depth = no.
 
+:- func trace_node_proc_label(wrap(S), edt_node(R)) = proc_label
+	<= annotated_trace(S, R).
+
+trace_node_proc_label(wrap(Store), dynamic(Ref)) = ProcLabel :-
+	det_edt_return_node_from_id(Store, Ref, Node),
+	(
+		Node = fail(_, _, _, _, Label)
+	;
+		Node = exit(_, _, _, _, _, Label, _)
+	;
+		Node = excp(_, _, _, _, _, Label)
+	),
+	ProcLayout = get_proc_layout_from_label_layout(Label),
+	ProcLabel = get_proc_label_from_layout(ProcLayout).
+
 :- type contour_type
 			% The contour ends with an EXIT event.
 	--->	normal
@@ -1475,7 +1493,7 @@
 		( list.member(Var0, BoundVars) ->
 			(
 				TermPath0 = [],
-				Origin = primitive_op(File, Line)
+				Origin = primitive_op(File, Line, unification)
 			;
 				TermPath0 = [TermPathStep0 | TermPath],
 				list.index1_det(FieldVars, TermPathStep0,
@@ -1529,7 +1547,7 @@
 	;
 		AtomicGoal = pragma_foreign_code_rep(_Args),
 		( list.member(Var0, BoundVars) ->
-			Origin = primitive_op(File, Line)
+			Origin = primitive_op(File, Line, foreign_proc)
 		;
 			traverse_primitives(Prims, Var0, TermPath0,
 				Store, ProcRep, Origin)
@@ -1557,7 +1575,7 @@
 	;
 		AtomicGoal = builtin_call_rep(_, _, _),
 		( list.member(Var0, BoundVars) ->
-			Origin = primitive_op(File, Line)
+			Origin = primitive_op(File, Line, builtin_call)
 		;
 			traverse_primitives(Prims, Var0, TermPath0,
 				Store, ProcRep, Origin)
@@ -1586,7 +1604,7 @@
 			Origin = output(dynamic(NodeId), Pos, TermPath)
 		;
 			MaybeNodeId = no,
-			Origin = primitive_op(File, Line)
+			Origin = primitive_op(File, Line, untraced_call)
 		)
 	;
 		traverse_primitives(Prims, Var, TermPath, Store, ProcRep,
@@ -1711,6 +1729,15 @@
 	select_arg_at_pos(ArgPos, Args, ArgInfo),
 	ArgInfo = arg_info(_, _, MaybeArg),
 	MaybeArg = yes(_).
+
+:- func trace_arg_pos_to_user_arg_num(wrap(S), edt_node(R), arg_pos) = int
+	<= annotated_trace(S, R).
+
+trace_arg_pos_to_user_arg_num(wrap(Store), dynamic(Ref), ArgPos) = ArgNum :-
+	get_edt_call_node(Store, Ref, CallId),
+	call_node_from_id(Store, CallId, Call),
+	Atom = get_trace_call_atom(Call),
+	user_arg_num(ArgPos, Atom, ArgNum).
 
 %-----------------------------------------------------------------------------%
 
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.429
diff -u -r1.429 user_guide.texi
--- doc/user_guide.texi	12 Mar 2005 04:46:30 -0000	1.429
+++ doc/user_guide.texi	12 Mar 2005 11:21:34 -0000
@@ -4102,8 +4102,9 @@
 List the filename and line number of the predicate the current question
 is about as well as the filename and line number where the predicate 
 was called (if this information is available).  Also print some information
-about the state of the bug search, such as the current search mode and
-how many events are yet to be eliminated.
+about the state of the bug search, such as the current search mode,
+how many events are yet to be eliminated and the reason for asking
+the current question.
 @sp 1
 @item help
 Summarize the list of available commands.
Index: tests/debugger/declarative/info.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/declarative/info.exp,v
retrieving revision 1.1
diff -u -r1.1 info.exp
--- tests/debugger/declarative/info.exp	12 Mar 2005 04:46:32 -0000	1.1
+++ tests/debugger/declarative/info.exp	12 Mar 2005 11:50:55 -0000
@@ -1,34 +1,184 @@
-      E1:     C1 CALL pred info.main/2-0 (det) info.m:13
+      E1:     C1 CALL pred info.main/2-0 (det) info.m:26
 mdb> mdb> Contexts will not be printed.
 mdb> echo on
 Command echo enabled.
-mdb> s
-      E2:     C2 CALL pred info.p/1-0 (det)
+mdb> break info.last
+ 0: + stop  interface pred info.last/2-0 (semidet)
+mdb> c
+      E2:     C2 CALL pred info.last/2-0 (semidet)
+mdb> delete *
+ 0: E stop  interface pred info.last/2-0 (semidet)
 mdb> f
-      E3:     C2 EXIT pred info.p/1-0 (det)
+      E3:     C2 EXIT pred info.last/2-0 (semidet)
+mdb> dd -s divide_and_query
+last([1, 2, 3, 4, 5, 6, 7, 8, ...], t/1)
+Valid? info
+
+Context of current question   : info.m:43 (info.m:15)
+Search mode                   : divide and query     
+Estimated questions remaining : 5                    
+Number of suspect events      : 30                   
+The current question was chosen because this is the node where the `dd'
+command was given.
+
+last([1, 2, 3, 4, 5, 6, 7, 8, ...], t/1)
+Valid? n
+last([6, 7, 8, 9, 10], t(10))
+Valid? info
+
+Context of current question   : info.m:43 (info.m:45)
+Search mode                   : divide and query     
+Estimated questions remaining : 5                    
+Number of suspect events      : 30                   
+The current question was chosen because this node divides the suspect
+area into two regions of 15 and 15 events each.
+
+last([6, 7, 8, 9, 10], t(10))
+Valid? n
+last([9, 10], t(10))
+Valid? info
+
+Context of current question   : info.m:43 (info.m:45)
+Search mode                   : divide and query     
+Estimated questions remaining : 4                    
+Number of suspect events      : 15                   
+The current question was chosen because this node divides the suspect
+area into two regions of 9 and 6 events each.
+
+last([9, 10], t(10))
+Valid? a
+Diagnosis aborted.
+      E3:     C2 EXIT pred info.last/2-0 (semidet)
+mdb> 
+      E4:     C3 CALL pred info.last/2-0 (semidet)
+mdb> f
+      E5:     C3 EXIT pred info.last/2-0 (semidet)
 mdb> dd
-p(1)
+last([101, 112, 103, 104, 105, 106, 107, 108], t/1)
+Valid? n
+last([112, 103, 104, 105, 106, 107, 108], t(108))
 Valid? info
 
-Context of current question : info.m:19 (info.m:14)
+Context of current question : info.m:43 (info.m:45)
 Search mode                 : top down             
-Number of suspect events    : 2                    
+Number of suspect events    : 24                   
+The current question was chosen because this is the next node in the
+top-down search.
+
+last([112, 103, 104, 105, 106, 107, 108], t(108))
+Valid? b 2
+browser> mark
+last([108], t(108))
+Valid? info
+
+Context of current question : info.m:43 (info.m:45)
+Search mode                 : binary search on path
+Number of suspect events    : 21                   
+The current question was chosen because the marked subterm was bound by
+the unification inside the predicate info.last/2 (info.m:43). The path
+to the sub-term in the atom is 2.
+
+last([108], t(108))
+Valid? y
+last([104, 105, 106, 107, 108], t(108))
+Valid? info
 
-p(1)
+Context of current question : info.m:43 (info.m:45)
+Search mode                 : binary search on path
+Number of suspect events    : 18                   
+The current question was chosen because this node divides a path of
+length 6 into two paths of length 3 and 3.
+
+last([104, 105, 106, 107, 108], t(108))
+Valid? n
+last([106, 107, 108], t(108))
+Valid? info
+
+Context of current question : info.m:43 (info.m:45)
+Search mode                 : binary search on path
+Number of suspect events    : 12                   
+The current question was chosen because this node divides a path of
+length 3 into two paths of length 1 and 2.
+
+last([106, 107, 108], t(108))
+Valid? b 1
+browser> cd 1
+browser> mark
+last([105, 106, 107, 108], t(108))
+Valid? info
+
+Context of current question : info.m:43 (info.m:45)
+Search mode                 : binary search on path
+Number of suspect events    : 6                    
+The current question was chosen because tracking of the marked subterm
+was stopped here, because the binding node lies in a portion of the
+tree which has been eliminated.
+
+last([105, 106, 107, 108], t(108))
 Valid? a
 Diagnosis aborted.
-      E3:     C2 EXIT pred info.p/1-0 (det)
-mdb> dd -s divide_and_query
-p(1)
+      E5:     C3 EXIT pred info.last/2-0 (semidet)
+mdb> break q
+ 0: + stop  interface pred info.q/4-0 (det)
+mdb> c
+      E6:     C4 CALL pred info.q/4-0 (det)
+mdb> delete *
+ 0: E stop  interface pred info.q/4-0 (det)
+mdb> f
+      E7:     C4 EXIT pred info.q/4-0 (det)
+mdb> dd
+q(0, "lala", t(t(t("lala"))), 2)
+Valid? b 3
+browser> cd 1/1
+browser> mark
+f(0, "lala") = t(t(t("lala")))
 Valid? info
 
-Context of current question   : info.m:19 (info.m:14)
-Search mode                   : divide and query     
-Estimated questions remaining : 1                    
-Number of suspect events      : 2                    
+Context of current question : info.m:51 (info.m:34)
+Search mode                 : binary search on path
+Number of suspect events    : 6                    
+The current question was chosen because the marked subterm was bound by
+the unification inside the function info.f/3 (info.m:52). The path to
+the sub-term in the atom is 3/1/1.
 
-p(1)
+f(0, "lala") = t(t(t("lala")))
 Valid? a
 Diagnosis aborted.
-      E3:     C2 EXIT pred info.p/1-0 (det)
+      E7:     C4 EXIT pred info.q/4-0 (det)
+mdb> 
+      E8:     C5 CALL pred info.q/4-0 (det)
+mdb> f
+      E9:     C5 EXIT pred info.q/4-0 (det)
+mdb> dd
+q(1, "lala", t(t(t("lala"))), 2)
+Valid? b 4
+browser> mark
+fproc(1) = 2
+Valid? info
+
+Context of current question : info.m:57 (info.m:37)
+Search mode                 : binary search on path
+Number of suspect events    : 6                    
+The current question was chosen because the marked subterm was bound by
+the foreign procedure call inside the function info.fproc/2
+(info.m:57). The path to the sub-term in the atom is 2.
+
+fproc(1) = 2
+Valid? n
+Found incorrect contour:
+fproc(1) = 2
+Is this a bug? n
+fproc(1) = 2
+Valid? [no] info
+
+Context of current question : info.m:57 (info.m:37)
+Search mode                 : top down             
+Number of suspect events    : 6                    
+The current question was chosen because this node is being revised,
+because of an unsuccessful previous bug search.
+
+fproc(1) = 2
+Valid? [no] a
+Diagnosis aborted.
+      E9:     C5 EXIT pred info.q/4-0 (det)
 mdb> quit -y
Index: tests/debugger/declarative/info.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/declarative/info.inp,v
retrieving revision 1.1
diff -u -r1.1 info.inp
--- tests/debugger/declarative/info.inp	12 Mar 2005 04:46:32 -0000	1.1
+++ tests/debugger/declarative/info.inp	12 Mar 2005 11:49:27 -0000
@@ -1,12 +1,52 @@
 register --quiet
 context none
 echo on
-s
+break info.last
+c
+delete *
+f
+dd -s divide_and_query
+info
+n
+info
+n
+info
+a
+
+f
+dd
+n
+info
+b 2
+mark
+info
+y
+info
+n
+info
+b 1
+cd 1
+mark
+info
+a
+break q
+c
+delete *
 f
 dd
+b 3
+cd 1/1
+mark
 info
 a
-dd -s divide_and_query
+
+f
+dd
+b 4
+mark
+info
+n
+n
 info
 a
 quit -y
Index: tests/debugger/declarative/info.m
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/declarative/info.m,v
retrieving revision 1.1
diff -u -r1.1 info.m
--- tests/debugger/declarative/info.m	12 Mar 2005 04:46:32 -0000	1.1
+++ tests/debugger/declarative/info.m	12 Mar 2005 11:45:39 -0000
@@ -8,12 +8,54 @@
 
 :- implementation.
 
-:- import_module int.
+:- import_module int, list.
 
 main(!IO) :-
-	p(X),
-	io.write(X, !IO).
-	
-:- pred p(int::out) is det.
+	(
+		info.last([1,2,3,4,5,6,7,8,9,10], A),
+		info.last([101,112,103,104,105,106,107,108], B)
+	->
+		q(0, "lala", C, D),
+		q(1, "lala", E, F),
+		io.write(A, !IO),
+		io.write(B, !IO),
+		io.write(C, !IO),
+		io.write(D, !IO),
+		io.write(E, !IO),
+		io.write(F, !IO)
+	;
+		true
+	).
 
-p(1).
+:- pred q(int::in, T::in, t(t(t(T)))::out, int::out) is det.
+
+q(N, X, Y, M) :-
+	( N = 0 ->
+		Y = f(N, X),
+		M = 2
+	;
+		M = fproc(N),
+		Y = t(t(t(X)))
+	).
+
+:- pred last(list(T)::in, t(T)::out) is semidet.
+
+info.last([H], t(H)).
+info.last([_ , H2 | T], L) :-
+	info.last([H2 | T], L).
+
+:- type t(T) ---> t(T).
+
+:- func f(int, T) = t(t(t(T))).
+
+f(_, X) = Y :-
+	Z = t(t(t(X))),
+	Y = Z.
+
+:- func fproc(int) = int.
+
+:- pragma foreign_proc("C", fproc(X::in) = (Y::out), 
+	[will_not_call_mercury, thread_safe, promise_pure],
+"
+	Y = X + 1;
+").
--------------------------------------------------------------------------
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