[m-rev.] for review: Add a post-process predicate in collect

Erwan Jahier Erwan.Jahier at irisa.fr
Wed Jul 4 20:25:45 AEST 2001


This change was on my todo heap for a while now ...

-------------------------
Estimated hours taken: 6
branches: main.

Add a post-process predicate in collect. This predicate is optional
and automatically added if the collect user do not define it. 

browser/collect_lib.m:
	Add support for dynamically link the post_process/2 predicates.
	
extras/morphine/source/collect.in:
extras/morphine/source/collect.op
	Add support for automatically add a post_process predicate definition
	as well as a accumulator_type definition.


trace/mercury_trace_external.h:
trace/mercury_trace_external.c:
	Change the name of the accumulator variable type from
	MR_collecting_variable to MR_accumulator variable. Also Add a new
	variable type MR_collected_variable that contains the value that
	is sent to the collect caller process (instead of
	MR_collecting_variable).

	Apply (post_process_ptr) (which points to
	collect__post_process/2) to the accumulator variable before
	sending the collect result.

	
Index: browser/collect_lib.m
===================================================================
RCS file: /home/mercury1/repository/mercury/browser/collect_lib.m,v
retrieving revision 1.6
diff -u -d -u -r1.6 collect_lib.m
--- browser/collect_lib.m	2001/07/03 15:22:21	1.6
+++ browser/collect_lib.m	2001/07/04 10:22:02
@@ -15,13 +15,11 @@
 %
 %	To use it, users just need to define 4 things in a file, using the
 %	Mercury syntax:
-%		1) a `collected_type' which is the type of the collecting 
-%		   variable that will contain the result of the monitoring
-%		   activity.
+%		1) `accumulator_type' which is the type of the accumulator.
 %		2) The predicate initialize/1 which initializes the 
 %		   collecting variable. initialize/1 should respect the
 %		   following declarations:
-%			:- pred initialize(collected_type).
+%			:- pred initialize(accumulator_type).
 %			:- mode initialize(out) is det.
 %		3) The predicate filter/4 which updates the collecting  
 %		   variable at each execution event. filter/4 also outputs  
@@ -31,17 +29,27 @@
 %		   variable is always set to `continue', the collecting will 
 %		   process until the last event is reached. filter/4 should 
 %		   respect the following declarations:
-%			:- pred filter(event, collected_type, collected_type,
+%			:- pred filter(event, accumulator_type, accumulator_type,
 %				stop_or_continue).
 %			:- mode filter(in, di, uo, out) is det.
-%		4) And eventually the mode definition of the second and the 
+%               4) Optionally, a `post_process/2' function that lets
+%   	           one post-process the final value of the
+%   	           accumulator. `post_process/2' should respect the
+%   	           following declarations:
+%  	                :- pred post_process(accumulator_type, collected_type).
+%	                :- mode post_process(in, out) is det.
+% 	           If `collected_type' is different from `accumulator_type', 
+% 	           the `accumulator_type' should also be defined; otherwise
+% 	           by default, `accumulator_type' is automatically defined as
+% 	           being the same type as `collected_type'.
+%		5) And optionally the mode definition of the second and the 
 %		   third arguments of filter/4: `acc_in' and `acc_out'. Those
 %		   mode have `di' and `uo' respectively as default values.
 %
 % 	Then, this file is used to generate the Mercury module `collect.m',
 % 	which is compiled and dynamically linked with the current execution.
 % 	When a `collect' request is made from the external debugger, a variable
-% 	of type collected_type is first initialized (with initialize/1) and
+% 	of type accumulator_type is first initialized (with initialize/1) and
 % 	then updated (with filter/4) for all the events of the remaining
 % 	execution. When the end of the execution is reached, the last value of
 % 	the collecting variable is send to the debugger.
@@ -58,7 +66,7 @@
 
 dummy_pred_to_avoid_warning_about_nothing_exported.
 
