[m-rev.] for review: more variable naming improvements
Simon Taylor
stayl at cs.mu.OZ.AU
Mon Jun 17 18:52:04 AEST 2002
Estimated hours taken: 2
Branches: main
compiler/typecheck.m:
Use more meaningful variable names when an argument
has the same name in all clauses.
Rename variables so that both arguments of
a clause like `p(X, X).' are both called `X'
in the debugger.
tests/debugger/print_goal.{m,inp,exp}:
Add a test case.
tests/debugger/field_names.exp:
tests/debugger/interpreter.exp:
tests/invalid/aditi_update_mode_errors.err_exp:
tests/invalid/merge_ground_any.err_exp:
tests/invalid/polymorphic_unification.err_exp:
Update expected output.
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.318
diff -u -u -r1.318 typecheck.m
--- compiler/typecheck.m 5 Jun 2002 16:41:14 -0000 1.318
+++ compiler/typecheck.m 17 Jun 2002 08:49:05 -0000
@@ -339,8 +339,7 @@
( Iteration = 1 ->
maybe_add_field_access_function_clause(ModuleInfo,
PredInfo0, PredInfo0a),
- maybe_improve_single_clause_headvar_names(Globals,
- PredInfo0a, PredInfo1)
+ maybe_improve_headvar_names(Globals, PredInfo0a, PredInfo1)
;
PredInfo1 = PredInfo0
),
@@ -841,13 +840,14 @@
% as the head variables in the proc_info.
% This gives better error messages, more meaningful variable
% names in the debugger and slightly faster compilation.
-:- pred maybe_improve_single_clause_headvar_names(globals,
- pred_info, pred_info).
-:- mode maybe_improve_single_clause_headvar_names(in, in, out) is det.
+:- pred maybe_improve_headvar_names(globals, pred_info, pred_info).
+:- mode maybe_improve_headvar_names(in, in, out) is det.
-maybe_improve_single_clause_headvar_names(Globals, PredInfo0, PredInfo) :-
+maybe_improve_headvar_names(Globals, PredInfo0, PredInfo) :-
pred_info_clauses_info(PredInfo0, ClausesInfo0),
clauses_info_clauses(ClausesInfo0, Clauses0),
+ clauses_info_headvars(ClausesInfo0, HeadVars0),
+ clauses_info_varset(ClausesInfo0, VarSet0),
(
% Don't do this when making a `.opt' file.
% intermod.m needs to perform a similar transformation
@@ -856,13 +856,13 @@
% variables in the clause head, and this pass would make it
% difficult to work out what were the original arguments).
globals__lookup_bool_option(Globals,
- make_optimization_interface, no),
-
+ make_optimization_interface, yes)
+ ->
+ PredInfo = PredInfo0
+ ;
Clauses0 = [SingleClause0]
->
SingleClause0 = clause(A, Goal0, C, D),
- clauses_info_headvars(ClausesInfo0, HeadVars0),
- clauses_info_varset(ClausesInfo0, VarSet0),
Goal0 = _ - GoalInfo0,
goal_to_conj_list(Goal0, Conj0),
@@ -885,7 +885,24 @@
clauses_info_set_varset(ClausesInfo2, VarSet, ClausesInfo),
pred_info_set_clauses_info(PredInfo0, ClausesInfo, PredInfo)
;
- PredInfo = PredInfo0
+ %
+ % If a headvar is assigned to a variable with the
+ % same name (or no name) in every clause, rename
+ % it to have that name.
+ %
+ {HeadVarNames, _} = list__foldl(
+ find_headvar_names_in_clause(VarSet0, HeadVars0),
+ Clauses0, {map__init, yes}),
+ VarSet = map__foldl(
+ (func(HeadVar, MaybeHeadVarName, VarSet1) =
+ ( MaybeHeadVarName = yes(HeadVarName) ->
+ varset__name_var(VarSet1, HeadVar, HeadVarName)
+ ;
+ VarSet1
+ )
+ ), HeadVarNames, VarSet0),
+ clauses_info_set_varset(ClausesInfo0, VarSet, ClausesInfo),
+ pred_info_set_clauses_info(PredInfo0, ClausesInfo, PredInfo)
).
:- pred improve_single_clause_headvars(list(hlds_goal)::in, list(prog_var)::in,
@@ -898,31 +915,20 @@
improve_single_clause_headvars([Goal | Conj0], HeadVars, SeenVars0,
VarSet0, VarSet, Subst0, Subst, RevConj0, RevConj) :-
(
- Goal = unify(LVar, var(RVar), _, _, _) - _,
- ( list__member(LVar, HeadVars) ->
- HeadVar = LVar,
- OtherVar = RVar
- ; list__member(RVar, HeadVars) ->
- HeadVar = RVar,
- OtherVar = LVar
- ;
- fail
- ),
-
- % The headvars must be distinct variables, so check
- % that this variable doesn't already appear in the
- % argument list.
- \+ list__member(OtherVar, HeadVars),
- \+ list__member(OtherVar, SeenVars0)
+ goal_is_headvar_unification(HeadVars, Goal, HeadVar, OtherVar)
->
%
% If the headvar doesn't appear elsewhere the
- % unification can be removed. This check is
- % just to be safe -- the unification should
- % always be removable.
+ % unification can be removed.
%
(
- some [OtherGoal] (
+ % The headvars must be distinct variables, so check
+ % that this variable doesn't already appear in the
+ % argument list.
+ \+ list__member(OtherVar, HeadVars),
+ \+ list__member(OtherVar, SeenVars0),
+
+ \+ ( some [OtherGoal] (
( list__member(OtherGoal, Conj0)
; list__member(OtherGoal, RevConj0)
),
@@ -930,28 +936,55 @@
goal_info_get_nonlocals(OtherGoalInfo,
OtherNonLocals),
set__member(HeadVar, OtherNonLocals)
- )
+ ))
->
- RevConj1 = [Goal | RevConj0]
- ;
- RevConj1 = RevConj0
- ),
+ SeenVars = [OtherVar | SeenVars0],
+ RevConj1 = RevConj0,
+ Subst1 = map__det_insert(Subst0, HeadVar, OtherVar),
- %
- % If the variable wasn't named, use the `HeadVar__n' name.
- %
- (
- \+ varset__search_name(VarSet0, OtherVar, _),
- varset__search_name(VarSet0, HeadVar, HeadVarName)
- ->
- varset__name_var(VarSet0, OtherVar,
- HeadVarName, VarSet1)
+ %
+ % If the variable wasn't named, use the
+ % `HeadVar__n' name.
+ %
+ (
+ \+ varset__search_name(VarSet0, OtherVar, _),
+ varset__search_name(VarSet0,
+ HeadVar, HeadVarName)
+ ->
+ varset__name_var(VarSet0, OtherVar,
+ HeadVarName, VarSet1)
+ ;
+ VarSet1 = VarSet0
+ )
;
- VarSet1 = VarSet0
- ),
+ RevConj1 = [Goal | RevConj0],
+ Subst1 = Subst0,
+ SeenVars = SeenVars0,
- Subst1 = map__det_insert(Subst0, HeadVar, OtherVar),
- SeenVars = [OtherVar | SeenVars0]
+ (
+ varset__search_name(VarSet0,
+ OtherVar, OtherVarName)
+ ->
+ %
+ % The unification can't be eliminated,
+ % so just rename the head variable.
+ %
+ varset__name_var(VarSet0, HeadVar,
+ OtherVarName, VarSet1)
+ ;
+ varset__search_name(VarSet0, HeadVar,
+ HeadVarName)
+ ->
+ %
+ % If the variable wasn't named, use the
+ % `HeadVar__n' name.
+ %
+ varset__name_var(VarSet0, OtherVar,
+ HeadVarName, VarSet1)
+ ;
+ VarSet1 = VarSet0
+ )
+ )
;
RevConj1 = [Goal | RevConj0],
VarSet1 = VarSet0,
@@ -960,6 +993,91 @@
),
improve_single_clause_headvars(Conj0, HeadVars, SeenVars,
VarSet1, VarSet, Subst1, Subst, RevConj1, RevConj).
+
+ % Head variables which have the same name in each clause.
+ % will have an entry of `yes(Name)' in the result map.
+:- func find_headvar_names_in_clause(prog_varset, list(prog_var), clause,
+ {map(prog_var, maybe(string)), bool}) =
+ {map(prog_var, maybe(string)), bool}.
+
+find_headvar_names_in_clause(VarSet, HeadVars, clause(_, Goal, _, _),
+ {HeadVarMap0, IsFirstClause}) = {HeadVarMap, no} :-
+ goal_to_conj_list(Goal, Conj),
+ ClauseHeadVarMap = list__foldl(
+ find_headvar_names_in_goal(VarSet, HeadVars),
+ Conj, map__init),
+ ( IsFirstClause = yes ->
+ HeadVarMap = ClauseHeadVarMap
+ ;
+ % Check that the variables in this clause match
+ % the names in previous clauses.
+ HeadVarMap1 = map__foldl(
+ (func(HeadVar, MaybeHeadVarName, Map) =
+ (
+ map__search(Map, HeadVar,
+ MaybeClauseHeadVarName),
+ MaybeHeadVarName = MaybeClauseHeadVarName
+ ->
+ Map
+ ;
+ map__set(Map, HeadVar, no)
+ )
+ ), HeadVarMap0, ClauseHeadVarMap),
+
+ % Check for variables which weren't named in previous
+ % clauses. It would be confusing to refer to variable
+ % `A' in the second clause below.
+ % p(A, _).
+ % p([_|_], _).
+ HeadVarMap = map__foldl(
+ (func(HeadVar, _, Map) =
+ ( map__contains(HeadVarMap0, HeadVar) ->
+ Map
+ ;
+ map__set(Map, HeadVar, no)
+ )
+ ), HeadVarMap1, HeadVarMap1)
+ ).
+
+:- func find_headvar_names_in_goal(prog_varset, list(prog_var), hlds_goal,
+ map(prog_var, maybe(string))) = map(prog_var, maybe(string)).
+
+find_headvar_names_in_goal(VarSet, HeadVars, Goal,
+ HeadVarMap0) = HeadVarMap :-
+ (
+ goal_is_headvar_unification(HeadVars, Goal, HeadVar, OtherVar)
+ ->
+ maybe_pred(varset__search_name(VarSet), OtherVar,
+ MaybeOtherVarName),
+ ( map__search(HeadVarMap0, HeadVar, MaybeHeadVarName) ->
+ ( MaybeOtherVarName = MaybeHeadVarName ->
+ HeadVarMap = HeadVarMap0
+ ;
+ HeadVarMap = map__det_update(
+ HeadVarMap0, HeadVar, no)
+ )
+ ;
+ HeadVarMap = map__set(HeadVarMap0, HeadVar,
+ MaybeOtherVarName)
+ )
+ ;
+ HeadVarMap = HeadVarMap0
+ ).
+
+:- pred goal_is_headvar_unification(list(prog_var)::in, hlds_goal::in,
+ prog_var::out, prog_var::out) is semidet.
+
+goal_is_headvar_unification(HeadVars, Goal, HeadVar, OtherVar) :-
+ Goal = unify(LVar, var(RVar), _, _, _) - _,
+ ( list__member(LVar, HeadVars) ->
+ HeadVar = LVar,
+ OtherVar = RVar
+ ; list__member(RVar, HeadVars) ->
+ HeadVar = RVar,
+ OtherVar = LVar
+ ;
+ fail
+ ).
%-----------------------------------------------------------------------------%
Index: tests/debugger/field_names.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/field_names.exp,v
retrieving revision 1.2
diff -u -u -r1.2 field_names.exp
--- tests/debugger/field_names.exp 19 Dec 2001 06:44:51 -0000 1.2
+++ tests/debugger/field_names.exp 12 Jun 2002 09:40:10 -0000
@@ -227,55 +227,55 @@
mdb> finish
11: 6 2 EXIT pred field_names:make_t4/2-0 (det)
mdb> p 2
- HeadVar__2 t2f(0.600000000000000, 61, t1f1(41, 42, 43, 44), t1f2(51, 52, 53))
+ A(2) (arg 2) t2f(0.600000000000000, 61, t1f1(41, 42, 43, 44), t1f2(51, 52, 53))
mdb> p 2^1
- HeadVar__2 0.600000000000000
+ A(2) (arg 2) 0.600000000000000
mdb> p 2^2
- HeadVar__2 61
+ A(2) (arg 2) 61
mdb> p 2^3^t1a
- HeadVar__2 41
+ A(2) (arg 2) 41
mdb> p 2^3^t1b
- HeadVar__2 42
+ A(2) (arg 2) 42
mdb> p 2^3^t1c
mdb: the path t1c does not exist.
mdb> p 2^3^t1d
- HeadVar__2 44
+ A(2) (arg 2) 44
mdb> p 2^3^t1e
mdb: the path t1e does not exist.
mdb> p 2^4
- HeadVar__2 t1f2(51, 52, 53)
+ A(2) (arg 2) t1f2(51, 52, 53)
mdb> p 2^4^t1a
mdb: the path t1a does not exist.
mdb> p 2^4^t1e
- HeadVar__2 51
+ A(2) (arg 2) 51
mdb> p 2^4^t1f
mdb: the path t1f does not exist.
mdb> p 2^4^t1g
- HeadVar__2 53
+ A(2) (arg 2) 53
mdb> p 2^t2a
- HeadVar__2 0.600000000000000
+ A(2) (arg 2) 0.600000000000000
mdb> p 2^t2b
- HeadVar__2 t1f1(41, 42, 43, 44)
+ A(2) (arg 2) t1f1(41, 42, 43, 44)
mdb> p 2^t2b^t1a
- HeadVar__2 41
+ A(2) (arg 2) 41
mdb> p 2^t2b^t1b
- HeadVar__2 42
+ A(2) (arg 2) 42
mdb> p 2^t2b^t1c
mdb: the path t1c does not exist.
mdb> p 2^t2b^t1d
- HeadVar__2 44
+ A(2) (arg 2) 44
mdb> p 2^t2b^t1e
mdb: the path t1e does not exist.
mdb> p 2^t2c
- HeadVar__2 t1f2(51, 52, 53)
+ A(2) (arg 2) t1f2(51, 52, 53)
mdb> p 2^t2c^t1a
mdb: the path t1a does not exist.
mdb> p 2^t2c^t1e
- HeadVar__2 51
+ A(2) (arg 2) 51
mdb> p 2^t2c^t1f
mdb: the path t1f does not exist.
mdb> p 2^t2c^t1g
- HeadVar__2 53
+ A(2) (arg 2) 53
mdb> step
12: 7 2 CALL pred field_names:make_t5/2-0 (det)
mdb> finish
Index: tests/debugger/interpreter.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/interpreter.exp,v
retrieving revision 1.14
diff -u -u -r1.14 interpreter.exp
--- tests/debugger/interpreter.exp 5 Jun 2002 16:41:22 -0000 1.14
+++ tests/debugger/interpreter.exp 13 Jun 2002 12:49:45 -0000
@@ -12,11 +12,11 @@
mdb> vars
1 HeadVar__1
2 HeadVar__2
- 3 HeadVar__4
+ 3 DCG_0 (arg 4)
mdb> print *
HeadVar__1 term(varset(var_supply(0), empty, empty), functor(atom(":-"), [|](functor/3, []), context("interpreter.m", 22)))
HeadVar__2 []
- HeadVar__4 state('<<c_pointer>>')
+ DCG_0 (arg 4) state('<<c_pointer>>')
mdb> goto 30
30: 16 12 CALL pred interpreter:database_assert_clause/4-0 (det)
mdb> print *
Index: tests/debugger/print_goal.exp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/print_goal.exp,v
retrieving revision 1.2
diff -u -u -r1.2 print_goal.exp
--- tests/debugger/print_goal.exp 14 Jun 2002 08:18:04 -0000 1.2
+++ tests/debugger/print_goal.exp 17 Jun 2002 08:44:36 -0000
@@ -7,7 +7,7 @@
mdb> b big_data
0: + stop interface pred print_goal:big_data/1-0 (det)
mdb> b print_goal
- 1: + stop interface pred print_goal:print_goal/8-0 (det)
+ 1: + stop interface pred print_goal:print_goal/9-0 (det)
mdb> c
2: 2 2 CALL pred print_goal:big_data/1-0 (det)
mdb> p goal
@@ -18,13 +18,49 @@
big_data(big(big(big/3, 2, small), 3, big(big/3, 6, small)))
mdb> c
big(big(big(small, 1, small), 2, small), 3, big(big(small, 4, big(small, 5, small)), 6, small)).
- 4: 3 2 CALL pred print_goal:print_goal/8-0 (det)
+ 4: 3 2 CALL pred print_goal:print_goal/9-0 (det)
+mdb> v
+ 1 HeadVar__1
+ 2 _W (arg 2)
+ 3 X (arg 3)
+ 4 Y (arg 6)
+ 5 DCG_0 (arg 8)
mdb> p goal
-print_goal(100, 101, '_', '_', 102, '_', state('<<c_pointer>>'), '_')
+print_goal(yes, 100, 101, _, _, 102, _, state(<<c_pointer>>), _)
mdb> finish
- 5: 3 2 EXIT pred print_goal:print_goal/8-0 (det)
+ 6: 3 2 EXIT pred print_goal:print_goal/9-0 (det)
+mdb> v
+ 1 HeadVar__1
+ 2 _W (arg 2)
+ 3 X (arg 3)
+ 4 HeadVar__4
+ 5 HeadVar__5
+ 6 Y (arg 6)
+ 7 HeadVar__7
+ 8 DCG_1 (arg 9)
mdb> p goal
-print_goal(100, 101, 102, 103, 102, 103, _, state(<<c_pointer>>))
+print_goal(yes, 100, 101, 102, 103, 102, 103, _, state(<<c_pointer>>))
mdb> c
103.
103.
+ 7: 4 2 CALL pred print_goal:print_goal/9-0 (det)
+mdb> v
+ 1 HeadVar__1
+ 2 _W (arg 2)
+ 3 X (arg 3)
+ 4 Y (arg 6)
+ 5 DCG_0 (arg 8)
+mdb> finish
+ 9: 4 2 EXIT pred print_goal:print_goal/9-0 (det)
+mdb> v
+ 1 HeadVar__1
+ 2 _W (arg 2)
+ 3 X (arg 3)
+ 4 HeadVar__4
+ 5 HeadVar__5
+ 6 Y (arg 6)
+ 7 HeadVar__7
+ 8 DCG_1 (arg 9)
+mdb> c
+104.
+104.
Index: tests/debugger/print_goal.inp
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/print_goal.inp,v
retrieving revision 1.2
diff -u -u -r1.2 print_goal.inp
--- tests/debugger/print_goal.inp 14 Jun 2002 08:18:03 -0000 1.2
+++ tests/debugger/print_goal.inp 17 Jun 2002 08:43:52 -0000
@@ -8,7 +8,13 @@
finish
p goal
c
+v
p goal
finish
+v
p goal
+c
+v
+finish
+v
c
Index: tests/debugger/print_goal.m
===================================================================
RCS file: /home/mercury1/repository/tests/debugger/print_goal.m,v
retrieving revision 1.1
diff -u -u -r1.1 print_goal.m
--- tests/debugger/print_goal.m 8 Jun 2002 17:43:45 -0000 1.1
+++ tests/debugger/print_goal.m 17 Jun 2002 08:44:27 -0000
@@ -3,7 +3,7 @@
:- import_module io.
:- pred main(io__state::di, io__state::uo) is det.
:- implementation.
-:- import_module int.
+:- import_module bool, int.
:- type big
---> big(big, int, big)
@@ -13,10 +13,15 @@
{ big_data(Data) },
io__print(Data),
io__write_string(".\n"),
- print_goal(100, 101, _, Y, 102, Z),
+ print_goal(yes, 100, 101, _, Y, 102, Z),
io__print(Y),
io__write_string(".\n"),
io__print(Z),
+ io__write_string(".\n"),
+ print_goal(no, 100, 101, _, Y2, 102, Z2),
+ io__print(Y2),
+ io__write_string(".\n"),
+ io__print(Z2),
io__write_string(".\n").
:- pred big_data(big::out) is det.
@@ -48,8 +53,9 @@
)
).
-:- pred print_goal(int::in, int::in, int::out, int::out, int::in, int::out,
- io__state::di, io__state::uo) is det.
+:- pred print_goal(bool::in, int::in, int::in, int::out, int::out, int::in,
+ int::out, io__state::di, io__state::uo) is det.
-print_goal(W, X, X + 1, X + 2, Y, Y + 1) --> [].
+print_goal(yes, _W, X, X + 1, X + 2, Y, Y + 1) --> [].
+print_goal(no, _W, X, X + 2, X + 3, Y, Y + 2) --> [].
Index: tests/invalid/aditi_update_mode_errors.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/aditi_update_mode_errors.err_exp,v
retrieving revision 1.5
diff -u -u -r1.5 aditi_update_mode_errors.err_exp
--- tests/invalid/aditi_update_mode_errors.err_exp 10 Jul 2001 10:45:36 -0000 1.5
+++ tests/invalid/aditi_update_mode_errors.err_exp 13 Jun 2002 13:01:48 -0000
@@ -78,7 +78,7 @@
aditi_update_mode_errors.m:125: expected instantiatedness was `(pred(in, out, out, unused, out, out) is nondet)'.
aditi_update_mode_errors.m:047: In clause for `anc((aditi:aditi_mui), out, out)':
aditi_update_mode_errors.m:047: in argument 2 of clause head:
-aditi_update_mode_errors.m:047: mode error in unification of `HeadVar__2' and `X'.
-aditi_update_mode_errors.m:047: Variable `HeadVar__2' has instantiatedness `free',
+aditi_update_mode_errors.m:047: mode error in unification of `X' and `X'.
+aditi_update_mode_errors.m:047: Variable `X' has instantiatedness `free',
aditi_update_mode_errors.m:047: variable `X' has instantiatedness `free'.
For more information, try recompiling with `-E'.
Index: tests/invalid/merge_ground_any.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/merge_ground_any.err_exp,v
retrieving revision 1.1
diff -u -u -r1.1 merge_ground_any.err_exp
--- tests/invalid/merge_ground_any.err_exp 13 Sep 2001 23:18:17 -0000 1.1
+++ tests/invalid/merge_ground_any.err_exp 13 Jun 2002 13:01:40 -0000
@@ -1,5 +1,5 @@
merge_ground_any.m:013: In clause for `pass(in, in(merge_ground_any:hpair(ground, any)), out(merge_ground_any:hpair(ground, any)))':
merge_ground_any.m:013: mode error: argument 5 did not get sufficiently instantiated.
-merge_ground_any.m:013: Final instantiatedness of `HeadVar__3' was `bound(merge_ground_any:'+'(ground, ground) ; merge_ground_any:'-'(ground, any))',
+merge_ground_any.m:013: Final instantiatedness of `X' was `bound(merge_ground_any:'+'(ground, ground) ; merge_ground_any:'-'(ground, any))',
merge_ground_any.m:013: expected final instantiatedness was `merge_ground_any:hpair(ground, any)'.
For more information, try recompiling with `-E'.
Index: tests/invalid/polymorphic_unification.err_exp
===================================================================
RCS file: /home/mercury1/repository/tests/invalid/polymorphic_unification.err_exp,v
retrieving revision 1.4
diff -u -u -r1.4 polymorphic_unification.err_exp
--- tests/invalid/polymorphic_unification.err_exp 11 Aug 2001 09:21:21 -0000 1.4
+++ tests/invalid/polymorphic_unification.err_exp 12 Jun 2002 09:52:15 -0000
@@ -1,5 +1,5 @@
polymorphic_unification.m:019: In clause for `p(in, ((list:list_skel) -> dead))':
polymorphic_unification.m:019: in polymorphically-typed unification:
-polymorphic_unification.m:019: mode error: variable `HeadVar__2' has instantiatedness `(list:list_skel)',
+polymorphic_unification.m:019: mode error: variable `X' has instantiatedness `(list:list_skel)',
polymorphic_unification.m:019: expected instantiatedness was `ground' or `any'.
For more information, try recompiling with `-E'.
--------------------------------------------------------------------------
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