[m-dev.] diff: split up ml_code_gen.m

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Dec 29 19:08:33 AEDT 1999


Estimated hours taken: 3.5

Split up ml_code_gen.m into four modules.

compiler/ml_call_gen.m:
	New module, contains the code to do MLDS code generation
	for calls and builtins.

compiler/ml_unify_gen.m:
	New module, contains the code to do MLDS code generation
	for unifications.

compiler/ml_code_util.m:
	New module, contains stuff shared between
	ml_call_gen.m, ml_unify_gen.m, and ml_code_gen.m.

compiler/ml_code_gen.m:
	Move about 60% of the code here into the three new
	modules.

----------

The full diff for this one is long (>200k) and not very interesting, since
the only change I made was to move code around.  So rather than posting the
full diff, I'll just post an extract from it showing the interfaces for
the new modules.

In the unlikely event that someone wants to have a look at the full diff,
it's available in ~fjh/ws/alpha/compiler/CHANGES.mlds8.diff on murlibobo.

----------

+++ ml_call_gen.m	Wed Dec 29 18:20:47 1999
@@ -0,0 +1,814 @@
+%-----------------------------------------------------------------------------%
+% Copyright (C) 1999 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+
+% File: ml_call_gen.m
+% Main author: fjh
+
+% This module is part of the MLDS code generator.
+% It handles code generation of procedures calls,
+% calls to builtins, and other closely related stuff.
+
+%-----------------------------------------------------------------------------%
+
+:- module ml_call_gen.
+:- interface.
+
+:- import_module prog_data.
+:- import_module hlds_pred, hlds_goal.
+:- import_module mlds, ml_code_util.
+:- import_module llds. % XXX for `code_model'
+
+:- import_module list.
+
+	% Generate MLDS code for an HLDS generic_call goal.
+	% This includes boxing/unboxing the arguments if necessary.
+:- pred ml_gen_generic_call(generic_call, list(prog_var), list(mode),
+		code_model, prog_context, mlds__defns, mlds__statements,
+		ml_gen_info, ml_gen_info).
+:- mode ml_gen_generic_call(in, in, in, in, in, out, out, in, out) is det.
+
+	%
+	% Generate MLDS code for an HLDS procedure call, making sure to
+	% box/unbox the arguments if necessary.
+	%
+:- pred ml_gen_call(pred_id, proc_id, list(var_name), list(mlds__lval),
+		list(prog_data__type), code_model, prog_context,
+		mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
+:- mode ml_gen_call(in, in, in, in, in, in, in, out, out, in, out) is det.
+
+	%
+	% Generate MLDS code for a call to a builtin procedure.
+	%
+:- pred ml_gen_builtin(pred_id, proc_id, list(prog_var), code_model,
+		prog_context, mlds__defns, mlds__statements,
+		ml_gen_info, ml_gen_info).
+:- mode ml_gen_builtin(in, in, in, in, in, out, out, in, out) is det.
+
+	%
+	% Generate an rval containing the address of the specified procedure.
+	%
+:- pred ml_gen_proc_addr_rval(pred_id, proc_id, mlds__rval,
+		ml_gen_info, ml_gen_info).
+:- mode ml_gen_proc_addr_rval(in, in, out, in, out) is det.
+
+	% Given a source type and a destination type,
+	% and given an source rval holding a value of the source type,
+	% produce an rval that converts the source rval to the destination type.
+	%
+:- pred ml_gen_box_or_unbox_rval(prog_type, prog_type, mlds__rval, mlds__rval).
+:- mode ml_gen_box_or_unbox_rval(in, in, in, out) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module hlds_module.
+:- import_module builtin_ops.
+:- import_module type_util, mode_util.
+
+:- import_module bool, string, std_util, term, varset, require.
+
...
diff -N ml_unify_gen.m
--- /dev/null	Wed Dec 29 18:05:50 1999
+++ ml_unify_gen.m	Wed Dec 29 17:52:55 1999
@@ -0,0 +1,1137 @@
+%-----------------------------------------------------------------------------%
+% Copyright (C) 1999 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+
+% File: ml_unify_gen.m
+% Main author: fjh
+
+% This module is part of the MLDS code generator.
+% It handles MLDS code generation for unifications.
+
+%-----------------------------------------------------------------------------%
+
+:- module ml_unify_gen.
+:- interface.
+
+:- import_module prog_data.
+:- import_module hlds_data, hlds_goal.
+:- import_module mlds, ml_code_util.
+:- import_module llds. % XXX for `code_model'
+
+%-----------------------------------------------------------------------------%
+
+	% Generate MLDS code for a unification.
+	%
+:- pred ml_gen_unification(unification, code_model, prog_context,
+		mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
+:- mode ml_gen_unification(in, in, in, out, out, in, out) is det.
+
+	% Convert a cons_id for a given type to a cons_tag.
+	%
+:- pred ml_cons_id_to_tag(cons_id, prog_type, cons_tag,
+		ml_gen_info, ml_gen_info).
+:- mode ml_cons_id_to_tag(in, in, out, in, out) is det.
+
+	% ml_gen_tag_test(Var, ConsId, Defns, Statements, Expression):
+	%	Generate code to perform a tag test.
+	%
+	%	The test checks whether Var has the functor specified by
+	%	ConsId.  The generated code may contain Defns, Statements
+	%	and an Expression.  The Expression is a boolean rval.
+	%	After execution of the Statements, Expression will evaluate
+	%	to true iff the Var has the functor specified by ConsId.
+	%
+:- pred ml_gen_tag_test(prog_var, cons_id, mlds__defns, mlds__statements,
+		mlds__rval, ml_gen_info, ml_gen_info).
+:- mode ml_gen_tag_test(in, in, out, out, out, in, out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module hlds_pred, hlds_module, hlds_out, builtin_ops.
+:- import_module ml_call_gen, prog_util, type_util, mode_util.
+:- import_module code_util. % XXX needed for `code_util__cons_id_to_tag'.
+
+:- import_module int, string, list, require, std_util, term, varset.
+
+%-----------------------------------------------------------------------------%
+
--- ml_code_gen.m	1999/12/21 10:28:01	1.24
+++ ml_code_gen.m	1999/12/29 07:56:43
@@ -582,7 +582,7 @@
 
 :- interface.
 
-:- import_module hlds_module, hlds_pred, mlds.
+:- import_module hlds_module, mlds.
 :- import_module io.
 
 %-----------------------------------------------------------------------------%
@@ -593,35 +593,20 @@
 :- pred ml_code_gen(module_info, mlds, io__state, io__state).
 :- mode ml_code_gen(in, out, di, uo) is det.
 
-	% Generate the mlds__pred_label and module name
-	% for a given procedure.
-	%
-:- pred ml_gen_pred_label(module_info, pred_id, proc_id,
-		mlds__pred_label, mlds_module_name).
-:- mode ml_gen_pred_label(in, in, in, out, out) is det.
-
-	% Generate the function prototype for a given procedure.
-	%
-:- func ml_gen_proc_params(module_info, pred_id, proc_id) = mlds__func_params.
-
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
 
-:- import_module ml_base_type_info.
+:- import_module ml_base_type_info, ml_call_gen, ml_unify_gen, ml_code_util.
 :- import_module llds. % XXX needed for `code_model'.
 :- import_module export, llds_out. % XXX needed for pragma C code
-:- import_module code_util. % XXX needed for `code_util__compiler_generated'.
-			    % and `code_util__cons_id_to_tag'.
-:- import_module goal_util.
-:- import_module hlds_goal, hlds_data, prog_data, special_pred.
-:- import_module hlds_out, builtin_ops, passes_aux, type_util, mode_util.
-:- import_module prog_util.
-:- import_module globals, options.
+:- import_module hlds_pred, hlds_goal, hlds_data, prog_data.
+:- import_module goal_util, type_util, mode_util, builtin_ops.
+:- import_module passes_aux.
 
-:- import_module string, int, bool, varset, term.
-:- import_module list, map, set, stack.
+:- import_module string.
+:- import_module list, map, set.
 :- import_module require, std_util.
 
 %-----------------------------------------------------------------------------%
diff -N ml_code_util.m
--- /dev/null	Wed Dec 29 18:05:50 1999
+++ ml_code_util.m	Wed Dec 29 18:18:57 1999
@@ -0,0 +1,1220 @@
+%-----------------------------------------------------------------------------%
+% Copyright (C) 1999 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+
+% File: ml_code_util.m
+% Main author: fjh
+
+% This module is part of the MLDS code generator.
+% It defines the ml_gen_info type and its access routines.
+
+%-----------------------------------------------------------------------------%
+
+:- module ml_code_util.
+:- interface.
+
+:- import_module prog_data.
+:- import_module hlds_module, hlds_pred.
+:- import_module mlds.
+:- import_module llds. % XXX for `code_model'.
+
+:- import_module bool, int, list, map, std_util.
+
+%-----------------------------------------------------------------------------%
+%
+% Various utility routines used for MLDS code generation.
+%
+
+	% A convenient abbreviation.
+	%
+:- type prog_type == prog_data__type.
+
+	% Generate an MLDS assignment statement.
+:- func ml_gen_assign(mlds__lval, mlds__rval, prog_context) = mlds__statement.
+
+	% Generate a block statement, i.e. `{ <Decls>; <Statements>; }'.
+	% But if the block consists only of a single statement with no
+	% declarations, then just return that statement.
+	%
+:- func ml_gen_block(mlds__defns, mlds__statements, prog_context) =
+		mlds__statement.
+
+	% ml_join_decls:
+	% 	Join two statement lists and their corresponding
+	% 	declaration lists in sequence.
+	% 
+	% 	If the statements have no declarations in common,
+	% 	then their corresponding declaration lists will be
+	% 	concatenated together into a single list of declarations.
+	% 	But if they have any declarations in common, then we
+	% 	put each statement list and its declarations into
+	% 	a block, so that the declarations remain local to
+	% 	each statement list.
+	% 
+:- pred ml_join_decls(mlds__defns, mlds__statements,
+		mlds__defns, mlds__statements, prog_context,
+		mlds__defns, mlds__statements).
+:- mode ml_join_decls(in, in, in, in, in, out, out) is det.
+
+	% ml_combine_conj:
+	%	Given closures to generate code for two conjuncts,
+	%	generate code for their conjunction.
+
+:- type gen_pred == pred(mlds__defns, mlds__statements,
+		ml_gen_info, ml_gen_info).
+:- inst gen_pred = (pred(out, out, in, out) is det).
+
+:- pred ml_combine_conj(code_model, prog_context, gen_pred, gen_pred,
+		mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
+:- mode ml_combine_conj(in, in, in(gen_pred), in(gen_pred),
+		out, out, in, out) is det.
+
+	% Given a function label and the statement which will comprise
+	% the function body for that function, generate an mlds__defn
+	% which defines that function.
+	%
+:- pred ml_gen_nondet_label_func(ml_label_func, prog_context,
+		mlds__statement, mlds__defn, ml_gen_info, ml_gen_info).
+:- mode ml_gen_nondet_label_func(in, in, in, out, in, out) is det.
+
+	% Given a function label, the function parameters, and the statement
+	% which will comprise the function body for that function,
+	% generate an mlds__defn which defines that function.
+	%
+:- pred ml_gen_label_func(ml_label_func, mlds__func_params, prog_context,
+		mlds__statement, mlds__defn, ml_gen_info, ml_gen_info).
+:- mode ml_gen_label_func(in, in, in, in, out, in, out) is det.
+
+	% Call error/1 with a "Sorry, not implemented" message.
+	%
+:- pred sorry(string::in) is erroneous.
+
+%-----------------------------------------------------------------------------%
+%
+% Routines for generating function declarations (i.e. mlds__func_params).
+%
+
+	% Generate the function prototype for a given procedure.
+	%
+:- func ml_gen_proc_params(module_info, pred_id, proc_id) = mlds__func_params.
+
+	% Generate the function prototype for a procedure with the
+	% given argument types, modes, and code model.
+	%
+:- func ml_gen_params(module_info, list(string), list(prog_type),
+		list(mode), code_model) = mlds__func_params.
+
+%-----------------------------------------------------------------------------%
+%
+% Routines for generating labels and entity names.
+%
+
+	% Generate the mlds__entity_name for the entry point function
+	% corresponding to a given procedure.
+	%
+:- func ml_gen_proc_label(module_info, pred_id, proc_id) = mlds__entity_name.
+
+	% Generate an mlds__entity_name for a continuation function
+	% with the given sequence number.  The pred_id and proc_id
+	% specify the procedure that this continuation function
+	% is part of.
+	%
+:- func ml_gen_nondet_label(module_info, pred_id, proc_id, ml_label_func)
+		= mlds__entity_name.
+
+	% Allocate a new function label and return an rval containing
+	% the function's address.
+	%
+:- pred ml_gen_new_func_label(ml_label_func, mlds__rval,
+		ml_gen_info, ml_gen_info).
+:- mode ml_gen_new_func_label(out, out, in, out) is det.
+
+	% Generate the mlds__pred_label and module name
+	% for a given procedure.
+	%
+:- pred ml_gen_pred_label(module_info, pred_id, proc_id,
+		mlds__pred_label, mlds_module_name).
+:- mode ml_gen_pred_label(in, in, in, out, out) is det.
+
+%-----------------------------------------------------------------------------%
+%
+% Routines for dealing with variables
+%
+
+	% Generate a list of the mlds__lvals corresponding to a
+	% given list of prog_vars.
+	%
+:- pred ml_gen_var_list(list(prog_var), list(mlds__lval),
+		ml_gen_info, ml_gen_info).
+:- mode ml_gen_var_list(in, out, in, out) is det.
+
+	% Generate the mlds__lval corresponding to a given prog_var.
+	%
+:- pred ml_gen_var(prog_var, mlds__lval, ml_gen_info, ml_gen_info).
+:- mode ml_gen_var(in, out, in, out) is det.
+
+	% Lookup the types of a list of variables.
+	%
+:- pred ml_variable_types(list(prog_var), list(prog_type),
+		ml_gen_info, ml_gen_info).
+:- mode ml_variable_types(in, out, in, out) is det.
+
+	% Lookup the type of a variable.
+	%
+:- pred ml_variable_type(prog_var, prog_type, ml_gen_info, ml_gen_info).
+:- mode ml_variable_type(in, out, in, out) is det.
+
+	% Generate the MLDS variable names for a list of variables.
+	%
+:- func ml_gen_var_names(prog_varset, list(prog_var)) = list(mlds__var_name).
+
+	% Generate the MLDS variable name for a variable.
+	%
+:- func ml_gen_var_name(prog_varset, prog_var) = mlds__var_name.
+
+	% Qualify the name of the specified variable
+	% with the current module name.
+	%
+:- pred ml_qualify_var(mlds__var_name, mlds__lval,
+		ml_gen_info, ml_gen_info).
+:- mode ml_qualify_var(in, out, in, out) is det.
+
+	% Generate a declaration for an MLDS variable, given its HLDS type.
+	%
+:- func ml_gen_var_decl(var_name, prog_type, mlds__context) = mlds__defn.
+
+	% Generate a declaration for an MLDS variable, given its MLDS type.
+	%
+:- func ml_gen_mlds_var_decl(var_name, mlds__type, mlds__context) = mlds__defn.
+
+%-----------------------------------------------------------------------------%
+%
+% Routines for handling success and failure
+%
+
+	% Generate code to succeed in the given code_model.
+	%
+:- pred ml_gen_success(code_model, prog_context, mlds__statements,
+			ml_gen_info, ml_gen_info).
+:- mode ml_gen_success(in, in, out, in, out) is det.
+
+	% Generate code to fail in the given code_model.
+	%
+:- pred ml_gen_failure(code_model, prog_context, mlds__statements,
+			ml_gen_info, ml_gen_info).
+:- mode ml_gen_failure(in, in, out, in, out) is det.
+
+	% Generate the declaration for the built-in `succeeded' flag.
+	% (`succeeded' is a boolean variable used to record
+	% the success or failure of model_semi procedures.)
+	%
+:- func ml_gen_succeeded_var_decl(mlds__context) = mlds__defn.
+
+	% Return the lval for the `succeeded' flag.
+	% (`succeeded' is a boolean variable used to record
+	% the success or failure of model_semi procedures.)
+	%
+:- pred ml_success_lval(mlds__lval, ml_gen_info, ml_gen_info).
+:- mode ml_success_lval(out, in, out) is det.
+
+	% Return an rval which will test the value of the `succeeded' flag.
+	% (`succeeded' is a boolean variable used to record
+	% the success or failure of model_semi procedures.)
+	%
+:- pred ml_gen_test_success(mlds__rval, ml_gen_info, ml_gen_info).
+:- mode ml_gen_test_success(out, in, out) is det.
+	
+	% Generate code to set the `succeeded' flag to the
+	% specified truth value.
+	%
+:- pred ml_gen_set_success(mlds__rval, prog_context, mlds__statement,
+				ml_gen_info, ml_gen_info).
+:- mode ml_gen_set_success(in, in, out, in, out) is det.
+
+	% Return rvals for the success continuation that was
+	% passed as the current function's argument(s).
+	% The success continuation consists of two parts, the
+	% `cont' argument, and the `cont_env' argument.
+	% The `cont' argument is a continuation function that
+	% will be called when a model_non goal succeeds.
+	% The `cont_env' argument is a pointer to the environment (set
+	% of local variables in the containing procedure) for the continuation
+	% function.  (If we're using gcc nested function, the `cont_env'
+	% is not used.)
+	%
+:- pred ml_initial_cont(success_cont, ml_gen_info, ml_gen_info).
+:- mode ml_initial_cont(out, in, out) is det.
+
+	% Generate code to call the current success continuation.
+	% This is used for generating success when in a model_non context.
+	%
+:- pred ml_gen_call_current_success_cont(prog_context, mlds__statement,
+			ml_gen_info, ml_gen_info).
+:- mode ml_gen_call_current_success_cont(in, out, in, out) is det.
+
+%-----------------------------------------------------------------------------%
+%
+% Routines for dealing with the environment pointer
+% used for nested functions.
+%
+
+	% Return an rval for a pointer to the current environment
+	% (the set of local variables in the containing procedure).
+	% Note that we generate this as a dangling reference.
+	% The ml_elim_nested pass will insert the declaration
+	% of the env_ptr variable.
+:- pred ml_get_env_ptr(mlds__rval, ml_gen_info, ml_gen_info).
+:- mode ml_get_env_ptr(out, in, out) is det.
+
+	% Return an rval for a pointer to the current environment
+	% (the set of local variables in the containing procedure).
+:- pred ml_declare_env_ptr_arg(pair(mlds__entity_name, mlds__type),
+		ml_gen_info, ml_gen_info).
+:- mode ml_declare_env_ptr_arg(out, in, out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+%
+% The `ml_gen_info' ADT.
+%
+
+	%
+	% The `ml_gen_info' type holds information used during
+	% MLDS code generation for a given procedure.
+	%
+:- type ml_gen_info.
+
+	% initialize the ml_gen_info, so that it is
+	% ready for generating code for the given procedure
+:- func ml_gen_info_init(module_info, pred_id, proc_id) = ml_gen_info.
+
+	% accessor predicates; these just get the specified
+	% information from the ml_gen_info
+
+:- pred ml_gen_info_get_module_info(ml_gen_info, module_info).
+:- mode ml_gen_info_get_module_info(in, out) is det.
+
+:- pred ml_gen_info_get_module_name(ml_gen_info, mercury_module_name).
+:- mode ml_gen_info_get_module_name(in, out) is det.
+
+:- pred ml_gen_info_get_pred_id(ml_gen_info, pred_id).
+:- mode ml_gen_info_get_pred_id(in, out) is det.
+
+:- pred ml_gen_info_get_proc_id(ml_gen_info, proc_id).
+:- mode ml_gen_info_get_proc_id(in, out) is det.
+
+:- pred ml_gen_info_get_varset(ml_gen_info, prog_varset).
+:- mode ml_gen_info_get_varset(in, out) is det.
+
+:- pred ml_gen_info_get_var_types(ml_gen_info, map(prog_var, prog_type)).
+:- mode ml_gen_info_get_var_types(in, out) is det.
+
+:- pred ml_gen_info_get_output_vars(ml_gen_info, list(prog_var)).
+:- mode ml_gen_info_get_output_vars(in, out) is det.
+
+:- pred ml_gen_info_use_gcc_nested_functions(bool, ml_gen_info, ml_gen_info).
+:- mode ml_gen_info_use_gcc_nested_functions(out, in, out) is det.
+
+	% A number corresponding to an MLDS nested function which serves as a
+	% label (i.e. a continuation function).
+:- type ml_label_func == mlds__func_sequence_num.
+
+	% Generate a new function label number.
+	% This is used to give unique names to the nested functions
+	% used when generating code for nondet procedures.
+:- pred ml_gen_info_new_func_label(ml_label_func, ml_gen_info, ml_gen_info).
+:- mode ml_gen_info_new_func_label(out, in, out) is det.
+
+	% Generate a new commit label number.
+	% This is used to give unique names to the labels
+	% used when generating code for commits.
+:- type commit_sequence_num == int.
+:- pred ml_gen_info_new_commit_label(commit_sequence_num,
+		ml_gen_info, ml_gen_info).
+:- mode ml_gen_info_new_commit_label(out, in, out) is det.
+
+	%
+	% A success continuation specifies the (rval for the variable
+	% holding the address of the) function that a nondet procedure
+	% should call if it succeeds, and possible also the
+	% (rval for the variable holding) the environment pointer
+	% for that function.
+	%
+:- type success_cont 
+	--->	success_cont(
+			mlds__rval,	% function pointer
+			mlds__rval	% environment pointer
+				% note that if we're using nested
+				% functions then the environment
+				% pointer will not be used
+		).
+
+	%
+	% The ml_gen_info contains a stack of success continuations.
+	% The following routines provide access to that stack.
+	%
+
+:- pred ml_gen_info_push_success_cont(success_cont,
+			ml_gen_info, ml_gen_info).
+:- mode ml_gen_info_push_success_cont(in, in, out) is det.
+
+:- pred ml_gen_info_pop_success_cont(ml_gen_info, ml_gen_info).
+:- mode ml_gen_info_pop_success_cont(in, out) is det.
+
+:- pred ml_gen_info_current_success_cont(success_cont,
+			ml_gen_info, ml_gen_info).
+:- mode ml_gen_info_current_success_cont(out, in, out) is det.
+
+	%
+	% The ml_gen_info contains a list of extra definitions
+	% of functions or global constants which should be inserted
+	% before the definition of the function for the current procedure.
+	% This is used for the definitions of the wrapper functions needed
+	% for closures.  When generating code for a procedure that creates
+	% a closure, we insert the definition of the wrapper function used
+	% for that closure into this list.
+	%
+
+	% Insert an extra definition at the start of the list of extra
+	% definitions.
+:- pred ml_gen_info_add_extra_defn(mlds__defn,
+			ml_gen_info, ml_gen_info).
+:- mode ml_gen_info_add_extra_defn(in, in, out) is det.
+
+	% Get the list of extra definitions.
+:- pred ml_gen_info_get_extra_defns(ml_gen_info, mlds__defns).
+:- mode ml_gen_info_get_extra_defns(in, out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module prog_util, type_util, mode_util, special_pred.
+:- import_module code_util. % XXX for `code_util__compiler_generated'.
+:- import_module globals, options.
+
+:- import_module stack, string, require, term, varset.
+
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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