[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