[m-dev.] For review: implementation of collect for Opium-M

Erwan Jahier Erwan.Jahier at irisa.fr
Fri Oct 29 04:43:11 AEST 1999


| > | Also, the use of MR_Trace_Port
| > | and MR_PredFunc looks dangerous; the type here should exactly match
| > | the type with which the function is defined, and I'll bet that it
| > | will be defined using Integer or Word rather than MR_Trace_Port.
| > 
| > Well, collect.m is generated with the help of the file collect.in (which is 
| > not typed by users) which contains:
| > 
| > 	% The stuff defined below is similar to types goal_path and trace_port
| > 	% defined in modules compiler/hlds_goal.m and compiler/trace.m.
| > 	% This enumeration must be EXACTLY the same as the MR_trace_port enum in
| > 	% runtime/mercury_trace_base.h, and in the same order, since the code
| > 	% assumes the representation is the same.
| >
| > 	:- type trace_port_type
| > 		--->	call
| > 		;	exit
| > 		;	redo
| > 		;	fail
| > 		...
| > 
| > In runtime/mercury_trace_base.h, there is the comment:
| > 
| > 	/*
| > 	** This enum should EXACTLY match the definition of the `trace_port_type'
| > 	** type in browser/debugger_interface, and the port names list in the
| > 	** C source file of this module.
| > 	*/
| > 
| > 	typedef	enum {
| > 		MR_PORT_CALL,
| > 		MR_PORT_EXIT,
| > 		...}
| 
| Actually I think that code only assumes that the representation of the
| enum VALUES are the same.  I don't think it assumes that the representation
| of the TYPES are the same.  (If it does, then that assumption is a bug.)
| In particular, although the same numerical values will be used, the C
| compiler may well choose to use a `short' or `unsigned short' or
| even `unsigned char' type to represent the enum.  There is no guarantee
| that the type used will have the same representation and calling convention
| as `Word' or `Integer'.
| 
| In particular, for the `pred_or_func'/`MR_PredFunc' type, the enum has
| only two values.  The numerical values of these two will always be the
| same (pred = MR_PREDICATE = 0, func = MR_FUNCTION = 1).  But a clever C
| compiler might recognize that the MR_PredFunc type has only two values
| and thus might try passing values of type MR_PredFunc in a single-bit
| condition register rather than in a full-word register.  The calling
| convention might depend on the type.
| 
| It might be best to change the definitions of the types so that
| they are typedefs for `Word' rather than being enums.  The enumeration
| constants would of course stay.  So the declarations would look like
| this
| 
| 	enum { MR_PORT_CALL, MR_PORT_EXIT, ... };
| 	typedef Word MR_Trace_Port;
| 
| or perhaps like this
| 
| 	typedef enum { MR_PORT_CALL, MR_PORT_EXIT, ... } MR_Trace_Port_Enum;
| 	typedef Word MR_Trace_Port; 



I will do that as a separate change.

Here is the relative diff taking into account your review:

--- logmsg.save	Thu Oct 28 19:44:09 1999
+++ logmsg	Thu Oct 28 19:57:01 1999
@@ -27,14 +27,24 @@
 
 browser/debugger_interface.m:
 	Add 2 new debugger requests `link_collect' and `collect':
-	(1) `link_collect' to dynamically link the module collect.m with the 
-	current execution; (2) `collect' to start the monitoring process.
+	(1) `link_collect(ObjectFile)' to dynamically link ObjectFile
+	with the current execution; (2) `collect' to start the monitoring 
+	process.
+
+	Define a new predicate get_object_file_name/2 that let the 
+	MR_trace_event_external() retrieve the name of the object file
+	available from the `link_collect(string)' request.
+
+	Define a new function get_collecting_variable_type/2 that retrieves
+	the type of a variable. This type is needed in MR_trace_event_external()
+	to be able to call MR_make_permanent() on MR_collecting_variable; we
+	need to do that to ensure that the memory allocated for it won't be 
+	deallocated on backtracking.
 
 	Add the new request `current_grade' which lets the external debugger
 	know the grade the current execution has been compiled with; it is 
 	necessary to be able to compile collect.m in the same grade as the 
 	the program being monitored.