-:- pragma export(link_collect(in, out, out, out, out, out, out, di, uo), 
+:- pragma export(link_collect(in, out, out, out, out, out, out, out, di, uo), 
 	"ML_CL_link_collect").
 
 :- pragma export(unlink_collect(in, di, uo), "ML_CL_unlink_collect").
@@ -70,10 +78,10 @@
 % at each event.
 
 % dynamically link the collect module;
-:- pred link_collect(string, c_pointer, c_pointer, c_pointer, c_pointer, 
+:- pred link_collect(string, c_pointer, c_pointer, c_pointer, c_pointer, c_pointer, 
 	dl__result(handle), char, io__state, io__state).
-:- mode link_collect(in, out, out, out, out, out, out, di, uo) is det.
-link_collect(ObjectFile, Filter, Initialize, SendResult, GetCollectType, 
+:- mode link_collect(in, out, out, out, out, out, out, out, di, uo) is det.
+link_collect(ObjectFile, Filter, Initialize, PostProcess, SendResult, GetCollectType, 
 	MaybeHandle, Result) -->
 	%
 	% Link in the object code for the module `collect' from ObjectFile.
@@ -84,6 +92,7 @@
 		print("dlopen failed: "), print(Msg), nl,
 		{ set_to_null_pointer(Initialize) },
 		{ set_to_null_pointer(Filter) },
+		{ set_to_null_pointer(PostProcess) },
 		{ set_to_null_pointer(SendResult) },
 		{ set_to_null_pointer(GetCollectType) },
 		{ Result = 'n' }
@@ -95,22 +104,26 @@
  		%
 		dl__sym(Handle, "ML_COLLECT_initialize", MaybeInitialize),
 		dl__sym(Handle, "ML_COLLECT_filter", MaybeFilter),
+		dl__sym(Handle, "ML_COLLECT_post_process", MaybePostProcess),
 		dl__sym(Handle, "ML_COLLECT_send_collect_result", MaybeSendResult),
-		dl__sym(Handle, "ML_COLLECT_collecting_variable_type", MaybeType),
+		dl__sym(Handle, "ML_COLLECT_collected_variable_type", MaybeType),
 		(
 			{ MaybeInitialize = ok(Initialize0) },
 			{ MaybeFilter = ok(Filter0) },
+			{ MaybePostProcess = ok(PostProcess0) },
 			{ MaybeSendResult = ok(SendResult0) },
 			{ MaybeType = ok(Type0) }
 		->
 			{ Result = 'y' },
 			{ Initialize = Initialize0 },
 			{ Filter = Filter0 },
+			{ PostProcess = PostProcess0 },
 			{ GetCollectType = Type0 },
 			{ SendResult = SendResult0 }
 		;
 			{ set_to_null_pointer(Initialize) },
 			{ set_to_null_pointer(Filter) },
+			{ set_to_null_pointer(PostProcess) },
 			{ set_to_null_pointer(SendResult) },
 			{ set_to_null_pointer(GetCollectType) },
 			{ Result = 'n' }

Index: extras/morphine/source/collect.in
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/morphine/source/collect.in,v
retrieving revision 1.5
diff -u -d -u -r1.5 collect.in
--- extras/morphine/source/collect.in	2001/07/03 15:22:20	1.5
+++ extras/morphine/source/collect.in	2001/07/04 10:22:06
@@ -6,16 +6,19 @@
 :- interface.
 :- import_module char.
 
+:- type accumulator_type.
 :- type collected_type.
 
-:- pred initialize(collected_type).
+:- pred initialize(accumulator_type).
 :- mode initialize(out) is det.
 
+:- pred post_process(accumulator_type, collected_type).
+:- mode post_process(in, out) is det.
 
 :- pred filter(event_number, call_number, depth_number, trace_port_type,
         pred_or_func, declared_module_name, defined_module_name, proc_name,
         arity, mode_number, arguments, determinism, goal_path_string,
-        line_number, collected_type, collected_type, char).
+        line_number, accumulator_type, accumulator_type, char).
 
 :- mode filter(in, in, in, in, in, in, in, in, in, in, in, in, in, in, 
 	acc_in, acc_out, out) is det.
@@ -32,10 +35,11 @@
 :- pragma export(initialize(out), "ML_COLLECT_initialize").
 :- pragma export(filter(in, in, in, in, in, in, in, in, in, in, in, in, in, in,
 	acc_in, acc_out, out), "ML_COLLECT_filter").
+:- pragma export(post_process(in, out), "ML_COLLECT_post_process").
 :- pragma export(send_collect_result(in, in, di, uo), 
 	"ML_COLLECT_send_collect_result").
 :- pragma export(collected_variable_type(out), 
-	"ML_COLLECT_collecting_variable_type").
+	"ML_COLLECT_collected_variable_type").
 
 :- import_module list, int, io, std_util.
 
@@ -226,6 +230,6 @@
 	collected(collected_type).
 
 
-:- pred filter(event, collected_type, collected_type, stop_or_continue).
+:- pred filter(event, accumulator_type, accumulator_type, stop_or_continue).
 :- mode filter(in, acc_in, acc_out, out) is det.
 :- pragma inline(filter/4).
Index: extras/morphine/source/collect.op
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/morphine/source/collect.op,v
retrieving revision 1.7
diff -u -d -u -r1.7 collect.op
--- extras/morphine/source/collect.op	2001/07/03 15:22:20	1.7
+++ extras/morphine/source/collect.op	2001/07/04 10:22:06
@@ -28,13 +28,11 @@
 \n\
 To use it, users just need to define 4 things in a file, using the Mercury \
 syntax.\n\
-	(1) A `collected_type' which is the type of the collecting  \n\
-	   variable that will contain the result of the monitoring\n\
-	   activity.\n\
+	(1) `accumulator_type' which is the type of the accumulator. \n\
 	(2) A predicate `initialize/1' which initializes this collecting \n\
 	   variable. Predicate `initialize/1' should respect the \n\
 	   following declarations:\n\
-		:- pred initialize(collected_type).\n\
+		:- pred initialize(accumulator_type).\n\
 		:- mode initialize(out) is det.\n\
 	(3) A predicate `filter/4' which updates the collecting variable at \n\
 	   each execution event. The fourth argument of `filter/4' \n\
@@ -43,18 +41,27 @@
 	   continues. If this variable is always set to `continue', the \n\
 	   collecting processes until the last event is reached. `filter/4' \n\
 	   should respect the following declarations:\n\
-		:- pred filter(event, collected_type, collected_type, \n\
+		:- pred filter(event, accumulator_type, accumulator_type, \n\
 			stop_or_continue).\n\
 		:- mode filter(in, acc_in, acc_out, out) is det.\n\
 	   where modes `acc\_in' and `acc\_out' are equivalent to\n\
 	   `in' and `out' respectively by default.\n\
-	(4) And optionally, a mode definition for `acc_in' and `acc_out'\n\
+	(4) Optionally, a `post_process/2' function that lets one post-process\n\
+  	    the final value of the accumulator. `post_process/2' should respect\n\
+	    the following declarations:\n\
+	        :- pred post_process(accumulator_type, collected_type).\n\
+	        :- mode post_process(in, out) is det.\n\
+	    If `collected_type' is different from the `accumulator_type', \n\
+	    `collected_type' should also be defined; otherwise by default,\n\
+	    `collected_type' is automatically defined as being the same type\n\
+	    as `accumulator_type'.\n\
+	(5) And optionally, a mode definition for `acc_in' and `acc_out'\n\
 	   if one wants to override their default values.\n\
 \n\
 Then, this file is used to generate the Mercury module `collect.m', \
 which is compiled and dynamically linked with the current execution. \
 When a `collect' request is made from the external debugger, a variable \
-of type `collected_type' is first initialized (with `initialize/1') and \
+of type `accumulator_type' is first initialized (with `initialize/1') and \
 then updated (with `filter/4') for all the remaining events of the \
 execution. When the fourth argument of `filter/4' is equal to `stop', or when \
 the end of the execution is reached, the last value of \
@@ -168,7 +175,7 @@
 If a file `count_call' contains the following statements:\n\
 `\n\
 	:- import_module int.\n\
-	:- type collected_type == int.\n\
+	:- type accumulator_type == int.\n\
 \n\
 	initialize(0).\n\
 \n\
@@ -181,6 +188,19 @@
 '\n\
 Then the goal `run(queens), collect(count_call, Result)' will unify `Result' \
 with the number of calls occurring during the execution of `queens' program.\
+You can also post-process the last value of the accumalator by defining \
+post_process(accumulator_type::in, collected_type::out) predicate. If collected_type \
+is different from accumulator_type, you should also define it. For example, \
+you can post-process the final value of the `count_call' monitor by adding \
+the following statements to `count_call' file: \n\
+`\n\
+	:- type collected_type == string.\n\
+	post_process(Int, String) :-\n\
+		if Int > 100 then \n\
+	              String = \"More than 100 calls have been done\"\n\
+		else\n\
+	              String = \"Less than 101 calls have been done\"\n\
+'\n\
 "
 	).
 
@@ -311,6 +331,18 @@
 	write(collect, ""),
 	write(collect, "\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n"),
 	( 
+		is_collected_type_defined(File)
+	;
+		% Add a definition for collected_type if necessary
+	        write(collect, ":- type collected_type == accumulator_type.\n")
+	),
+	( 
+		is_post_process_pred_defined(File)
+	;
+		% Add a definition for post_process/2 if necessary
+	        write(collect, "post_process(Acc, Acc).\n")
+	),
+	( 
 		is_there_any_mode_declaration(File)
 	;
 		% Add a mode definition of `acc_in' and `acc_out' if not
@@ -334,7 +366,56 @@
 	close(collect),
 	close(collect_in).
 
+% Check if accumulator_type is defined. 
+is_collected_type_defined(File) :-
+	open(File, read, S),
+	(
+		is_collected_type_defined_do(S),
+		close(S), 
+		!
+	;
+		close(S),
+		fail
+	).
+
+is_collected_type_defined_do(S) :-
+	read_mercury_term(S, Term),
+	(
+	        term_string(Term, String),
+		append_strings(":- type(collected_type", _,  String)
+	;
+		Term = end_of_file,
+		!,
+		fail
+	;
+		is_collected_type_defined_do(S)
+	).
 
+% Check if post_process is defined. 
+is_post_process_pred_defined(File) :-
+	open(File, read, S),
+	(
+		is_post_process_pred_defined_do(S),
+		close(S), 
+		!
+	;
+		close(S),
+		fail
+	).
+
+is_post_process_pred_defined_do(S) :-
+	read_mercury_term(S, Term),
+	(
+		term_string(Term, String),
+		append_strings("post_process", _,  String)
+	;
+		Term = end_of_file,
+		!,
+		fail
+	;
+		is_post_process_pred_defined_do(S)
+	).
+
 % Check if there is a mode definition of `acc_in' and `acc_out' in the 
 % file `File'. Those are to let users specify di and uo as modes for filter.
 is_there_any_mode_declaration(File) :-
@@ -366,7 +447,6 @@
 	;
 		is_there_any_mode_declaration_do(S)
 	).
-
 
 %------------------------------------------------------------------------------%
 opium_primitive(

Index: trace/mercury_trace_external.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_external.c,v
retrieving revision 1.58
diff -u -d -u -r1.58 mercury_trace_external.c
--- trace/mercury_trace_external.c	2001/07/03 15:22:17	1.58
+++ trace/mercury_trace_external.c	2001/07/04 10:22:09
@@ -125,9 +125,21 @@
 ** a collect request.
 */
 
-static  MR_Word	MR_collecting_variable;
+static  MR_Word	MR_accumulator_variable;
+
+/*
+** Global variable that is sent to collect caller.
+*/
+
+static  MR_Word	MR_collected_variable;
 
 /*
+** Function pointer used to post-process the result of the collect activity
+*/
+
+static void	(*post_process_ptr)(MR_Word, MR_Word *);
+
+/*
 ** Function pointer used to sent the collecting variable to the external 
 ** debugger.
 */
@@ -755,7 +767,7 @@
 			case MR_REQUEST_LINK_COLLECT:
 			  {
 			        MR_Char	result;
-				MR_Word	MR_collecting_variable_type;
+				MR_Word	MR_accumulator_variable_type;
 
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
@@ -768,6 +780,7 @@
 			       		    MR_object_file_name,
 					    (MR_Word *) &cmd->MR_filter_ptr,
 					    (MR_Word *) &initialize_ptr,
+					    (MR_Word *) &post_process_ptr,
 					    (MR_Word *) &send_collect_result_ptr,
 					    (MR_Word *) &get_collect_var_type_ptr,
 					    &collect_lib_maybe_handle,
@@ -779,12 +792,12 @@
 						"link_collect_succeeded");
 					MR_TRACE_CALL_MERCURY(
 					    (*get_collect_var_type_ptr)(
-						&MR_collecting_variable_type));
-					MR_collecting_variable = 
+						&MR_accumulator_variable_type));
+					MR_accumulator_variable = 
 					    MR_make_permanent(
-						MR_collecting_variable,
+						MR_accumulator_variable,
 						(MR_TypeInfo) 
-						MR_collecting_variable_type);
+						MR_accumulator_variable_type);
 				} else {
 					MR_send_message_to_socket(
 						"link_collect_failed");
@@ -802,7 +815,7 @@
 						"collect_linked");
 					external_debugger_mode = MR_collecting;
 					MR_TRACE_CALL_MERCURY(
-					  (*initialize_ptr)(&MR_collecting_variable));
+					  (*initialize_ptr)(&MR_accumulator_variable));
 
 					/*
 					** In order to perform the collect from
@@ -1504,8 +1517,8 @@
 		layout->MR_sll_entry->MR_sle_detism,
 		(MR_String) path,
 		lineno,
-		MR_collecting_variable,
-		&MR_collecting_variable,
+		MR_accumulator_variable,
+		&MR_accumulator_variable,
 		&result));
 	*stop_collecting = (result == 'y');
 }
@@ -1548,8 +1561,12 @@
 MR_send_collect_result(void)
 {
 	MR_TRACE_CALL_MERCURY(
+		(*post_process_ptr)(
+			MR_accumulator_variable, 
+			&MR_collected_variable);
+
 		(*send_collect_result_ptr)(
-			MR_collecting_variable, 
+			MR_collected_variable, 
 			(MR_Word) &MR_debugger_socket_out));
 #if defined(HAVE_DLFCN_H) && defined(HAVE_DLCLOSE)
 	MR_TRACE_CALL_MERCURY(

-- 
R1.


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