[m-rev.] diff: fix bug in determinism analysis

Zoltan Somogyi zs at csse.unimelb.edu.au
Wed Jun 15 13:27:56 AEST 2011


compiler/det_analysis.m:
	Fix a bug: when computing FailingContexts for a complicated
	unification, allow the complicated unification to be of the form
	X = f(...) as well as X = Y.

	Add conditionally-compiled trace code to help debug problems like this.

tests/hard_coded/complicated_unify_bug.{m,exp}:
	New test case to test for the bug.

tests/hard_coded/Mmakefile:
	Enable the new test case.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/extra
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/extra
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/doc
cvs diff: Diffing boehm_gc/libatomic_ops/src
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/armcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops/tests
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/m4
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/det_analysis.m,v
retrieving revision 1.230
diff -u -b -r1.230 det_analysis.m
--- compiler/det_analysis.m	23 May 2011 05:08:01 -0000	1.230
+++ compiler/det_analysis.m	14 Jun 2011 09:20:47 -0000
@@ -286,6 +286,14 @@
         SolnContext = all_solns
     ),
 
+    trace [compiletime(flag("debug-det-analysis-progress")), io(!IO)] (
+        io.write_string("inferring procedure ", !IO),
+        io.write(PredId, !IO),
+        io.write_string("/", !IO),
+        io.write(ProcId, !IO),
+        io.nl(!IO)
+    ),
+
     % Infer the determinism of the goal.
     proc_info_get_goal(ProcInfo0, Goal0),
     proc_info_get_initial_instmap(ProcInfo0, !.ModuleInfo, InstMap0),
@@ -617,9 +625,19 @@
         GoalExpr = disj(Goals)
     ;
         GoalExpr0 = switch(Var, SwitchCanFail, Cases0),
+        trace [compiletime(flag("debug-det-analysis-progress")), io(!IO)] (
+            io.write_string("inferring switch on ", !IO),
+            io.write(Var, !IO),
+            io.nl(!IO)
+        ),
         det_infer_switch(Var, SwitchCanFail, Cases0, Cases, GoalInfo, InstMap0,
             SolnContext, RightFailingContexts, MaybePromiseEqvSolutionSets,
             Detism, GoalFailingContexts, !DetInfo),