-
 
 browser/dl.m:
 	Move the type definition of the type `handle' to be able to use it in

 Index: 0.1/debugger_interface.m
--- 0.1/debugger_interface.m Thu, 28 Oct 1999 12:57:51 +0200 jahier (collect/1_debugger_i 1.1 640)
+++ 0.1(w)/debugger_interface.m Thu, 28 Oct 1999 20:19:39 +0200 jahier (collect/1_debugger_i 1.1 640)
@@ -177,7 +177,7 @@
 	;	browse(string)
 			% dynamically link the collect module with the 
 			% current execution
-	;	link_collect
+	;	link_collect(string)
 			% execute the collect command
 	;	collect
 			% retrieve the grade the current execution has been 
@@ -602,6 +602,22 @@
 	;
 		error("get_mmc_options: not a mmc_options request")
 	).
+%-----------------------------------------------------------------------------%
+
+:- pred get_object_file_name(debugger_request, string).
+:- mode get_object_file_name(in, out) is det.
+
+:- pragma export(get_object_file_name(in, out), "ML_DI_get_object_file_name").
+	% This predicate allows mercury_trace_external.c to retrieve the name 
+	% of the object to link from a `link_collect(ObjectFileName)' request.
+get_object_file_name(DebuggerRequest, ObjectFileName) :-
+	(
+		DebuggerRequest = link_collect(ObjectFileName1)
+	->
+		ObjectFileName = ObjectFileName1
+	;
+		error("get_object_file_name: not a link_collect request")
+	).
 
 %-----------------------------------------------------------------------------%
 
@@ -629,6 +645,18 @@
 		error("get_variable_name: not a browse request")
 	).
 
+%---------------------------------------------------------------------------%
+
+:- pred get_collecting_variable_type(T, type_info).
+:- mode get_collecting_variable_type(in, out) is det.
+
+:- pragma export(get_collecting_variable_type(in, out), 
+	"ML_DI_get_collecting_variable_type").
+	% This predicate allows mercury_trace_external.c to retrieve the name 
+	% of the type_info a collecting variable.
+get_collecting_variable_type(CollectVar, Type) :-
+	Type = type_of(CollectVar).
+
 %------------------------------------------------------------------------------%
 
 :- pred classify_request(debugger_request, int).
@@ -655,7 +683,7 @@
 classify_request(io_query(_),15).
 classify_request(mmc_options(_),16).
 classify_request(browse(_),17).
-classify_request(link_collect,18).
+classify_request(link_collect(_),18).
 classify_request(collect,19).
 classify_request(current_grade,20).
 
Index: 0.1/mercury_trace_external.c
--- 0.1/mercury_trace_external.c Thu, 28 Oct 1999 12:57:51 +0200 jahier (collect/3_mercury_tr 1.1 640)
+++ 0.1(w)/mercury_trace_external.c Thu, 28 Oct 1999 20:24:28 +0200 jahier (collect/3_mercury_tr 1.1 640)
@@ -32,6 +32,7 @@
 #include "debugger_interface.h"
 #include "collect_lib.h"
 #include "std_util.h"
+#include "mercury_deep_copy.h"
 
 #include <stdio.h>
 #include <errno.h>
@@ -43,8 +44,11 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <netdb.h>
-#include <dlfcn.h>
 #include <stdlib.h>
+#ifdef HAVE_DLFCN_H
+  #include <dlfcn.h>
+#endif
+
 
 /*
 ** This type must match the definition of classify_request in
@@ -93,14 +97,39 @@
 /*
 ** Type of a local variable that indicates in which mode the external 
 ** debugger is. When the external debugger is in mode:
-** - `searching', it tries to find an event that matches a forward move request,
-** - `reading_request', it reads a new request on the socket,
-** - `collecting', it is collecting information (after a `collect' request).
+** - `MR_searching', it tries to find an event that matches a forward 
+**   move request,
+** - `MR_reading_request', it reads a new request on the socket,
+** - `MR_collecting', it is collecting information (after a `collect' request).
 */
 typedef enum {
-	searching, reading_request, collecting
+	MR_searching, MR_reading_request, MR_collecting
 } MR_external_debugger_mode_type;
 
