[m-rev.] diff: fix inter-module optimization bug
Simon Taylor
stayl at cs.mu.OZ.AU
Mon Jul 15 01:13:03 AEST 2002
Estimated hours taken: 2
Branches: main
Fix a bug in inter-module optimization with sub-modules reported
by Michael Day <mikeday at bigpond.net.au>. The symptom was a compiler
abort due to an attempt to take the address of a predicate with
multiple modes. The predicate only had multiple mode declarations
because the declarations were read from both the `.int0' and `.opt'
files for the module.
compiler/post_typecheck.m:
compiler/purity.m:
Remove duplicate modes and report other errors in type
declarations for all predicates in a separate pass before
purity checking and overloading resolution.
tests/valid/Mmakefile:
tests/valid/intermod_nested_module_bug.m:
tests/valid/intermod_nested_module_bug2.m:
Test case.
tests/valid/assoc_list.m:
tests/valid/assoc_list_bug.m:
Rename the assoc_list test case -- it interfered with
other test cases attempting to import the assoc_list
library module.
Index: compiler/post_typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/post_typecheck.m,v
retrieving revision 1.39
diff -u -u -r1.39 post_typecheck.m
--- compiler/post_typecheck.m 30 Jun 2002 17:06:35 -0000 1.39
+++ compiler/post_typecheck.m 14 Jul 2002 14:47:33 -0000
@@ -34,7 +34,8 @@
:- import_module hlds__hlds_pred, parse_tree__prog_data.
:- import_module list, io, bool, std_util.
- % check_type_bindings(PredId, PredInfo, ModuleInfo, ReportErrors):
+ % post_typecheck__finish_preds(PredIds, ReportTypeErrors,
+ % NumErrors, FoundTypeError, Module0, Module)
%
% Check that all Aditi predicates have an `aditi__state' argument.
% Check that the all of the types which have been inferred
@@ -47,11 +48,37 @@
% Note that when checking assertions we take the conservative
% approach of warning about unbound type variables. There may
% be cases for which this doesn't make sense.
+ % FoundTypeError will be `yes' if there were errors which
+ % should prevent further processing (e.g. polymorphism or
+ % mode analysis).
+ %
+:- pred post_typecheck__finish_preds(list(pred_id), bool,
+ int, bool, module_info, module_info, io__state, io__state).
+:- mode post_typecheck__finish_preds(in, in, out, out,
+ in, out, di, uo) is det.
+
+ % As above, but don't check for `aditi__state's and return
+ % the list of procedures containing unbound inst variables
+ % instead of reporting the errors directly.
%
-:- pred post_typecheck__check_type_bindings(pred_id, pred_info, module_info,
- bool, pred_info, int, io__state, io__state).
-:- mode post_typecheck__check_type_bindings(in, in, in, in, out, out, di, uo)
- is det.
+:- pred post_typecheck__finish_pred_no_io(module_info, list(proc_id),
+ pred_info, pred_info).
+:- mode post_typecheck__finish_pred_no_io(in, out, in, out) is det.
+
+:- pred post_typecheck__finish_imported_pred_no_io(module_info,
+ list(proc_id), pred_info, pred_info).
+:- mode post_typecheck__finish_imported_pred_no_io(in, out, in, out) is det.
+
+:- pred post_typecheck__finish_ill_typed_pred(module_info, pred_id,
+ pred_info, pred_info, io__state, io__state).
+:- mode post_typecheck__finish_ill_typed_pred(in, in, in, out, di, uo) is det.
+
+ % Now that the assertion has finished being typechecked,
+ % remove it from further processing and store it in the
+ % assertion_table.
+:- pred post_typecheck__finish_promise(promise_type, module_info, pred_id,
+ module_info, io__state, io__state) is det.
+:- mode post_typecheck__finish_promise(in, in, in, out, di, uo) is det.
% Handle any unresolved overloading for a predicate call.
%
@@ -89,43 +116,6 @@
:- mode post_typecheck__resolve_unify_functor(in, in, in, in, in, in,
in, in, in, out, in, out, in, out, out) is det.
- % Do the stuff needed to initialize the pred_infos and proc_infos
- % so that a pred is ready for running polymorphism and then
- % mode checking.
- % Also check that all predicates with an `aditi' marker have
- % an `aditi__state' argument.
- %
-:- pred post_typecheck__finish_pred(module_info, pred_id, pred_info, pred_info,
- io__state, io__state).
-:- mode post_typecheck__finish_pred(in, in, in, out, di, uo) is det.
-
-:- pred post_typecheck__finish_imported_pred(module_info, pred_id,
- pred_info, pred_info, io__state, io__state).
-:- mode post_typecheck__finish_imported_pred(in, in, in, out, di, uo) is det.
-
- % As above, but don't check for `aditi__state's and return
- % the list of procedures containing unbound inst variables
- % instead of reporting the errors directly.
- %
-:- pred post_typecheck__finish_pred_no_io(module_info, list(proc_id),
- pred_info, pred_info).
-:- mode post_typecheck__finish_pred_no_io(in, out, in, out) is det.
-
-:- pred post_typecheck__finish_imported_pred_no_io(module_info,
- list(proc_id), pred_info, pred_info).
-:- mode post_typecheck__finish_imported_pred_no_io(in, out, in, out) is det.
-
-:- pred post_typecheck__finish_ill_typed_pred(module_info, pred_id,
- pred_info, pred_info, io__state, io__state).
-:- mode post_typecheck__finish_ill_typed_pred(in, in, in, out, di, uo) is det.
-
- % Now that the assertion has finished being typechecked,
- % remove it from further processing and store it in the
- % assertion_table.
-:- pred post_typecheck__finish_promise(promise_type, module_info, pred_id,
- module_info, io__state, io__state) is det.
-:- mode post_typecheck__finish_promise(in, in, in, out, di, uo) is det.
-
%-----------------------------------------------------------------------------%
:- implementation.
@@ -144,6 +134,92 @@
:- import_module string, varset.
%-----------------------------------------------------------------------------%
+
+post_typecheck__finish_preds(PredIds, ReportTypeErrors, NumErrors,
+ FoundTypeError, ModuleInfo0, ModuleInfo) -->
+ post_typecheck__finish_preds(PredIds, ReportTypeErrors,
+ ModuleInfo0, ModuleInfo, 0, NumErrors, no, FoundTypeError).
+
+:- pred post_typecheck__finish_preds(list(pred_id), bool,
+ module_info, module_info, int, int, bool, bool, io__state, io__state).
+:- mode post_typecheck__finish_preds(in, in, in, out, in, out,
+ in, out, di, uo) is det.
+
+post_typecheck__finish_preds([], _, ModuleInfo, ModuleInfo,
+ NumErrors, NumErrors,
+ PostTypecheckError, PostTypecheckError) --> [].
+post_typecheck__finish_preds([PredId | PredIds], ReportTypeErrors,
+ ModuleInfo0, ModuleInfo, NumErrors0, NumErrors,
+ FoundTypeError0, FoundTypeError) -->
+ { module_info_pred_info(ModuleInfo0, PredId, PredInfo0) },
+ (
+ { pred_info_is_imported(PredInfo0)
+ ; pred_info_is_pseudo_imported(PredInfo0) }
+ ->
+ post_typecheck__finish_imported_pred(ModuleInfo0, PredId,
+ PredInfo0, PredInfo),
+ { NumErrors1 = NumErrors0 },
+ { FoundTypeError1 = FoundTypeError0 }
+ ;
+ %
+ % Only report error messages for unbound type variables
+ % if we didn't get any type errors already; this avoids
+ % a lot of spurious diagnostics.
+ %
+ post_typecheck__check_type_bindings(PredId, PredInfo0,
+ ModuleInfo0, ReportTypeErrors,
+ PredInfo1, UnboundTypeErrsInThisPred),
+
+ %
+ % if there were any unsatisfied type class constraints,
+ % then that can cause internal errors in polymorphism.m
+ % if we try to continue, so we need to halt compilation
+ % after this pass.
+ %
+ { UnboundTypeErrsInThisPred \= 0 ->
+ FoundTypeError1 = yes
+ ;
+ FoundTypeError1 = FoundTypeError0
+ },
+
+ { post_typecheck__finish_pred_no_io(ModuleInfo0,
+ ErrorProcs, PredInfo1, PredInfo2) },
+ report_unbound_inst_vars(ModuleInfo0, PredId,
+ ErrorProcs, PredInfo2, PredInfo3),
+ check_for_indistinguishable_modes(ModuleInfo0, PredId,
+ PredInfo3, PredInfo),
+
+ %
+ % check that main/2 has the right type
+ %
+ ( { ReportTypeErrors = yes } ->
+ check_type_of_main(PredInfo)
+ ;
+ []
+ ),
+
+ %
+ % Check that all Aditi predicates have an `aditi__state'
+ % argument. This must be done after typechecking because
+ % of type inference -- the types of some Aditi predicates
+ % may not be known before.
+ %
+ { pred_info_get_markers(PredInfo, Markers) },
+ ( { ReportTypeErrors = yes, check_marker(Markers, aditi) } ->
+ check_aditi_state(ModuleInfo0, PredInfo)
+ ;
+ []
+ ),
+
+ { NumErrors1 is NumErrors0 + UnboundTypeErrsInThisPred }
+ ),
+ { module_info_set_pred_info(ModuleInfo0, PredId,
+ PredInfo, ModuleInfo1) },
+ post_typecheck__finish_preds(PredIds, ReportTypeErrors,
+ ModuleInfo1, ModuleInfo, NumErrors1, NumErrors,
+ FoundTypeError1, FoundTypeError).
+
+%-----------------------------------------------------------------------------%
% Check for unbound type variables
%
% Check that the all of the types which have been inferred
@@ -151,6 +227,11 @@
% variables other than those that occur in the types of head
% variables, and that there are no unsatisfied type class constraints.
+:- pred post_typecheck__check_type_bindings(pred_id, pred_info, module_info,
+ bool, pred_info, int, io__state, io__state).
+:- mode post_typecheck__check_type_bindings(in, in, in, in, out, out, di, uo)
+ is det.
+
post_typecheck__check_type_bindings(PredId, PredInfo0, ModuleInfo, ReportErrs,
PredInfo, NumErrors, IOState0, IOState) :-
(
@@ -179,16 +260,16 @@
[], Errs, Set0, Set),
( Errs = [] ->
PredInfo = PredInfo0,
- IOState2 = IOState1
+ IOState = IOState1
;
( ReportErrs = yes ->
%
% report the warning
%
report_unresolved_type_warning(Errs, PredId, PredInfo0,
- ModuleInfo, VarSet, IOState1, IOState2)
+ ModuleInfo, VarSet, IOState1, IOState)
;
- IOState2 = IOState1
+ IOState = IOState1
),
%
@@ -201,27 +282,6 @@
ClausesInfo),
pred_info_set_clauses_info(PredInfo0, ClausesInfo, PredInfo1),
pred_info_set_constraint_proofs(PredInfo1, Proofs, PredInfo)
- ),
-
- %
- % check that main/2 has the right type
- %
- ( ReportErrs = yes ->
- check_type_of_main(PredInfo, IOState2, IOState3)
- ;
- IOState3 = IOState2
- ),
-
- %
- % Check that all Aditi predicates have an `aditi__state' argument.
- % This must be done after typechecking because of type inference --
- % the types of some Aditi predicates may not be known before.
- %
- pred_info_get_markers(PredInfo, Markers),
- ( ReportErrs = yes, check_marker(Markers, aditi) ->
- check_aditi_state(ModuleInfo, PredInfo, IOState3, IOState)
- ;
- IOState = IOState3
).
:- pred check_type_bindings_2(assoc_list(prog_var, (type)), list(tvar),
@@ -625,18 +685,6 @@
%-----------------------------------------------------------------------------%
- %
- % Ensure that all constructors occurring in predicate mode
- % declarations are module qualified.
- %
-post_typecheck__finish_pred(ModuleInfo, PredId, PredInfo0, PredInfo) -->
- { post_typecheck__finish_pred_no_io(ModuleInfo,
- ErrorProcs, PredInfo0, PredInfo1) },
- report_unbound_inst_vars(ModuleInfo, PredId,
- ErrorProcs, PredInfo1, PredInfo2),
- check_for_indistinguishable_modes(ModuleInfo, PredId,
- PredInfo2, PredInfo).
-
post_typecheck__finish_pred_no_io(ModuleInfo, ErrorProcs,
PredInfo0, PredInfo) :-
post_typecheck__propagate_types_into_modes(ModuleInfo,
@@ -661,6 +709,10 @@
% constructors occurring in predicate mode declarations are
% module qualified.
%
+:- pred post_typecheck__finish_imported_pred(module_info, pred_id,
+ pred_info, pred_info, io__state, io__state).
+:- mode post_typecheck__finish_imported_pred(in, in, in, out, di, uo) is det.
+
post_typecheck__finish_imported_pred(ModuleInfo, PredId,
PredInfo0, PredInfo) -->
{ pred_info_get_markers(PredInfo0, Markers) },
Index: compiler/purity.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/purity.m,v
retrieving revision 1.46
diff -u -u -r1.46 purity.m
--- compiler/purity.m 28 Mar 2002 03:43:34 -0000 1.46
+++ compiler/purity.m 14 Jul 2002 14:48:01 -0000
@@ -331,79 +331,55 @@
check_preds_purity(FoundTypeError, ModuleInfo0,
PostTypecheckError, ModuleInfo) -->
{ module_info_predids(ModuleInfo0, PredIds) },
- check_preds_purity_2(PredIds, FoundTypeError, ModuleInfo0,
- ModuleInfo1, 0, NumErrors, no, PostTypecheckError),
- { module_info_num_errors(ModuleInfo1, Errs0) },
- { Errs is Errs0 + NumErrors },
- { module_info_set_num_errors(ModuleInfo1, Errs, ModuleInfo) }.
+ % Only report error messages for unbound type variables
+ % if we didn't get any type errors already; this avoids
+ % a lot of spurious diagnostics.
+ { ReportTypeErrors = bool__not(FoundTypeError) },
+ post_typecheck__finish_preds(PredIds, ReportTypeErrors, NumErrors1,
+ PostTypecheckError, ModuleInfo0, ModuleInfo1),
+
+ check_preds_purity_2(PredIds, ModuleInfo1, ModuleInfo2,
+ NumErrors1, NumErrors),
+ { module_info_num_errors(ModuleInfo2, Errs0) },
+ { Errs is Errs0 + NumErrors },
+ { module_info_set_num_errors(ModuleInfo2, Errs, ModuleInfo) }.
-:- pred check_preds_purity_2(list(pred_id), bool, module_info, module_info,
- int, int, bool, bool, io__state, io__state).
-:- mode check_preds_purity_2(in, in, in, out, in, out, in, out, di, uo) is det.
+:- pred check_preds_purity_2(list(pred_id), module_info, module_info,
+ int, int, io__state, io__state).
+:- mode check_preds_purity_2(in, in, out, in, out, di, uo) is det.
-check_preds_purity_2([], _, ModuleInfo, ModuleInfo, NumErrors, NumErrors,
- PostTypecheckError, PostTypecheckError) --> [].
-check_preds_purity_2([PredId | PredIds], FoundTypeError, ModuleInfo0,
- ModuleInfo, NumErrors0, NumErrors,
- PostTypecheckError0, PostTypecheckError) -->
- { module_info_preds(ModuleInfo0, Preds0) },
- { map__lookup(Preds0, PredId, PredInfo0) },
+check_preds_purity_2([], ModuleInfo, ModuleInfo, NumErrors, NumErrors) --> [].
+check_preds_purity_2([PredId | PredIds], ModuleInfo0, ModuleInfo,
+ NumErrors0, NumErrors) -->
+ { module_info_pred_info(ModuleInfo0, PredId, PredInfo0) },
(
{ pred_info_is_imported(PredInfo0)
; pred_info_is_pseudo_imported(PredInfo0) }
->
- post_typecheck__finish_imported_pred(ModuleInfo0, PredId,
- PredInfo0, PredInfo),
- { NumErrors1 = NumErrors0 },
- { PostTypecheckError1 = PostTypecheckError0 }
+ { ModuleInfo1 = ModuleInfo0 },
+ { PredInfo = PredInfo0 },
+ { NumErrors1 = NumErrors0 }
;
write_pred_progress_message("% Purity-checking ", PredId,
ModuleInfo0),
- %
- % Only report error messages for unbound type variables
- % if we didn't get any type errors already; this avoids
- % a lot of spurious diagnostics.
- %
- { bool__not(FoundTypeError, ReportErrs) },
- post_typecheck__check_type_bindings(PredId, PredInfo0,
- ModuleInfo0, ReportErrs,
- PredInfo1, UnboundTypeErrsInThisPred),
- %
- % if there were any unsatisfied type class constraints,
- % then that can cause internal errors in polymorphism.m
- % if we try to continue, so we need to halt compilation
- % after this pass.
- %
- { UnboundTypeErrsInThisPred \= 0 ->
- PostTypecheckError1 = yes
- ;
- PostTypecheckError1 = PostTypecheckError0
- },
- puritycheck_pred(PredId, PredInfo1, PredInfo2, ModuleInfo0,
+ puritycheck_pred(PredId, PredInfo0, PredInfo, ModuleInfo0,
PurityErrsInThisPred),
- post_typecheck__finish_pred(ModuleInfo0, PredId, PredInfo2,
- PredInfo),
- { NumErrors1 is NumErrors0 + UnboundTypeErrsInThisPred
- + PurityErrsInThisPred }
+ { NumErrors1 = NumErrors0 + PurityErrsInThisPred },
+ { module_info_set_pred_info(ModuleInfo0, PredId,
+ PredInfo, ModuleInfo1) }
),
- { map__det_update(Preds0, PredId, PredInfo, Preds) },
- { module_info_get_predicate_table(ModuleInfo0, PredTable0) },
- { predicate_table_set_preds(PredTable0, Preds, PredTable) },
- { module_info_set_predicate_table(ModuleInfo0, PredTable,
- ModuleInfo1) },
% finish processing of promise declarations
- { pred_info_get_goal_type(PredInfo0, GoalType) },
+ { pred_info_get_goal_type(PredInfo, GoalType) },
( { GoalType = promise(PromiseType) } ->
post_typecheck__finish_promise(PromiseType, ModuleInfo1,
PredId, ModuleInfo2)
;
{ ModuleInfo2 = ModuleInfo1 }
),
- check_preds_purity_2(PredIds, FoundTypeError, ModuleInfo2, ModuleInfo,
- NumErrors1, NumErrors,
- PostTypecheckError1, PostTypecheckError).
+ check_preds_purity_2(PredIds, ModuleInfo2, ModuleInfo,
+ NumErrors1, NumErrors).
% Purity-check the code for single predicate, reporting any errors.
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.106
diff -u -u -r1.106 Mmakefile
--- tests/valid/Mmakefile 4 Jul 2002 23:25:49 -0000 1.106
+++ tests/valid/Mmakefile 13 Jul 2002 16:43:39 -0000
@@ -95,6 +95,7 @@
intermod_impure.m \
intermod_lambda.m \
intermod_nested_module.m \
+ intermod_nested_module_bug.m \
intermod_nested_uniq.m \
intermod_pragma_import.m \
intermod_quote.m \
@@ -177,7 +178,7 @@
zero_arity.m
# XXX The mode system can't handle the following test cases yet:
-# assoc_list.m
+# assoc_list_bug.m
# determinism.m
# mode_merge_insts.m
# inst_perf_bug_2.m
@@ -289,6 +290,8 @@
MCFLAGS-intermod_lambda2 = --intermodule-optimization
MCFLAGS-intermod_nested_module = --intermodule-optimization
MCFLAGS-intermod_nested_module2 = --intermodule-optimization
+MCFLAGS-intermod_nested_module_bug = --intermodule-optimization
+MCFLAGS-intermod_nested_module_bug2 = --intermodule-optimization
MCFLAGS-intermod_nested_uniq = --intermodule-optimization
MCFLAGS-intermod_nested_uniq2 = --intermodule-optimization
MCFLAGS-intermod_pragma_import = --intermodule-optimization
Index: tests/valid/assoc_list.m
===================================================================
RCS file: tests/valid/assoc_list.m
diff -N tests/valid/assoc_list.m
--- tests/valid/assoc_list.m 11 Dec 1996 00:01:35 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,11 +0,0 @@
-:- module assoc_list.
-:- interface.
-:- import_module list, std_util.
-
-:- pred assoc_list_member(pair(K,V), list(pair(K,V))).
-:- mode assoc_list_member(bound(free - ground) -> ground, in) is semidet.
-:- mode assoc_list_member(bound(free - free) -> ground, in) is nondet.
-
-assoc_list_member(X, [X|_]).
-assoc_list_member(X, [_|Xs]) :-
- assoc_list_member(X, Xs).
Index: tests/valid/assoc_list_bug.m
===================================================================
RCS file: tests/valid/assoc_list_bug.m
diff -N tests/valid/assoc_list_bug.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/valid/assoc_list_bug.m 11 Dec 1996 00:01:35 -0000
@@ -0,0 +1,11 @@
+:- module assoc_list.
+:- interface.
+:- import_module list, std_util.
+
+:- pred assoc_list_member(pair(K,V), list(pair(K,V))).
+:- mode assoc_list_member(bound(free - ground) -> ground, in) is semidet.
+:- mode assoc_list_member(bound(free - free) -> ground, in) is nondet.
+
+assoc_list_member(X, [X|_]).
+assoc_list_member(X, [_|Xs]) :-
+ assoc_list_member(X, Xs).
Index: tests/valid/intermod_nested_module_bug.m
===================================================================
RCS file: tests/valid/intermod_nested_module_bug.m
diff -N tests/valid/intermod_nested_module_bug.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/valid/intermod_nested_module_bug.m 13 Jul 2002 16:47:08 -0000
@@ -0,0 +1,25 @@
+:- module intermod_nested_module_bug.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io, io).
+:- mode main(di, uo) is det.
+
+:- implementation.
+
+:- import_module std_util.
+:- import_module intermod_nested_module_bug2, intermod_nested_module_bug2__sub.
+
+main -->
+ get_request(Res0),
+ (
+ { Res0 = ok(CGI) },
+ read_post(CGI, Form),
+ write(Form), nl
+ ;
+ { Res0 = error(Error) },
+ write_string(Error)
+ ).
+
Index: tests/valid/intermod_nested_module_bug2.m
===================================================================
RCS file: tests/valid/intermod_nested_module_bug2.m
diff -N tests/valid/intermod_nested_module_bug2.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/valid/intermod_nested_module_bug2.m 13 Jul 2002 16:47:08 -0000
@@ -0,0 +1,23 @@
+:- module intermod_nested_module_bug2.
+
+:- interface.
+
+:- include_module intermod_nested_module_bug2__sub.
+:- import_module io, string, list, assoc_list, int, std_util.
+
+:- type cgi
+ ---> cgi(
+ content_length :: maybe(int)
+ ).
+
+:- pred get_request(maybe_error(cgi), io, io).
+:- mode get_request(out, di, uo) is det.
+
+:- implementation.
+
+get_request(Res) --> { Res = promise_only_solution(get_request0) }.
+
+:- pred get_request0(maybe_error(cgi)).
+:- mode get_request0(out) is cc_multi.
+
+get_request0(error("foo")).
Index: tests/valid/intermod_nested_module_bug2.sub.m
===================================================================
RCS file: tests/valid/intermod_nested_module_bug2.sub.m
diff -N tests/valid/intermod_nested_module_bug2.sub.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/valid/intermod_nested_module_bug2.sub.m 13 Jul 2002 16:47:45 -0000
@@ -0,0 +1,15 @@
+
+:- module intermod_nested_module_bug2__sub.
+
+:- interface.
+
+:- type post == assoc_list(string).
+
+:- pred read_post(cgi, maybe_error(post), io, io).
+:- mode read_post(in, out, di, uo) is det.
+
+:- implementation.
+
+read_post(_CGI, error("foo")) --> [].
+
+:- end_module intermod_nested_module_bug2__sub.
--------------------------------------------------------------------------
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