+        trace [compiletime(flag("debug-det-analysis-progress")), io(!IO)] (
+            io.write_string("done inferring switch on ", !IO),
+            io.write(Var, !IO),
+            io.nl(!IO)
+        ),
         GoalExpr = switch(Var, SwitchCanFail, Cases)
     ;
         GoalExpr0 = plain_call(PredId, ProcId0, Args, Builtin, UnifyContext,
@@ -971,6 +989,13 @@
     bind_var_to_functors(Var, VarType, MainConsId, OtherConsIds,
         InstMap0, InstMap1, ModuleInfo0, ModuleInfo),
     det_info_set_module_info(ModuleInfo, !DetInfo),
+    trace [compiletime(flag("debug-det-analysis-progress")), io(!IO)] (
+        io.write_string("inferring switch case for ", !IO),
+        io.write(Var, !IO),
+        io.write_string(" with main cons id ", !IO),
+        io.write(MainConsId, !IO),
+        io.nl(!IO)
+    ),
     det_infer_goal(Goal0, Goal, InstMap1, SolnContext, RightFailingContexts,
         MaybePromiseEqvSolutionSets, FirstDetism, GoalFailingContexts,
         !DetInfo),
@@ -1205,6 +1230,15 @@
 det_infer_unify(LHS, RHS0, Unify, UnifyContext, RHS, GoalInfo, InstMap0,
         SolnContext, RightFailingContexts, Detism, GoalFailingContexts,
         !DetInfo) :-
+    trace [compiletime(flag("debug-det-analysis-progress")), io(!IO)] (
+        io.write_string("inferring unification ", !IO),
+        io.write(LHS, !IO),
+        io.write_string(" = ", !IO),
+        io.write(RHS0, !IO),
+        io.nl(!IO),
+        io.write(Unify, !IO),
+        io.nl(!IO)
+    ),
     % Unifications are either deterministic or semideterministic.
     (
         RHS0 = rhs_lambda_goal(Purity, Groundness, PredOrFunc, EvalMethod,
@@ -1247,15 +1281,17 @@
             Unify = complicated_unify(_, _, _),
             (
                 RHS = rhs_var(RHSVar),
-                FailingGoal = test_goal(LHS, RHSVar),
-                FailingContext = failing_context(Context, FailingGoal),
-                GoalFailingContexts = [FailingContext]
+                FailingGoal = test_goal(LHS, RHSVar)
             ;
-                ( RHS = rhs_functor(_, _, _)
-                ; RHS = rhs_lambda_goal(_, _, _, _, _, _, _, _, _)
+                RHS = rhs_functor(ConsId, _, _),
+                FailingGoal = deconstruct_goal(LHS, ConsId)
+            ;
+                RHS = rhs_lambda_goal(_, _, _, _, _, _, _, _, _),
+                unexpected($module, $pred,
+                    "complicated_unify but no fail context")
                 ),
-                unexpected($module, $pred, "complicated_unify but no var")
-            )
+            FailingContext = failing_context(Context, FailingGoal),
+            GoalFailingContexts = [FailingContext]
         ;
             Unify = deconstruct(Var, ConsId, _, _, _, _),
             FailingGoal = deconstruct_goal(Var, ConsId),
@@ -1288,6 +1324,9 @@
     % SolnContext correctly.
 
     % First process the `then' part.
+    trace [compiletime(flag("debug-det-analysis-progress")), io(!IO)] (
+        io.write_string("inferring condition\n", !IO)
+    ),
     update_instmap(Cond0, InstMap0, InstMap1),
     det_infer_goal(Then0, Then, InstMap1, SolnContext, RightFailingContexts,
         MaybePromiseEqvSolutionSets, ThenDetism, ThenFailingContexts,
@@ -1305,14 +1344,20 @@
     ;
         CondSolnContext = all_solns
     ),
-    % Process the `condition' part
+    % Process the `condition' part,
+    trace [compiletime(flag("debug-det-analysis-progress")), io(!IO)] (
+        io.write_string("inferring then-part\n", !IO)
+    ),
     det_infer_goal(Cond0, Cond, InstMap0, CondSolnContext,
         ThenFailingContexts ++ RightFailingContexts,
         MaybePromiseEqvSolutionSets, CondDetism, _CondFailingContexts,
         !DetInfo),
     determinism_components(CondDetism, CondCanFail, CondMaxSoln),
 
-    % Process the `else' part
+    % Process the `else' part.
+    trace [compiletime(flag("debug-det-analysis-progress")), io(!IO)] (
+        io.write_string("inferring else-part\n", !IO)
+    ),
     det_infer_goal(Else0, Else, InstMap0, SolnContext, RightFailingContexts,
         MaybePromiseEqvSolutionSets, ElseDetism, ElseFailingContexts,
         !DetInfo),
cvs diff: Diffing compiler/notes
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_cairo
cvs diff: Diffing extras/graphics/mercury_cairo/samples
cvs diff: Diffing extras/graphics/mercury_cairo/samples/data
cvs diff: Diffing extras/graphics/mercury_cairo/tutorial
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/monte
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/concurrency
cvs diff: Diffing samples/concurrency/dining_philosophers
cvs diff: Diffing samples/concurrency/midimon
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/java_interface
cvs diff: Diffing samples/java_interface/java_calls_mercury
cvs diff: Diffing samples/java_interface/mercury_calls_java
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.404
diff -u -b -r1.404 Mmakefile
--- tests/hard_coded/Mmakefile	24 May 2011 07:35:29 -0000	1.404
+++ tests/hard_coded/Mmakefile	15 Jun 2011 02:52:52 -0000
@@ -8,9 +8,9 @@
 	abstract_eqv \
 	address_of_builtins \
 	agg \
+	array_gen \
 	array_test \
 	array_test2 \
-	array_gen \
 	backquoted_qualified_ops \
 	bag_various \
 	bidirectional \
@@ -32,6 +32,7 @@
 	common_type_cast \
 	compare_spec \
 	comparison \
+	complicated_unify_bug \
 	constant_prop_1 \
 	constraint \
 	constraint_order \
Index: tests/hard_coded/complicated_unify_bug.exp
===================================================================
RCS file: tests/hard_coded/complicated_unify_bug.exp
diff -N tests/hard_coded/complicated_unify_bug.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/complicated_unify_bug.exp	14 Jun 2011 14:04:50 -0000
@@ -0,0 +1,6 @@
+a(2) aa
+a(5) aa
+b("4 four") diff
+b("five 5") diff
+b("six six") same
+b("seven eight") diff
Index: tests/hard_coded/complicated_unify_bug.m
===================================================================
RCS file: tests/hard_coded/complicated_unify_bug.m
diff -N tests/hard_coded/complicated_unify_bug.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/complicated_unify_bug.m	15 Jun 2011 02:57:47 -0000
@@ -0,0 +1,80 @@
+% vim: ts=4 sw=4 et ft=mercury
+%
+% We used to get this compiler abort on this file:
+%
+% Uncaught Mercury exception:
+% Software Error: check_hlds.det_analysis:
+% predicate `check_hlds.det_analysis.det_infer_unify'/13:
+% Unexpected: complicated_unify but no var
+%
+% The ultimate cause was the three-fold duplication of the X = Y test in p/4
+% due to the two-level switch on X and Y. In two of the copies, X and Y are
+% known to be non-unifiable (X = a/1 and Y = b/1 or vice versa). Both of those
+% copies of X = Y use a mode of the unification procedure of t that cannot
+% succeed, and which contain var/functor unifications that cannot succeed.
+% The compiler abort was due to determinism analysis not being able to compute
+% a failure context from a var/functor unification that cannot succeed.
+
+:- module complicated_unify_bug.
+
+:- interface.
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module bool.
+:- import_module int.
+:- import_module string.
+
+:- type t
+    --->    a(int)
+    ;       b(string).
+
+main(!IO) :-
+    do_test(a(1), a(1), !IO),
+    do_test(a(2), a(3), !IO),
+    do_test(a(4), b("four"), !IO),
+    do_test(b("five"), a(5), !IO),
+    do_test(b("six"), b("six"), !IO),
+    do_test(b("seven"), b("eight"), !IO).
+
+:- pred do_test(t::in, t::in, io::di, io::uo) is det.
+
+do_test(X, Y, !IO) :-
+    p(X, Y, Z, S),
+    io.write(Z, !IO),
+    io.write_string(" ", !IO),
+    io.write_string(S, !IO),
+    io.nl(!IO).
+
+:- pred p(t::in, t::in, t::out, string::out) is det.
+:- pragma no_inline(p/4).
+
+p(X, Y, Z, S) :-
+    (
+        X = a(XN),
+        Y = a(YN),
+        Z = a(XN + YN),
+        S = "aa"
+    ;
+        (
+            X = a(XN),
+            Y = b(YS),
+            Z = b(string.int_to_string(XN) ++ " " ++ YS)
+        ;
+            X = b(XS),
+            Y = a(YN),
+            Z = b(XS ++ " " ++ string.int_to_string(YN))
+        ;
+            X = b(XS),
+            Y = b(YS),
+            Z = b(XS ++ " " ++ YS)
+        ),
+        ( if X = Y then
+            S = "same"
+        else
+            S = "diff"
+        )
+    ).
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list