+static	MR_external_debugger_mode_type 
+	external_debugger_mode = MR_reading_request;
+
+/*
+** Global variable that is used to store the information collected during 
+** a collect request.
+*/
+
+static  Word	MR_collecting_variable;
+
+/*
+** Function pointer used to sent the collecting variable to the external 
+** debugger.
+*/
+
+static	void	(*send_collect_result_ptr)(Word, Word);
+
+/*
+** Variable generated during the dynamic linking that is needed to close
+** this linking properly.
+*/
+
+static	Word	*handle = NULL;
+
 /*
 ** Use a GNU C extension to enforce static type checking
 ** for printf-style functions. 
@@ -146,8 +175,15 @@
 			Integer *modules_list_length_ptr, Word *modules_list_ptr);
 static void	MR_get_mmc_options(Word debugger_request, 
 			String *mmc_options_ptr);
+static void	MR_get_object_file_name(Word debugger_request, 
+			String *objet_file_name_ptr);
 static void	MR_get_variable_name(Word debugger_request, String *var_name_ptr);
 static void	MR_trace_browse_one_external(MR_Var_Spec which_var);
+static void	MR_COLLECT_filter(Word (*filter_ptr)(Integer, Integer, Integer, 
+			Word, Word, String, String, String, Integer, Integer, 
+			Integer, String, Word, Word *), Unsigned seqno, 
+			Unsigned depth,	MR_Trace_Port port, 
+			const MR_Stack_Layout_Label *layout, const char *path);
 
 #if 0
 This pseudocode should go in the debugger process:
@@ -379,12 +415,29 @@
 MR_trace_final_external(void)
 {
 	/*
-	** This can only happen during a forward_move(),
-	** in which case we want to tell the debugger that
-	** no match was found.
+	** This can only happen during a forward_move or a 
+	** collect request. In the first case, we want to tell 
+	** the debugger that no match was found; in the second 
+	** one we send the result of the collect activity.
 	*/
-	MR_send_message_to_socket("forward_move_match_not_found");
 
+	switch(external_debugger_mode) {
+	case MR_searching:
+	       	MR_send_message_to_socket("forward_move_match_not_found");
+		break;
+
+	case MR_collecting:
+		(*send_collect_result_ptr)(
+			(Word) MR_collecting_variable, 
+			(Word) &MR_debugger_socket_out);
+			#if defined(HAVE_DLFCN_H)&&defined(HAVE_DLCLOSE)
+				dlclose((void *)handle);
+			#endif
+		break;
+
+	default:
+		fatal_error("Error in the external debugger");
+	}
 	/*
 	** Maybe we should loop to process requests from the
 	** debugger socket here?  Currently we just return,
@@ -397,16 +450,11 @@
 Code *
 MR_trace_event_external(MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info)
 {
-	static MR_external_debugger_mode_type 
-			external_debugger_mode = reading_request;
 	static Word	search_data;
-	static Word	collecting_variable;
-	static Word	(*initialize_ptr)(Word *) = NULL;
+	static void	(*initialize_ptr)(Word *) = NULL;
 	static Word    	(*filter_ptr)(Integer, Integer, Integer, MR_Trace_Port,
 				MR_PredFunc, String, String, String, Integer,
 				Integer, Integer, String, Word, Word *) = NULL;
-	static Word	(*send_collect_result_ptr)(Word, Word);
-	static Word    	*handle = NULL;
 	static bool    	collect_linked = FALSE;
 	Integer		debugger_request_type;
 	Integer		live_var_number;
@@ -428,6 +476,7 @@
 	Integer		modules_list_length;
 	Word		modules_list;
 	static String	MR_mmc_options;
+	static String	MR_object_file_name;
 
 	MR_trace_enabled = FALSE;
 
@@ -445,7 +494,7 @@
 
 	/* 
 	** MR_mmc_options contains the options to pass to mmc when compiling 
-	** queries. We initialise it to the String "".
+	** queries. We initialize it to the String "".
 	*/
 	MR_TRACE_CALL_MERCURY(ML_DI_init_mercury_string(&MR_mmc_options));
 
@@ -453,8 +502,8 @@
 		event_info->MR_saved_regs);
 
 
-	switch((MR_external_debugger_mode_type) external_debugger_mode) {
-		case searching:
+	switch(external_debugger_mode) {
+		case MR_searching:
 			/* 
 			** XXX should also pass registers here, since they're 
 			** needed for checking for matches with the arguments 
@@ -464,56 +513,32 @@
 			{
 				MR_send_message_to_socket(
 					"forward_move_match_found");
-				external_debugger_mode = reading_request;
+				external_debugger_mode = MR_reading_request;
 			} else {
 				goto done;
 			}
 			break;
 
-		case collecting:
-			if (seqno == 1 && port == MR_PORT_EXIT) {
-				/* The end of the execution is reached */
-				(*send_collect_result_ptr)(
-						collecting_variable, 
-						(Word) &MR_debugger_socket_out);
-				#if defined(HAVE_DLFCN_H)&&defined(HAVE_DLCLOSE)
-					dlclose((void *)handle);
-				#endif
-			} else {
-				/* 
-				** XXX Add a another request that takes 
-				** arguments into account. We need two kinds 
-				** of request in order to not penalize the 
-				** performance of collect in the cases where 
-				** arguments are not used.
-				**  
-				** arguments = MR_make_var_list(layout, 
-				**	saved_regs);
-				*/
-				(*filter_ptr)(
-			MR_trace_event_number,
-			seqno,
-			depth,
-			port,
-			layout->MR_sll_entry->MR_sle_user.MR_user_pred_or_func,
-			(String)
-			layout->MR_sll_entry->MR_sle_user.MR_user_decl_module,
-			(String)
-			layout->MR_sll_entry->MR_sle_user.MR_user_def_module,
-			(String)
-			layout->MR_sll_entry->MR_sle_user.MR_user_name,
-			layout->MR_sll_entry->MR_sle_user.MR_user_arity,
-			layout->MR_sll_entry->MR_sle_user.MR_user_mode,
-			layout->MR_sll_entry->MR_sle_detism,
-			(String) path,
-			(Word) collecting_variable,
-			&collecting_variable);
-				goto done;
-			}
-			
-			break;
+		case MR_collecting:
+			/* 
+			** XXX Add a another request that takes 
+			** arguments into account. We need two kinds 
+			** of request in order to not penalize the 
+			** performance of collect in the cases where 
+			** arguments are not used.
+			**  
+			** arguments = MR_make_var_list(layout, saved_regs);
+			*/
+			MR_COLLECT_filter(
+				*filter_ptr, 
+				(Unsigned) seqno, 
+				(Unsigned) depth, 
+				(MR_Trace_Port) port,
+				layout, 
+				path);
+			goto done;
 
-		case reading_request:
+		case MR_reading_request:
 			break;
 
 		default:
@@ -534,7 +559,7 @@
 						"FORWARD_MOVE\n");
 				}
 				search_data = debugger_request;
-			        external_debugger_mode = searching;
+			        external_debugger_mode = MR_searching;
 				goto done;
 
 			case MR_REQUEST_CURRENT_LIVE_VAR_NAMES:
@@ -730,23 +755,40 @@
 			case MR_REQUEST_LINK_COLLECT:
 			  {
 			        Char	result;
+				Word	MR_collecting_variable_type;
+				Word	*MR_collecting_variable_type_info=NULL;
 
 				if (MR_debug_socket) {
 					fprintf(stderr, "\nMercury runtime: "
 						"REQUEST_LINK_COLLECT\n");
 				}
+				MR_get_object_file_name(debugger_request,
+					    &MR_object_file_name);
 				MR_TRACE_CALL_MERCURY(
 					ML_DI_link_collect(
+			       		    MR_object_file_name,
 					    (Word *) &filter_ptr,
 					    (Word *) &initialize_ptr,
 					    (Word *) &send_collect_result_ptr,
 					    (Word *) &handle,
-					    (Char *) &result
+					    &result
 					    ));
 				collect_linked = (result == 'y');
 				if (collect_linked) {
 					MR_send_message_to_socket(
 						"link_collect_succeeded");
+					MR_TRACE_CALL_MERCURY(
+					    ML_DI_get_collecting_variable_type(
+						(Word) 
+						MR_collecting_variable_type_info,
+						MR_collecting_variable,
+						(Word *) 
+						&MR_collecting_variable_type));
+					MR_collecting_variable = 
+					    MR_make_permanent(
+						MR_collecting_variable,
+						(Word *) 
+						MR_collecting_variable_type);
 				} else {
 					MR_send_message_to_socket(
 						"link_collect_failed");
@@ -764,33 +806,23 @@
 				if (collect_linked) {
 					MR_send_message_to_socket(
 						"collect_linked");
-					external_debugger_mode = collecting;
+					external_debugger_mode = MR_collecting;
 					MR_TRACE_CALL_MERCURY(
-					  (*initialize_ptr)(&collecting_variable));
+					  (*initialize_ptr)(&MR_collecting_variable));
 
 					/*
 					** In order to perform the collect from
 					** the current event, we need to call 
 					** filter once here.
 					*/
-					(*filter_ptr)(
-			MR_trace_event_number,
-			seqno,
-			depth,
-			port,
-			layout->MR_sll_entry->MR_sle_user.MR_user_pred_or_func,
-			(String)
-			layout->MR_sll_entry->MR_sle_user.MR_user_decl_module,
-			(String)
-			layout->MR_sll_entry->MR_sle_user.MR_user_def_module,
-			(String)
-			layout->MR_sll_entry->MR_sle_user.MR_user_name,
-			layout->MR_sll_entry->MR_sle_user.MR_user_arity,
-			layout->MR_sll_entry->MR_sle_user.MR_user_mode,
-			layout->MR_sll_entry->MR_sle_detism,
-			(String) path,
-			(Word) collecting_variable,
-			&collecting_variable);
+					MR_COLLECT_filter(
+						*filter_ptr, 
+						(Unsigned) seqno, 
+						(Unsigned) depth, 
+						(MR_Trace_Port) port,
+						layout, 
+						path);
+					
 					goto done;
 				} else {
 					MR_send_message_to_socket(
@@ -1360,6 +1392,16 @@
 }
 
 static void
+MR_get_object_file_name(Word debugger_request, String *object_file_name_ptr)
+{
+	MR_TRACE_CALL_MERCURY(
+		ML_DI_get_object_file_name(
+			debugger_request, 
+			object_file_name_ptr);
+		);
+}
+
+static void
 MR_get_variable_name(Word debugger_request, String *var_name_ptr)
 {
 	MR_TRACE_CALL_MERCURY(
@@ -1387,6 +1429,34 @@
 	if (problem != NULL) {
 		MR_send_message_to_socket_format("error(\"%s\").\n", problem);
 	}
+}
+
+
+/*
+** This function calls the collect filtering predicate defined by the user
+** and dynamically link with the execution.
+*/
+static void
+MR_COLLECT_filter(Word (*filter_ptr)(Integer, Integer, Integer, Word, Word, 
+	String, String, String, Integer, Integer, Integer, String, Word, Word *), 
+       	Unsigned seqno, Unsigned depth, MR_Trace_Port port, 
+	const MR_Stack_Layout_Label *layout, const char *path)
+{		
+	MR_TRACE_CALL_MERCURY((*filter_ptr)(
+		MR_trace_event_number,
+		seqno,
+		depth,
+		port,
+		layout->MR_sll_entry->MR_sle_user.MR_user_pred_or_func,
+		(String) layout->MR_sll_entry->MR_sle_user.MR_user_decl_module,
+		(String) layout->MR_sll_entry->MR_sle_user.MR_user_def_module,
+		(String) layout->MR_sll_entry->MR_sle_user.MR_user_name,
+		layout->MR_sll_entry->MR_sle_user.MR_user_arity,
+		layout->MR_sll_entry->MR_sle_user.MR_user_mode,
+		layout->MR_sll_entry->MR_sle_detism,
+		(String) path,
+		MR_collecting_variable,
+		&MR_collecting_variable));
 }
 
 #endif /* MR_USE_EXTERNAL_DEBUGGER */
--- collect.op	Thu Oct 28 20:31:08 1999
+++ projet_en_cours/rmdb/source/collect.op	Thu Oct 28 16:24:53 1999
@@ -70,7 +70,7 @@
 event until the end of the execution; \n\
  *) foldl/4 is the classical fold predicate operating left-to-right. \n\
  \n\
-Hence, collect/2 does the same thing as collect_spec/2 except it operates \
+collect/2 does the same thing as collect_spec/2 except it operates \
 on the fly without creating any list of events."
 	).
 
@@ -107,7 +107,7 @@
 		).\n\
 '\n\
 Then the command `collect(count_call, Result)' will unify Result with the \
-number of calls that occurs during the program execution.\
+number of calls that occur during the program execution.\
 "
 	).
 
@@ -161,16 +161,17 @@
 		"mmc --grade ", 
 		Grade,
 		" -O6",
-		" -c --pic-reg collect.m"], Command1),
-	sh(Command1), 
+		" -c --pic-reg collect.m"], Command1), 
 	print(Command1), nl,
+	sh(Command1),
+	exists("collect.o"),
 	concat_string([
 		"ml --grade ", 
 		Grade, 
 		" --make-shared-lib ",
 		"--pic-reg -o collect.so collect.o"], Command2),
-	sh(Command2), 
 	print(Command2), nl,
+	sh(Command2), 
 	exists("collect.so"),
 	!,
 	opium_write_debug("collect.m has been compiled successfully.\n").
@@ -293,7 +294,7 @@
 		write("use generate_collect/1 primitive before.\n"),
 		fail
 	),
-	send_message_to_socket(link_collect),
+	send_message_to_socket(link_collect("\"./collect.so\"")),
 	read_message_from_socket(Result),
 	( Result = link_collect_succeeded ->
 		opium_write_debug("collect.so has been linked successfully.\n")

--- collect.in	Thu Oct 28 20:32:15 1999
+++ projet_en_cours/rmdb/source/collect.in	Thu Oct 28 19:34:41 1999
@@ -23,13 +23,13 @@
 %------------------------------------------------------------------------------%
 :- implementation.
 
-:- pragma export(initialize(out), "Collect_initialize").
+:- pragma export(initialize(out), "ML_COLLECT_initialize").
 
 :- pragma export(filter(in, in, in, in, in, in, in, in, in, in, in, in, 
-	acc_in, acc_out), "Collect_filter").
+	acc_in, acc_out), "ML_COLLECT_filter").
 
 :- pragma export(send_collect_result(in, in, di, uo), 
-	"Collect_send_collect_result").
+	"ML_COLLECT_send_collect_result").
 
 :- import_module int, io.
--- collect_lib.m.old	Thu Oct 28 20:39:46 1999
+++ collect_lib.m	Thu Oct 28 19:33:29 1999
@@ -44,16 +44,16 @@
 :- import_module io, char.
 
 % dynamically link the collect module; 
-:- pred link_collect(c_pointer, c_pointer, c_pointer, c_pointer, char,
+:- pred link_collect(string, c_pointer, c_pointer, c_pointer, c_pointer, char,
 	io__state, io__state).
-:- mode link_collect(out, out, out, out, out, di, uo) is det.
+:- mode link_collect(in, out, out, out, out, out, di, uo) is det.
 
 %------------------------------------------------------------------------------%
 :- implementation.
 :- import_module int, list, std_util, io, char.
-:- import_module name_mangle, dl.
+:- import_module dl.
 
-:- pragma export(link_collect(out, out, out, out, out, di, uo), 
+:- pragma export(link_collect(in, out, out, out, out, out, di, uo), 
 	"ML_DI_link_collect").
 
 % We need Handle to be able to close the shared object (dlclose) later on.
@@ -61,12 +61,12 @@
 % for performance reasons; indeed, filter will be called at every events
 % so we don't want to pay the price of the maybe variable de-construction
 % at each event.
-link_collect(Filter, Initialize, SendResult, HandlePtr, Result) -->
+link_collect(ObjetFile, Filter, Initialize, SendResult, HandlePtr, Result) -->
 	%
 	% Link in the object code for the module `collect' from
 	% the file `collect.so'.
 	%
-	dl__open("./collect.so", lazy, local, MaybeHandle),
+	dl__open(ObjetFile, lazy, local, MaybeHandle),
 	(	
 		{ MaybeHandle = error(Msg) },
 		print("dlopen failed: "), print(Msg), nl,
@@ -77,14 +77,13 @@
 		{ Result = 'n' }
 	;
 		{ MaybeHandle = ok(Handle) },
-		%
-		% Look up the address of the first mode (mode number 0)
-		% of the predicates initialize/1 and filter/14  in the 
-		% module collect.
-		%
-		dl__sym(Handle, "Collect_initialize", MaybeInitialize),
-		dl__sym(Handle, "Collect_filter", MaybeFilter),
-		dl__sym(Handle, "Collect_send_collect_result", MaybeSendResult),
+ 		%
+ 		% Look up the address of the C functions corresponding to the 
+		% initialize/1 and filter/14 predicates in the collect module.
+ 		%
+		dl__sym(Handle, "ML_COLLECT_initialize", MaybeInitialize),
+		dl__sym(Handle, "ML_COLLECT_filter", MaybeFilter),
+		dl__sym(Handle, "ML_COLLECT_send_collect_result", MaybeSendResult),
 		(
 			{ MaybeInitialize = ok(Initialize0) },
 			{ MaybeFilter = ok(Filter0) },
@@ -108,13 +107,3 @@
 		[will_not_call_mercury, thread_safe],
 		"(Pointer = (Word) NULL)").
  
-
-:- type io_pred == pred(io__state, io__state).
-:- inst io_pred == (pred(di, uo) is det).
-
-:- func inst_cast(io_pred) = io_pred.
-:- mode inst_cast(in) = out(io_pred) is det.
-
-:- pragma c_code(inst_cast(X::in) = (Y::out(io_pred)),
-	[will_not_call_mercury, thread_safe], "Y = X").
-


-- 
R1.


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