[m-rev.] for review: use java generics

Peter Wang novalazy at gmail.com
Fri Apr 9 15:48:44 AEST 2010


Branches: main, 10.04

Make the Java backend use generics in the output.  We do not use generics
everywhere, only where it interfaces with hand written code:

- in classes generated for Mercury types
- in the signatures of foreign_exported procedures
- in the variables which interface with foreign_proc code

Make `--java-export-ref-out' be the default.  Both changes will require users
to update their code so we might as well make them together.


compiler/mlds.m:
compiler/ml_proc_gen.m:
compiler/ml_type_gen.m:
        Record type parameters for classes generated for Mercury types.

        Record universally quantified type variables for exported procedures.

compiler/mlds_to_java.m:
        Output type variables in the appropriate places in the Java output.

compiler/ml_code_util.m:
        Add functions to return the MLDS types for jmercury.runtime.MercuryType
        and MercuryEnum.

compiler/ml_elim_nested.m:
compiler/ml_global_data.m:
compiler/ml_optimize.m:
compiler/ml_tailcall.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_il.m:
        Conform to previous changes.

compiler/hlds_pred.m:
        Change a wrong use of a type synonym.

compiler/options.m:
        Change `--java-export-ref-out' to be enabled by default.

doc/reference_manual.texi:
        Update manual to mention use of generics and `--java-export-ref-out'.

library/exception.m:
library/io.m:
library/list.m:
library/rtti_implementation.m:
library/string.m:
library/type_desc.m:
        Update code to comply with use of generics and `--java-export-ref-out'.

tests/hard_coded/exceptions/Mmakefile:
        Allow `java' grade testing in this directory.

diff --git a/compiler/hlds_pred.m b/compiler/hlds_pred.m
index 9c7b9f8..059998e 100644
--- a/compiler/hlds_pred.m
+++ b/compiler/hlds_pred.m
@@ -722,7 +722,7 @@
 :- pred pred_info_set_arg_types(tvarset::in, existq_tvars::in,
     list(mer_type)::in, pred_info::in, pred_info::out) is det.
 
-:- pred pred_info_get_univ_quant_tvars(pred_info::in, existq_tvars::out)
+:- pred pred_info_get_univ_quant_tvars(pred_info::in, list(tvar)::out)
     is det.
 
 :- pred pred_info_proc_info(pred_info::in, proc_id::in, proc_info::out) is det.
diff --git a/compiler/ml_code_util.m b/compiler/ml_code_util.m
index 9e8d19e..603bc97 100644
--- a/compiler/ml_code_util.m
+++ b/compiler/ml_code_util.m
@@ -140,6 +140,16 @@
     %
 :- func ml_make_boxed_types(arity) = list(mer_type).
 
+    % Return the MLDS type corresponding to the `jmercury.runtime.MercuryType'
+    % interface.
+    %
+:- func ml_java_mercury_type_interface = mlds_type.
+
+    % Return the MLDS type corresponding to the `jmercury.runtime.MercuryEnum'
+    % class.
+    %
+:- func ml_java_mercury_enum_class = mlds_type.
+
 %-----------------------------------------------------------------------------%
 %
 % Routines for generating function declarations (i.e. mlds_func_params).
@@ -554,6 +564,7 @@
 :- import_module ml_backend.ml_call_gen.
 :- import_module ml_backend.ml_code_gen.
 :- import_module parse_tree.builtin_lib_types.
+:- import_module parse_tree.java_names.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_util.
@@ -813,6 +824,18 @@ ml_make_boxed_types(Arity) = BoxedTypes :-
     varset.new_vars(TypeVarSet0, Arity, BoxedTypeVars, _TypeVarSet),
     prog_type.var_list_to_type_list(map.init, BoxedTypeVars, BoxedTypes).
 
+ml_java_mercury_type_interface = TypeInterfaceDefn :-
+    InterfaceModuleName = mercury_module_name_to_mlds(
+        java_names.mercury_runtime_package_name),
+    TypeInterface = qual(InterfaceModuleName, module_qual, "MercuryType"),
+    TypeInterfaceDefn = mlds_class_type(TypeInterface, 0, mlds_interface).
+
+ml_java_mercury_enum_class = EnumClassDefn :-
+    InterfaceModuleName = mercury_module_name_to_mlds(
+        java_names.mercury_runtime_package_name),
+    EnumClass = qual(InterfaceModuleName, module_qual, "MercuryEnum"),
+    EnumClassDefn = mlds_class_type(EnumClass, 0, mlds_class).
+
 %-----------------------------------------------------------------------------%
 %
 % Code for generating function declarations (i.e. mlds_func_params).
diff --git a/compiler/ml_elim_nested.m b/compiler/ml_elim_nested.m
index 5babbc9..f5d9af3 100644
--- a/compiler/ml_elim_nested.m
+++ b/compiler/ml_elim_nested.m
@@ -850,10 +850,11 @@ ml_create_env(Action, EnvClassName, EnvTypeName, LocalVars, Context,
     ),
 
     Imports = [],
-    Ctors = [],     % mlds_to_il.m will add an empty constructor if needed.
     Interfaces = [],
+    TypeParams = [],
+    Ctors = [],     % mlds_to_il.m will add an empty constructor if needed.
     EnvTypeDefnBody = mlds_class(mlds_class_defn(EnvTypeKind, Imports,
-        BaseClasses, Interfaces, Ctors, Fields)),
+        BaseClasses, Interfaces, TypeParams, Ctors, Fields)),
     EnvTypeDefn = mlds_defn(EnvTypeEntityName, Context, EnvTypeFlags,
         EnvTypeDefnBody),
 
@@ -2335,7 +2336,7 @@ defn_contains_matching_defn(Filter, Defn) :-
         ;
             DefnBody = mlds_class(ClassDefn),
             ClassDefn = mlds_class_defn(_Kind, _Imports, _Inherits,
-                _Implements, CtorDefns, FieldDefns),
+                _Implements, _TypeParams, CtorDefns, FieldDefns),
             (
                 defns_contains_matching_defn(Filter, FieldDefns)
             ;
diff --git a/compiler/ml_global_data.m b/compiler/ml_global_data.m
index 228bd4b..846b5cd 100644
--- a/compiler/ml_global_data.m
+++ b/compiler/ml_global_data.m
@@ -463,7 +463,8 @@ ml_gen_static_vector_type(MLDS_ModuleName, MLDS_Context, Target, ArgTypes,
         ml_gen_vector_cell_field_types(MLDS_Context, FieldFlags,
             FieldNamePrefix, 0, ArgTypes, FieldNames, FieldDefns),
 
-        ClassDefn = mlds_class_defn(mlds_struct, [], [], [], [], FieldDefns),
+        ClassDefn = mlds_class_defn(mlds_struct, [], [], [], [], [],
+            FieldDefns),
         StructTypeName = "vector_common_type_" ++ TypeRawNumStr,
         StructTypeEntityName = entity_type(StructTypeName, 0),
         StructTypeEntityDefn = mlds_class(ClassDefn),
diff --git a/compiler/ml_optimize.m b/compiler/ml_optimize.m
index 4d03525..c18994d 100644
--- a/compiler/ml_optimize.m
+++ b/compiler/ml_optimize.m
@@ -103,11 +103,11 @@ optimize_in_defn(ModuleName, Globals, Defn0, Defn) :-
     ;
         DefnBody0 = mlds_class(ClassDefn0),
         ClassDefn0 = mlds_class_defn(Kind, Imports, BaseClasses, Implements,
-            CtorDefns0, MemberDefns0),
+            TypeParams, CtorDefns0, MemberDefns0),
         optimize_in_defns(Globals, ModuleName, MemberDefns0, MemberDefns),
         optimize_in_defns(Globals, ModuleName, CtorDefns0, CtorDefns),
         ClassDefn = mlds_class_defn(Kind, Imports, BaseClasses, Implements,
-            CtorDefns, MemberDefns),
+            TypeParams, CtorDefns, MemberDefns),
         DefnBody = mlds_class(ClassDefn),
         Defn = mlds_defn(Name, Context, Flags, DefnBody)
     ).
diff --git a/compiler/ml_proc_gen.m b/compiler/ml_proc_gen.m
index 2b566fb..d587370 100644
--- a/compiler/ml_proc_gen.m
+++ b/compiler/ml_proc_gen.m
@@ -210,10 +210,13 @@ ml_gen_pragma_export_proc(ModuleInfo, PragmaExportedProc, Defn) :-
     PragmaExportedProc = pragma_exported_proc(Lang, PredId, ProcId,
         ExportName, ProgContext),
     ml_gen_proc_label(ModuleInfo, PredId, ProcId, Name, ModuleName),
+    MLDS_Name = qual(ModuleName, module_qual, Name),
     ml_gen_export_proc_params(ModuleInfo, PredId, ProcId, FuncParams),
+    module_info_pred_info(ModuleInfo, PredId, PredInfo),
+    pred_info_get_univ_quant_tvars(PredInfo, UnivQTVars),
     MLDS_Context = mlds_make_context(ProgContext),
-    Defn = ml_pragma_export(Lang, ExportName,
-        qual(ModuleName, module_qual, Name), FuncParams, MLDS_Context).
+    Defn = ml_pragma_export(Lang, ExportName, MLDS_Name, FuncParams,
+        UnivQTVars, MLDS_Context).
 
 :- pred ml_gen_export_proc_params(module_info::in, pred_id::in, proc_id::in,
     mlds_func_params::out) is det.
diff --git a/compiler/ml_tailcall.m b/compiler/ml_tailcall.m
index fe819dd..f281666 100644
--- a/compiler/ml_tailcall.m
+++ b/compiler/ml_tailcall.m
@@ -163,11 +163,11 @@ mark_tailcalls_in_defn(Defn0, Defn) :-
     ;
         DefnBody0 = mlds_class(ClassDefn0),
         ClassDefn0 = mlds_class_defn(Kind, Imports, BaseClasses, Implements,
-            CtorDefns0, MemberDefns0),
+            TypeParams, CtorDefns0, MemberDefns0),
         mark_tailcalls_in_defns(CtorDefns0, CtorDefns),
         mark_tailcalls_in_defns(MemberDefns0, MemberDefns),
         ClassDefn = mlds_class_defn(Kind, Imports, BaseClasses, Implements,
-            CtorDefns, MemberDefns),
+            TypeParams, CtorDefns, MemberDefns),
         DefnBody = mlds_class(ClassDefn),
         Defn = mlds_defn(Name, Context, Flags, DefnBody)
     ).
@@ -634,7 +634,7 @@ nontailcall_in_defn(ModuleName, Defn, Warning) :-
     ;
         DefnBody = mlds_class(ClassDefn),
         ClassDefn = mlds_class_defn(_Kind, _Imports, _BaseClasses,
-            _Implements, CtorDefns, MemberDefns),
+            _Implements, _TypeParams, CtorDefns, MemberDefns),
         ( nontailcall_in_defns(ModuleName, CtorDefns, Warning)
         ; nontailcall_in_defns(ModuleName, MemberDefns, Warning)
         )
diff --git a/compiler/ml_type_gen.m b/compiler/ml_type_gen.m
index 51b0098..6fc69e4 100644
--- a/compiler/ml_type_gen.m
+++ b/compiler/ml_type_gen.m
@@ -260,14 +260,8 @@ ml_gen_enum_type(Target, TypeCtor, TypeDefn, Ctors, TagValues,
     % interface and extend the MercuryEnum class.
     (
         Target = target_java,
-        InterfaceModuleName = mercury_module_name_to_mlds(
-            java_names.mercury_runtime_package_name),
-        TypeInterface = qual(InterfaceModuleName, module_qual, "MercuryType"),
-        TypeInterfaceDefn = mlds_class_type(TypeInterface, 0, mlds_interface),
-        EnumClass = qual(InterfaceModuleName, module_qual, "MercuryEnum"),
-        EnumClassDefn = mlds_class_type(EnumClass, 0, mlds_class),
-        Implements = [TypeInterfaceDefn],
-        Inherits = [EnumClassDefn]
+        Implements = [ml_java_mercury_type_interface],
+        Inherits = [ml_java_mercury_enum_class]
     ;
         ( Target = target_c
         ; Target = target_il
@@ -279,11 +273,13 @@ ml_gen_enum_type(Target, TypeCtor, TypeDefn, Ctors, TagValues,
         Inherits = []
     ),
 
+    get_type_defn_tparams(TypeDefn, TypeVars),
+
     % Put it all together.
     MLDS_TypeName = entity_type(MLDS_ClassName, MLDS_ClassArity),
     MLDS_TypeFlags = ml_gen_type_decl_flags,
     MLDS_TypeDefnBody = mlds_class(mlds_class_defn(mlds_enum,
-        Imports, Inherits, Implements, [], Members)),
+        Imports, Inherits, Implements, TypeVars, [], Members)),
     Defn = mlds_defn(MLDS_TypeName, MLDS_Context, MLDS_TypeFlags,
         MLDS_TypeDefnBody),
 
@@ -509,11 +505,7 @@ ml_gen_du_parent_type(ModuleInfo, TypeCtor, TypeDefn, Ctors, TagValues,
     % interface.
     (
         Target = target_java,
-        InterfaceModuleName = mercury_module_name_to_mlds(
-            java_names.mercury_runtime_package_name),
-        Interface = qual(InterfaceModuleName, module_qual, "MercuryType"),
-        InterfaceDefn = mlds_class_type(Interface, 0, mlds_interface),
-        Implements = [InterfaceDefn]
+        Implements = [ml_java_mercury_type_interface]
     ;
         ( Target = target_c
         ; Target = target_il
@@ -524,12 +516,14 @@ ml_gen_du_parent_type(ModuleInfo, TypeCtor, TypeDefn, Ctors, TagValues,
         Implements = []
     ),
 
+    get_type_defn_tparams(TypeDefn, TypeParams),
+
     % Put it all together.
     Members = MaybeEqualityMembers ++ TagMembers ++ CtorMembers,
     MLDS_TypeName = entity_type(BaseClassName, BaseClassArity),
     MLDS_TypeFlags = ml_gen_type_decl_flags,
-    MLDS_TypeDefnBody = mlds_class(mlds_class_defn(mlds_class,
-        Imports, Inherits, Implements, BaseClassCtorMethods, Members)),
+    MLDS_TypeDefnBody = mlds_class(mlds_class_defn(mlds_class, Imports,
+        Inherits, Implements, TypeParams, BaseClassCtorMethods, Members)),
     Defn = mlds_defn(MLDS_TypeName, MLDS_Context, MLDS_TypeFlags,
         MLDS_TypeDefnBody),
 
@@ -639,11 +633,15 @@ ml_gen_secondary_tag_class(MLDS_Context, BaseClassQualifier, BaseClassId,
     Implements = [],
     Ctors = [],
 
+    % Type parameters are only used by the Java backend, which doesn't use
+    % secondary tag classes.
+    TypeParams = [],
+
     % Put it all together.
     MLDS_TypeName = entity_type(UnqualClassName, ClassArity),
     MLDS_TypeFlags = ml_gen_type_decl_flags,
-    MLDS_TypeDefnBody = mlds_class(mlds_class_defn(mlds_class,
-        Imports, Inherits, Implements, Ctors, Members)),
+    MLDS_TypeDefnBody = mlds_class(mlds_class_defn(mlds_class, Imports,
+        Inherits, Implements, TypeParams, Ctors, Members)),
     MLDS_TypeDefn = mlds_defn(MLDS_TypeName, MLDS_Context,
         MLDS_TypeFlags, MLDS_TypeDefnBody).
 
@@ -830,12 +828,13 @@ ml_gen_du_ctor_member(ModuleInfo, BaseClassId, BaseClassQualifier,
             ),
             Imports = [],
             Implements = [],
+            get_type_defn_tparams(TypeDefn, TypeParams),
 
             % Put it all together.
             MLDS_TypeName = entity_type(UnqualCtorName, CtorArity),
             MLDS_TypeFlags = ml_gen_type_decl_flags,
-            MLDS_TypeDefnBody = mlds_class(mlds_class_defn(
-                mlds_class, Imports, Inherits, Implements, Ctors, Members)),
+            MLDS_TypeDefnBody = mlds_class(mlds_class_defn(mlds_class,
+                Imports, Inherits, Implements, TypeParams, Ctors, Members)),
             MLDS_TypeDefn = mlds_defn(MLDS_TypeName, MLDS_Context,
                 MLDS_TypeFlags, MLDS_TypeDefnBody),
             MLDS_Members = [MLDS_TypeDefn | MLDS_Members0],
diff --git a/compiler/ml_util.m b/compiler/ml_util.m
index c88391d..b2f1ac6 100644
--- a/compiler/ml_util.m
+++ b/compiler/ml_util.m
@@ -682,7 +682,7 @@ defn_body_contains_var(DefnBody, DataName) = ContainsVar :-
     ;
         DefnBody = mlds_class(ClassDefn),
         ClassDefn = mlds_class_defn(_Kind, _Imports, _Inherits, _Implements,
-            CtorDefns, FieldDefns),
+            _TypeParams, CtorDefns, FieldDefns),
         ( defns_contains_var(FieldDefns, DataName) = yes ->
             ContainsVar = yes
         ;
diff --git a/compiler/mlds.m b/compiler/mlds.m
index b1e7f22..5721717 100644
--- a/compiler/mlds.m
+++ b/compiler/mlds.m
@@ -708,6 +708,9 @@
                 % Implements these interfaces.
                 mcd_implements  :: list(mlds_interface_id),
 
+                % Type parameters.
+                mcd_tparams     :: list(type_param),
+
                 % Has these constructors.
                 mcd_ctors       :: list(mlds_defn),
 
@@ -956,6 +959,8 @@
                 string,                        % Exported name
                 mlds_qualified_entity_name,    % MLDS name for exported entity
                 mlds_func_params,              % MLDS function parameters
+                list(tvar),                    % Universally quantified type
+                                               % variables.
                 mlds_context
             ).
 
diff --git a/compiler/mlds_to_c.m b/compiler/mlds_to_c.m
index 283fd44..bce951b 100644
--- a/compiler/mlds_to_c.m
+++ b/compiler/mlds_to_c.m
@@ -995,7 +995,7 @@ mlds_output_c_defn(Opts, _Indent, UserForeignCode, !IO) :-
 
 mlds_output_pragma_export_defn(Opts, ModuleName, Indent, PragmaExport, !IO) :-
     PragmaExport = ml_pragma_export(Lang, _ExportName, MLDS_Name,
-        MLDS_Signature, Context),
+        MLDS_Signature, _UnivQTVars, Context),
     expect(unify(Lang, lang_c), this_file,
         "foreign_export to language other than C."),
     mlds_output_pragma_export_func_name(Opts, ModuleName, Indent,
@@ -1015,7 +1015,8 @@ mlds_output_pragma_export_defn(Opts, ModuleName, Indent, PragmaExport, !IO) :-
     io::di, io::uo) is det.
 
 mlds_output_pragma_export_func_name(Opts, ModuleName, Indent, Export, !IO) :-
-    Export = ml_pragma_export(Lang, ExportName, _MLDSName, Signature, Context),
+    Export = ml_pragma_export(Lang, ExportName, _MLDSName, Signature,
+        _UnivQTVars, Context),
     expect(unify(Lang, lang_c), this_file, "export to language other than C."),
     Name = qual(ModuleName, module_qual, entity_export(ExportName)),
     output_context_opts(Opts, Context, !IO),
@@ -1867,7 +1868,7 @@ mlds_output_class(Opts, Indent, Name, Context, ClassDefn, !IO) :-
     % not when compiling to C++
 
     ClassDefn = mlds_class_defn(Kind, _Imports, BaseClasses, _Implements,
-        Ctors, Members),
+        _TypeParams, Ctors, Members),
 
     AllMembers = Ctors ++ Members,
 
diff --git a/compiler/mlds_to_gcc.m b/compiler/mlds_to_gcc.m
index 032e69e..de044a4 100644
--- a/compiler/mlds_to_gcc.m
+++ b/compiler/mlds_to_gcc.m
@@ -1257,7 +1257,7 @@ gen_class(Name, Context, ClassDefn, !GlobalInfo, !IO) :-
     % not when compiling to C++
 
     ClassDefn = mlds_class_defn(Kind, _Imports, BaseClasses, _Implements,
-        Ctors, AllMembers),
+        _TypeParams, Ctors, AllMembers),
     (
         Ctors = []
     ;
diff --git a/compiler/mlds_to_il.m b/compiler/mlds_to_il.m
index 4dea644..157154e 100644
--- a/compiler/mlds_to_il.m
+++ b/compiler/mlds_to_il.m
@@ -414,7 +414,7 @@ wrapper_class(Members) =
         entity_export(wrapper_class_name),
         mlds_make_context(term.context_init),
         ml_gen_type_decl_flags,
-        mlds_class(mlds_class_defn(mlds_package, [], [], [], [], Members))
+        mlds_class(mlds_class_defn(mlds_package, [], [], [], [], [], Members))
     ).
 
 %-----------------------------------------------------------------------------%
@@ -447,9 +447,11 @@ rename_defn(Defn0) = Defn :-
     ;
         Entity0 = mlds_class(ClassDefn0),
         ClassDefn0 = mlds_class_defn(Kind, Imports, Inherits, Implements,
-            Ctors, Members),
+            TypeParams, Ctors0, Members0),
+        Ctors = list.map(rename_defn, Ctors0),
+        Members = list.map(rename_defn, Members0),
         ClassDefn = mlds_class_defn(Kind, Imports, Inherits, Implements,
-            list.map(rename_defn, Ctors), list.map(rename_defn, Members)),
+            TypeParams, Ctors, Members),
         Entity = mlds_class(ClassDefn)
     ),
     Defn = mlds_defn(Name, Context, Flags, Entity).
@@ -710,7 +712,7 @@ generate_class_body(Name, Context, ClassDefn, ClassName, EntityName, Extends,
         Interfaces, ClassMembers, !Info) :-
     EntityName = entity_name_to_ilds_id(Name),
     ClassDefn = mlds_class_defn(Kind, _Imports, Inherits, Implements,
-        Ctors0, Members),
+        _TypeParams, Ctors0, Members),
     Parent - Extends = generate_parent_and_extends(!.Info ^ il_data_rep,
         Kind, Inherits),
     Interfaces = implements(
@@ -1380,7 +1382,7 @@ attribute_to_custom_attribute(DataRep, custom(MLDSType))
 
 mlds_export_to_mlds_defn(ExportDefn, Defn) :-
     ExportDefn = ml_pragma_export(Lang, ExportName, EntityName, Params,
-        Context),
+        _UnivQTVars, Context),
     EntityName = qual(ModuleName, _QualKind, UnqualName),
     expect(unify(Lang, lang_il), this_file,
         "export for language other than IL."),
@@ -4459,7 +4461,7 @@ il_info_init(ModuleName, AssemblyName, Imports, ILDataRep,
     is det.
 
 il_info_new_class(ClassDefn, !Info) :-
-    ClassDefn = mlds_class_defn(_, _, _, _, _, Members),
+    ClassDefn = mlds_class_defn(_, _, _, _, _, _, Members),
     list.filter_map(
         (pred(M::in, S::out) is semidet :-
             M = mlds_defn(Name, _, _, mlds_data(_, _, _)),
diff --git a/compiler/mlds_to_java.m b/compiler/mlds_to_java.m
index e67c43d..47d136d 100644
--- a/compiler/mlds_to_java.m
+++ b/compiler/mlds_to_java.m
@@ -124,6 +124,7 @@
 :- import_module string.
 :- import_module svmap.
 :- import_module term.
+:- import_module varset.
 
 %-----------------------------------------------------------------------------%
 
@@ -497,13 +498,21 @@ output_exports(Info, Indent, Exports, !IO) :-
 :- pred output_export(java_out_info::in, indent::in, mlds_pragma_export::in,
     io::di, io::uo) is det.
 
-output_export(Info, Indent, Export, !IO) :-
-    Export = ml_pragma_export(Lang, ExportName, _, MLDS_Signature, _),
+output_export(Info0, Indent, Export, !IO) :-
+    Export = ml_pragma_export(Lang, ExportName, _, MLDS_Signature,
+        UnivQTVars, _),
     expect(unify(Lang, lang_java), this_file,
         "foreign_export for language other than Java."),
+
     indent_line(Indent, !IO),
     io.write_string("public static ", !IO),
+    output_generic_tvars(UnivQTVars, !IO),
+    io.nl(!IO),
+    indent_line(Indent, !IO),
+
     MLDS_Signature = mlds_func_params(Parameters, ReturnTypes),
+    Info = (Info0 ^ joi_output_generics := do_output_generics)
+                  ^ joi_univ_tvars := UnivQTVars,
     (
         ReturnTypes = [],
         io.write_string("void", !IO)
@@ -538,9 +547,9 @@ output_export(Info, Indent, Export, !IO) :-
 
 output_export_no_ref_out(Info, Indent, Export, !IO) :-
     Export = ml_pragma_export(_Lang, _ExportName, MLDS_Name, MLDS_Signature,
-        MLDS_Context),
+        _UnivQTVars, _MLDS_Context),
     MLDS_Signature = mlds_func_params(Parameters, ReturnTypes),
-    output_params(Info, Indent + 1, MLDS_Context, Parameters, !IO),
+    output_params(Info, Indent + 1, Parameters, !IO),
     io.nl(!IO),
     indent_line(Indent, !IO),
     io.write_string("{\n", !IO),
@@ -548,7 +557,14 @@ output_export_no_ref_out(Info, Indent, Export, !IO) :-
     (
         ReturnTypes = []
     ;
-        ReturnTypes = [_ | _],
+        ReturnTypes = [RetType],
+        % The cast is required when the exported method uses generics but the
+        % underlying method does not use generics (i.e. returns Object).
+        io.write_string("return (", !IO),
+        output_type(Info, normal_style, RetType, !IO),
+        io.write_string(") ", !IO)
+    ;
+        ReturnTypes = [_, _ | _],
         io.write_string("return ", !IO)
     ),
     write_export_call(MLDS_Name, Parameters, !IO),
@@ -560,11 +576,11 @@ output_export_no_ref_out(Info, Indent, Export, !IO) :-
 
 output_export_ref_out(Info, Indent, Export, !IO) :-
     Export = ml_pragma_export(_Lang, _ExportName, MLDS_Name, MLDS_Signature,
-        MLDS_Context),
+        _UnivQTVars, _MLDS_Context),
     MLDS_Signature = mlds_func_params(Parameters, ReturnTypes),
     list.filter(has_ptr_type, Parameters, RefParams, NonRefParams),
 
-    output_export_params_ref_out(Info, Indent, MLDS_Context, Parameters, !IO),
+    output_export_params_ref_out(Info, Indent, Parameters, !IO),
     io.nl(!IO),
     indent_line(Indent, !IO),
     io.write_string("{\n", !IO),
@@ -594,9 +610,9 @@ output_export_ref_out(Info, Indent, Export, !IO) :-
     io.write_string("}\n", !IO).
 
 :- pred output_export_params_ref_out(java_out_info::in, indent::in,
-    mlds_context::in, list(mlds_argument)::in, io::di, io::uo) is det.
+    list(mlds_argument)::in, io::di, io::uo) is det.
 
-output_export_params_ref_out(Info, Indent, Context, Parameters, !IO) :-
+output_export_params_ref_out(Info, Indent, Parameters, !IO) :-
     io.write_string("(", !IO),
     (
         Parameters = []
@@ -604,14 +620,14 @@ output_export_params_ref_out(Info, Indent, Context, Parameters, !IO) :-
         Parameters = [_ | _],
         io.nl(!IO),
         io.write_list(Parameters, ",\n",
-            output_export_param_ref_out(Info, Indent + 1, Context), !IO)
+            output_export_param_ref_out(Info, Indent + 1), !IO)
     ),
     io.write_string(")", !IO).
 
 :- pred output_export_param_ref_out(java_out_info::in, indent::in,
-    mlds_context::in, mlds_argument::in, io::di, io::uo) is det.
+    mlds_argument::in, io::di, io::uo) is det.
 
-output_export_param_ref_out(Info, Indent, _Context, Argument, !IO) :-
+output_export_param_ref_out(Info, Indent, Argument, !IO) :-
     Argument = mlds_argument(Name, Type, _),
     indent_line(Indent, !IO),
     ( Type = mlds_ptr_type(InnerType) ->
@@ -747,7 +763,7 @@ method_ptrs_in_entity_defn(mlds_data(_Type, Initializer, _GCStatement),
         !CodeAddrs) :-
     method_ptrs_in_initializer(Initializer, !CodeAddrs).
 method_ptrs_in_entity_defn(mlds_class(ClassDefn), !CodeAddrs) :-
-    ClassDefn = mlds_class_defn(_, _, _, _, Ctors, Members),
+    ClassDefn = mlds_class_defn(_, _, _, _, _, Ctors, Members),
     method_ptrs_in_defns(Ctors, !CodeAddrs),
     method_ptrs_in_defns(Members, !CodeAddrs).
 
@@ -1061,14 +1077,15 @@ generate_addr_wrapper_class(MLDS_ModuleName, Arity - CodeAddrs, ClassDefn,
     ClassExtends = [],
     InterfaceDefn = mlds_class_type(Interface, 0, mlds_interface),
     ClassImplements = [InterfaceDefn],
+    TypeParams = [],
 
     % Put it all together.
     ClassMembers  = DataDefns ++ [MethodDefn],
     ClassEntityName = entity_type(ClassName, 0),
     ClassContext  = mlds_make_context(term.context_init),
     ClassFlags    = addr_wrapper_decl_flags,
-    ClassBodyDefn = mlds_class_defn(mlds_class, ClassImports,
-        ClassExtends, ClassImplements, CtorDefns, ClassMembers),
+    ClassBodyDefn = mlds_class_defn(mlds_class, ClassImports, ClassExtends,
+        ClassImplements, TypeParams, CtorDefns, ClassMembers),
     ClassBody     = mlds_class(ClassBodyDefn),
     ClassDefn = mlds_defn(ClassEntityName, ClassContext, ClassFlags,
         ClassBody),
@@ -1419,11 +1436,11 @@ rename_class_names_defn(Renaming, !Defn) :-
             Attributes, EnvVarNames)
     ;
         EntityDefn0 = mlds_class(mlds_class_defn(ClassKind, Imports, Inherits,
-            Implements, Ctors0, Members0)),
+            Implements, TypeParams, Ctors0, Members0)),
         list.map(rename_class_names_defn(Renaming), Ctors0, Ctors),
         list.map(rename_class_names_defn(Renaming), Members0, Members),
         EntityDefn = mlds_class(mlds_class_defn(ClassKind, Imports, Inherits,
-            Implements, Ctors, Members))
+            Implements, TypeParams, Ctors, Members))
     ),
     !Defn ^ md_entity_defn := EntityDefn.
 
@@ -2102,7 +2119,7 @@ output_defn_body(Info, Indent, UnqualName, OutputAux, Context, Entity, !IO) :-
             Signature, MaybeBody, !IO)
     ;
         Entity = mlds_class(ClassDefn),
-        output_class(Info, Indent, UnqualName, Context, ClassDefn, !IO)
+        output_class(Info, Indent, UnqualName, ClassDefn, !IO)
     ).
 
 %-----------------------------------------------------------------------------%
@@ -2111,9 +2128,9 @@ output_defn_body(Info, Indent, UnqualName, OutputAux, Context, Entity, !IO) :-
 %
 
 :- pred output_class(java_out_info::in, indent::in, mlds_entity_name::in,
-    mlds_context::in, mlds_class_defn::in, io::di, io::uo) is det.
+    mlds_class_defn::in, io::di, io::uo) is det.
 
-output_class(Info, Indent, UnqualName, _Context, ClassDefn, !IO) :-
+output_class(!.Info, Indent, UnqualName, ClassDefn, !IO) :-
     (
         UnqualName = entity_type(ClassNamePrime, ArityPrime),
         ClassName = ClassNamePrime,
@@ -2126,30 +2143,71 @@ output_class(Info, Indent, UnqualName, _Context, ClassDefn, !IO) :-
         unexpected(this_file, "output_class: name is not entity_type.")
     ),
     ClassDefn = mlds_class_defn(Kind, _Imports, BaseClasses, Implements,
-        Ctors, AllMembers),
-    (
-        Kind = mlds_interface,
-        io.write_string("interface ", !IO)
+        TypeParams, Ctors, AllMembers),
+
+    !Info ^ joi_univ_tvars := TypeParams,
+
+    % Use generics in the output if this class represents a Mercury type.
+    ( list.member(ml_java_mercury_type_interface, Implements) ->
+        !Info ^ joi_output_generics := do_output_generics
     ;
-        ( Kind = mlds_class
-        ; Kind = mlds_package
-        ; Kind = mlds_enum
-        ; Kind = mlds_struct
-        ),
-        io.write_string("class ", !IO)
+        true
     ),
+
+    output_class_kind(Kind, !IO),
     output_class_name_and_arity(ClassName, Arity, !IO),
+    OutputGenerics = !.Info ^ joi_output_generics,
+    (
+        OutputGenerics = do_output_generics,
+        output_generic_tvars(TypeParams, !IO)
+    ;
+        OutputGenerics = do_not_output_generics
+    ),
     io.nl(!IO),
-    output_extends_list(Info, Indent + 1, BaseClasses, !IO),
+
+    output_extends_list(!.Info, Indent + 1, BaseClasses, !IO),
     output_implements_list(Indent + 1, Implements, !IO),
     indent_line(Indent, !IO),
     io.write_string("{\n", !IO),
-    output_class_body(Info, Indent + 1, Kind, UnqualName, AllMembers, !IO),
+    output_class_body(!.Info, Indent + 1, Kind, UnqualName, AllMembers, !IO),
     io.nl(!IO),
-    output_defns(Info, Indent + 1, cname(UnqualName), Ctors, !IO),
+    output_defns(!.Info, Indent + 1, cname(UnqualName), Ctors, !IO),
     indent_line(Indent, !IO),
     io.write_string("}\n\n", !IO).
 
+:- pred output_class_kind(mlds_class_kind::in, io::di, io::uo) is det.
+
+output_class_kind(Kind, !IO) :-
+    (
+        Kind = mlds_interface,
+        io.write_string("interface ", !IO)
+    ;
+        ( Kind = mlds_class
+        ; Kind = mlds_package
+        ; Kind = mlds_enum
+        ; Kind = mlds_struct
+        ),
+        io.write_string("class ", !IO)
+    ).
+
+:- pred output_generic_tvars(list(tvar)::in, io::di, io::uo) is det.
+
+output_generic_tvars(Vars, !IO) :-
+    (
+        Vars = []
+    ;
+        Vars = [_ | _],
+        io.write_string("<", !IO),
+        io.write_list(Vars, ", ", output_generic_tvar, !IO),
+        io.write_string(">", !IO)
+    ).
+
+:- pred output_generic_tvar(tvar::in, io::di, io::uo) is det.
+
+output_generic_tvar(Var, !IO) :-
+    varset.lookup_name(varset.init, Var, "MR_tvar_", VarName),
+    io.write_string(VarName, !IO).
+
     % Output superclass that this class extends. Java does not support
     % multiple inheritance, so more than one superclass is an error.
     %
@@ -2715,8 +2773,7 @@ output_func(Info, Indent, Name, OutputAux, Context, Signature, MaybeBody,
         !IO) :-
     (
         MaybeBody = body_defined_here(Body),
-        output_func_decl(Info, Indent, Name, OutputAux, Context, Signature,
-            !IO),
+        output_func_decl(Info, Indent, Name, OutputAux, Signature, !IO),
         io.write_string("\n", !IO),
         indent_line(Info, Context, Indent, !IO),
         io.write_string("{\n", !IO),
@@ -2728,59 +2785,59 @@ output_func(Info, Indent, Name, OutputAux, Context, Signature, MaybeBody,
         MaybeBody = body_external
     ).
 
-:- pred output_func_decl(java_out_info::in, indent::in,
-    mlds_entity_name::in, output_aux::in, mlds_context::in,
-    mlds_func_params::in, io::di, io::uo) is det.
+:- pred output_func_decl(java_out_info::in, indent::in, mlds_entity_name::in,
+    output_aux::in, mlds_func_params::in, io::di, io::uo) is det.
 
-output_func_decl(Info, Indent, Name, OutputAux, Context, Signature, !IO) :-
+output_func_decl(Info, Indent, Name, OutputAux, Signature, !IO) :-
+    Signature = mlds_func_params(Parameters, RetTypes),
     (
         OutputAux = cname(CtorName),
-        Signature = mlds_func_params(Parameters, _RetTypes),
-        output_name(CtorName, !IO),
-        output_params(Info, Indent, Context, Parameters, !IO)
+        Name = entity_export("<constructor>")
+    ->
+        output_name(CtorName, !IO)
     ;
-        ( OutputAux = none
-        ; OutputAux = alloc_only
-        ; OutputAux = force_init
-        ),
-        Signature = mlds_func_params(Parameters, RetTypes),
-        (
-            RetTypes = [],
-            io.write_string("void", !IO)
-        ;
-            RetTypes = [RetType],
-            output_type(Info, normal_style, RetType, !IO)
-        ;
-            RetTypes = [_, _ | _],
-            % For multiple outputs, we return an array of objects.
-            io.write_string("java.lang.Object []", !IO)
-        ),
+        output_return_types(Info, RetTypes, !IO),
         io.write_char(' ', !IO),
-        output_name(Name, !IO),
-        output_params(Info, Indent, Context, Parameters, !IO)
+        output_name(Name, !IO)
+    ),
+    output_params(Info, Indent, Parameters, !IO).
+
+:- pred output_return_types(java_out_info::in, mlds_return_types::in,
+    io::di, io::uo) is det.
+
+output_return_types(Info, RetTypes, !IO) :-
+    (
+        RetTypes = [],
+        io.write_string("void", !IO)
+    ;
+        RetTypes = [RetType],
+        output_type(Info, normal_style, RetType, !IO)
+    ;
+        RetTypes = [_, _ | _],
+        % For multiple outputs, we return an array of objects.
+        io.write_string("java.lang.Object []", !IO)
     ).
 
-:- pred output_params(java_out_info::in, indent::in, mlds_context::in,
-    mlds_arguments::in, io::di, io::uo) is det.
+:- pred output_params(java_out_info::in, indent::in, mlds_arguments::in,
+    io::di, io::uo) is det.
 
-output_params(Info, Indent, Context, Parameters, !IO) :-
+output_params(Info, Indent, Parameters, !IO) :-
     io.write_char('(', !IO),
     (
         Parameters = []
     ;
         Parameters = [_ | _],
         io.nl(!IO),
-        io.write_list(Parameters, ",\n",
-            output_param(Info, Indent + 1, Context), !IO)
+        io.write_list(Parameters, ",\n", output_param(Info, Indent + 1), !IO)
     ),
     io.write_char(')', !IO).
 
-:- pred output_param(java_out_info::in, indent::in, mlds_context::in,
-    mlds_argument::in, io::di, io::uo) is det.
+:- pred output_param(java_out_info::in, indent::in, mlds_argument::in,
+    io::di, io::uo) is det.
 
-output_param(Info, Indent, Context, Arg, !IO) :-
+output_param(Info, Indent, Arg, !IO) :-
     Arg = mlds_argument(Name, Type, _GCStatement),
-    indent_line(Info, Context, Indent, !IO),
+    indent_line(Indent, !IO),
     output_type(Info, normal_style, Type, !IO),
     io.write_char(' ', !IO),
     output_name(Name, !IO).
@@ -3098,7 +3155,7 @@ output_type(Info, Style, MLDS_Type, !IO) :-
         io.write_string("jmercury.runtime.MethodPtr", !IO)
     ;
         MLDS_Type = mlds_generic_type,
-        io.write_string("java.lang.Object", !IO)
+        io.write_string("/* generic_type */ java.lang.Object", !IO)
     ;
         MLDS_Type = mlds_generic_env_ptr_type,
         io.write_string("/* env_ptr */ java.lang.Object", !IO)
@@ -3162,7 +3219,15 @@ output_mercury_type(Info, Style, Type, CtorCat, !IO) :-
         io.write_string("builtin.Void_0", !IO)
     ;
         CtorCat = ctor_cat_variable,
-        io.write_string("java.lang.Object", !IO)
+        (
+            Info ^ joi_output_generics = do_output_generics,
+            Type = type_variable(TVar, kind_star),
+            list.member(TVar, Info ^ joi_univ_tvars)
+        ->
+            output_generic_tvar(TVar, !IO)
+        ;
+            io.write_string("java.lang.Object", !IO)
+        )
     ;
         CtorCat = ctor_cat_tuple,
         io.write_string("/* tuple */ java.lang.Object", !IO),
@@ -3187,18 +3252,43 @@ output_mercury_type(Info, Style, Type, CtorCat, !IO) :-
     mer_type::in, type_ctor_category::in, io::di, io::uo) is det.
 
 output_mercury_user_type(Info, Style, Type, CtorCat, !IO) :-
-    ( type_to_ctor_and_args(Type, TypeCtor, _ArgsTypes) ->
+    ( type_to_ctor_and_args(Type, TypeCtor, ArgsTypes) ->
         ml_gen_type_name(TypeCtor, ClassName, ClassArity),
         ( CtorCat = ctor_cat_enum(_) ->
             MLDS_Type = mlds_class_type(ClassName, ClassArity, mlds_enum)
         ;
             MLDS_Type = mlds_class_type(ClassName, ClassArity, mlds_class)
         ),
-        output_type(Info, Style, MLDS_Type, !IO)
+        output_type(Info, Style, MLDS_Type, !IO),
+        OutputGenerics = Info ^ joi_output_generics,
+        (
+            OutputGenerics = do_output_generics,
+            output_generics_args_types(Info, ArgsTypes, !IO)
+        ;
+            OutputGenerics = do_not_output_generics
+        )
     ;
         unexpected(this_file, "output_mercury_user_type: not a user type")
     ).
 
+:- pred output_generics_args_types(java_out_info::in, list(mer_type)::in,
+    io::di, io::uo) is det.
+
+output_generics_args_types(Info, ArgsTypes, !IO) :-
+    (
+        ArgsTypes = []
+    ;
+        ArgsTypes = [_ | _],
+        WriteType = (pred(ArgType::in, !.IO::di, !:IO::uo) is det :-
+            ModuleInfo = Info ^ joi_module_info,
+            MLDS_ArgType = mercury_type_to_mlds_type(ModuleInfo, ArgType),
+            output_boxed_type(Info, MLDS_ArgType, !IO)
+        ),
+        io.write_string("<", !IO),
+        io.write_list(ArgsTypes, ", ", WriteType, !IO),
+        io.write_string(">", !IO)
+    ).
+
 :- pred output_array_brackets(output_style::in, io::di, io::uo) is det.
 
 output_array_brackets(Style, !IO) :-
@@ -4123,7 +4213,8 @@ output_target_code_component(Info, TargetCode, !IO) :-
         output_lval(Info, Lval, !IO)
     ;
         TargetCode = target_code_type(Type),
-        output_type(Info, normal_style, Type, !IO)
+        InfoGenerics = Info ^ joi_output_generics := do_output_generics,
+        output_type(InfoGenerics, normal_style, Type, !IO)
     ;
         TargetCode = target_code_name(Name),
         output_maybe_qualified_name(Info, Name, !IO)
@@ -4745,12 +4836,22 @@ indent_line(N, !IO) :-
 
 :- type java_out_info
     --->    java_out_info(
+                % These are static.
+                joi_module_info     :: module_info,
                 joi_auto_comments   :: bool,
                 joi_line_numbers    :: bool,
                 joi_module_name     :: mlds_module_name,
-                joi_addrof_map      :: map(mlds_code_addr, code_addr_wrapper)
+                joi_addrof_map      :: map(mlds_code_addr, code_addr_wrapper),
+
+                % These are dynamic.
+                joi_output_generics :: output_generics,
+                joi_univ_tvars      :: list(tvar)
             ).
 
+:- type output_generics
+    --->    do_output_generics
+    ;       do_not_output_generics.
+
 :- func init_java_out_info(module_info, map(mlds_code_addr, code_addr_wrapper))
     = java_out_info.
 
@@ -4760,8 +4861,8 @@ init_java_out_info(ModuleInfo, AddrOfMap) = Info :-
     globals.lookup_bool_option(Globals, line_numbers, LineNumbers),
     module_info_get_name(ModuleInfo, ModuleName),
     MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
-    Info = java_out_info(AutoComments, LineNumbers, MLDS_ModuleName,
-        AddrOfMap).
+    Info = java_out_info(ModuleInfo, AutoComments, LineNumbers,
+        MLDS_ModuleName, AddrOfMap, do_not_output_generics, []).
 
 %-----------------------------------------------------------------------------%
 
diff --git a/compiler/options.m b/compiler/options.m
index 7eb8887..f56d3c1 100644
--- a/compiler/options.m
+++ b/compiler/options.m
@@ -1308,7 +1308,7 @@ option_defaults_2(compilation_model_option, [
     put_nondet_env_on_heap              -   bool(no),
 
     % Java back-end compilation model options
-    java_export_ref_out                 -   bool(no),
+    java_export_ref_out                 -   bool(yes),
 
     % IL back-end compilation model options
     verifiable_code                     -   bool(no),
diff --git a/doc/reference_manual.texi b/doc/reference_manual.texi
index 0930414..1d3acd7 100644
--- a/doc/reference_manual.texi
+++ b/doc/reference_manual.texi
@@ -6999,9 +6999,11 @@ passed as the corresponding Java type.
 Mercury tuple types are passed as @samp{java.lang.Object[]} where
 the length of the array is the number of elements in the tuple.
 
-Mercury variables whose type is a type variable will be passed as
+Mercury variables whose types are universally quantified type variables
+will have generic types.
+Mercury variables which are existentially typed will be passed as
 @code{java.lang.Object}.
-Mercury array types are mapped to Java array types.
+
 Mercury variables whose type is a Mercury discriminated union type
 will be passed as a Java type whose type name is determined from
 the Mercury type name (ignoring any type parameters) followed by
@@ -7009,6 +7011,9 @@ an underscore and then the type arity,
 expressed as a decimal integer.
 The first character of the type name will have its case inverted,
 and the name may be mangled to satisfy Java lexical rules.
+Generics are used in the Java type for any type parameters.
+
+Mercury array types are mapped to Java array types.
 
 Java code generated by the Mercury compiler is placed in the @samp{jmercury}
 package.  Mercury module qualifiers are converted into a Java class name by
@@ -7030,27 +7035,14 @@ whose result has an input mode, then the Mercury function result is
 appended to the list of input parameters, so that the Mercury function
 result becomes the last parameter to the corresponding Java function.
 
-The handling of multiple output arguments depends on the option
- at samp{--java-export-ref-out}.  It is disabled by default, but in the
-future will become enabled by default.
-
- at noindent
-Without @samp{--java-export-ref-out}:
+Arguments of type @samp{io.state} or @samp{store.store(_)} are not
+passed or returned at all.
+(The reason for this is that these types represent mutable state,
+and in Java modifications to mutable state are done via side effects,
+rather than argument passing.)
 
-The result of the Java function will be a sequence comprised of
-the outputs of the Mercury procedure.  If the Mercury procedure's
-determinism indicates that it can fail, then its first output will
-be a @samp{boolean} success indicator, with a @samp{true} value
-denoting success and a @samp{false} value denoting failure. The
-remaining outputs will be the subsequence of the Mercury procedure's
-arguments and function result (if any) that have output modes.
- 
-If the sequence has length zero then the return type of the
-Java function is @samp{void}.
-If the sequence has length one then the return type of the
-Java function is the type of the item in question.
-Otherwise, the Java function will return an array of type
- at samp{java.lang.Object[]}.
+The handling of multiple output arguments depends on the option
+ at samp{--java-export-ref-out}.  It is enabled by default.
 
 @noindent
 With @samp{--java-export-ref-out}:
@@ -7075,21 +7067,35 @@ same way as multiple outputs for deterministic procedures, using the
 @samp{Ref} class.  On failure the values of the @samp{val} fields are
 undefined.
 
-Arguments of type @samp{io.state} or @samp{store.store(_)} are not
-passed or returned at all.
-(The reason for this is that these types represent mutable state,
-and in Java modifications to mutable state are done via side effects,
-rather than argument passing.)
+ at noindent
+With @samp{--no-java-export-ref-out}:
+
+The result of the Java function will be a sequence comprised of
+the outputs of the Mercury procedure.  If the Mercury procedure's
+determinism indicates that it can fail, then its first output will
+be a @samp{boolean} success indicator, with a @samp{true} value
+denoting success and a @samp{false} value denoting failure. The
+remaining outputs will be the subsequence of the Mercury procedure's
+arguments and function result (if any) that have output modes.
+
+If the sequence has length zero then the return type of the
+Java function is @samp{void}.
+If the sequence has length one then the return type of the
+Java function is the type of the item in question.
+Otherwise, the Java function will return an array of type
+ at samp{java.lang.Object[]}.
+ at c end description of --no-java-export-ref-out
 
 Mercury lists can be manipulated by Java code using the following methods,
 which are defined by the Mercury implementation.
 
 @example
-list.is_empty(list)     /* test if a list is empty */
-list.det_head(list)     /* get the head of a list */
-list.det_tail(list)     /* get the tail of a list */
-list.empty_list()       /* create an empty list */
-list.cons(head, tail)   /* construct a list with the given head and tail */
+boolean   list.is_empty(List_1<E> list)     // test if a list is empty
+E         list.det_head(List_1<E> list)     // get the head of a list
+List_1<E> list.det_tail(List_1<E> list)     // get the tail of a list
+List_1<E> list.empty_list()                 // create an empty list
+List_1<E> list.cons(E head, List_1<E> tail) // construct a list with
+                                            //  the given head and tail
 @end example
 
 @node Erlang data passing conventions
diff --git a/library/exception.m b/library/exception.m
index 47746bd..c0cdb4f 100644
--- a/library/exception.m
+++ b/library/exception.m
@@ -1653,31 +1653,28 @@ call_handler(Handler, Exception, Result) :- Handler(Exception, Result).
     [will_not_call_mercury, promise_pure],
 "
     try {
-        T = exception.ML_call_goal_det(
-            TypeInfo_for_T,
-            (Object[]) Pred);
+        T = exception.ML_call_goal_det(TypeInfo_for_T, (Object[]) Pred);
     }
     catch (jmercury.runtime.Exception ex) {
-        T = exception.ML_call_handler_det(
-            TypeInfo_for_T,
-            (Object[]) Handler,
+        T = exception.ML_call_handler_det(TypeInfo_for_T, (Object[]) Handler,
             (univ.Univ_0) ex.exception);
     }
 ").
 :- pragma foreign_proc("Java",
     catch_impl(Pred::pred(out) is semidet, Handler::in(handler), T::out),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, may_not_duplicate],
 "
     try {
-        T = exception.ML_call_goal_semidet(
-            TypeInfo_for_T,
-            (Object[]) Pred);
+        jmercury.runtime.Ref<Object> ref =
+            new jmercury.runtime.Ref<Object>();
+        succeeded = exception.ML_call_goal_semidet(TypeInfo_for_T,
+            (Object[]) Pred, ref);
+        T = ref.val;
     }
     catch (jmercury.runtime.Exception ex) {
-        T = exception.ML_call_handler_det(
-            TypeInfo_for_T,
-            (Object[]) Handler,
+        T = exception.ML_call_handler_det(TypeInfo_for_T, (Object[]) Handler,
             (univ.Univ_0) ex.exception);
+        succeeded = true;
     }
 ").
 :- pragma foreign_proc("Java",
@@ -1685,14 +1682,10 @@ call_handler(Handler, Exception, Result) :- Handler(Exception, Result).
     [will_not_call_mercury, promise_pure],
 "
     try {
-        T = exception.ML_call_goal_det(
-            (jmercury.runtime.TypeInfo_Struct) TypeInfo_for_T,
-            (Object[]) Pred);
+        T = exception.ML_call_goal_det(TypeInfo_for_T, (Object[]) Pred);
     }
     catch (jmercury.runtime.Exception ex) {
-        T = exception.ML_call_handler_det(
-            (jmercury.runtime.TypeInfo_Struct) TypeInfo_for_T,
-            (Object[]) Handler,
+        T = exception.ML_call_handler_det(TypeInfo_for_T, (Object[]) Handler,
             (univ.Univ_0) ex.exception);
     }
 ").
diff --git a/library/io.m b/library/io.m
index a801fcc..a1f5f09 100644
--- a/library/io.m
+++ b/library/io.m
@@ -1804,8 +1804,8 @@
 
 :- pragma foreign_code("Java",
 "
-    static tree234.Tree234_2 ML_io_stream_db =
-        new tree234.Tree234_2.Empty_0();
+    static tree234.Tree234_2<Integer, Stream_info_0> ML_io_stream_db
+        = new tree234.Tree234_2.Empty_0<Integer, Stream_info_0>();
     static univ.Univ_0 ML_io_user_globals = null;
 ").
 
diff --git a/library/list.m b/library/list.m
index 37cf682..4bee1a0 100644
--- a/library/list.m
+++ b/library/list.m
@@ -2819,29 +2819,34 @@ list_to_doc_2([X | Xs]) = Doc :-
 ** the interfaces would expect type_info arguments.
 */
 
-public static List_1 empty_list()
+public static <E>
+List_1<E> empty_list()
 {
-    return new List_1.F_nil_0();
+    return new List_1.F_nil_0<E>();
 }
 
-public static List_1 cons(Object H, List_1 T)
+public static <E>
+List_1<E> cons(E head, List_1<E> tail)
 {
-    return new List_1.F_cons_2(H, T);
+    return new List_1.F_cons_2<E>(head, tail);
 }
 
-public static boolean is_empty(List_1 lst)
+public static <E>
+boolean is_empty(List_1<E> lst)
 {
     return (lst instanceof List_1.F_nil_0);
 }
 
-public static Object det_head(List_1 lst)
+public static <E>
+E det_head(List_1<E> lst)
 {
-    return ((List_1.F_cons_2) lst).F1;
+    return ((List_1.F_cons_2<E>) lst).F1;
 }
 
-public static List_1 det_tail(List_1 lst)
+public static <E>
+List_1<E> det_tail(List_1<E> lst)
 {
-    return ((List_1.F_cons_2) lst).F2;
+    return ((List_1.F_cons_2<E>) lst).F2;
 }
 
 /*
@@ -2852,9 +2857,9 @@ public static List_1 det_tail(List_1 lst)
 public static class ListIterator<E>
     implements java.lang.Iterable<E>, java.util.Iterator<E>
 {
-    private List_1 lst;
+    private List_1<E> lst;
 
-    public ListIterator(List_1 lst)
+    public ListIterator(List_1<E> lst)
     {
         this.lst = lst;
     }
@@ -2872,7 +2877,7 @@ public static class ListIterator<E>
     public E next()
     {
         if (!is_empty(lst)) {
-            E head = (E) det_head(lst);
+            E head = det_head(lst);
             lst = det_tail(lst);
             return head;
         } else {
diff --git a/library/rtti_implementation.m b/library/rtti_implementation.m
index 748a547..d5e16b0 100644
--- a/library/rtti_implementation.m
+++ b/library/rtti_implementation.m
@@ -202,6 +202,7 @@
     import jmercury.runtime.DuFunctorDesc;
     import jmercury.runtime.EnumFunctorDesc;
     import jmercury.runtime.PseudoTypeInfo;
+    import jmercury.runtime.Ref;
     import jmercury.runtime.TypeCtorInfo_Struct;
     import jmercury.runtime.TypeInfo_Struct;
 ").
@@ -441,9 +442,9 @@ create_pseudo_type_info(TypeInfo, PseudoTypeInfo) = ArgPseudoTypeInfo :-
 "
     PseudoTypeInfo[] as = new PseudoTypeInfo[Arity];
     int i = 0;
-    list.List_1 lst = Args;
+    list.List_1<PseudoTypeInfo> lst = Args;
     while (!list.is_empty(lst)) {
-        as[i] = (PseudoTypeInfo) list.det_head(lst);
+        as[i] = list.det_head(lst);
         lst = list.det_tail(lst);
         i++;
     }
@@ -1263,7 +1264,7 @@ iterate(Start, Max, Func) = Results :-
             TypeInfo_Struct ti = (TypeInfo_Struct) PseudoTypeInfo;
             TypeCtorInfo = ti.type_ctor;
 
-            list.List_1 lst = list.empty_list();
+            list.List_1<PseudoTypeInfo> lst = list.empty_list();
             if (ti.args != null) {
                 for (int i = ti.args.length - 1; i >= 0; i--) {
                     lst = list.cons(ti.args[i], lst);
@@ -1311,10 +1312,8 @@ is_exist_pseudo_type_info(_, _) :-
 :- pragma foreign_code("Java", "
 
     private static Object[]
-    ML_construct(
-        jmercury.runtime.TypeInfo_Struct TypeInfo,
-        int FunctorNumber,
-        list.List_1 ArgList)
+    ML_construct(TypeInfo_Struct TypeInfo, int FunctorNumber,
+        list.List_1<univ.Univ_0> ArgList)
     {
         /* If type_info is an equivalence type, expand it. */
         TypeInfo = ML_collapse_equivalences(TypeInfo);
@@ -1537,7 +1536,7 @@ is_exist_pseudo_type_info(_, _) :-
 
     private static Object
     ML_construct_du(TypeCtorInfo_Struct tc, DuFunctorDesc functor_desc,
-            list.List_1 arg_list)
+            list.List_1<univ.Univ_0> arg_list)
         throws ClassNotFoundException, NoSuchFieldException,
             IllegalAccessException, InstantiationException,
             InvocationTargetException
@@ -1585,13 +1584,15 @@ is_exist_pseudo_type_info(_, _) :-
     }
 
     private static Object[]
-    ML_univ_list_to_array(list.List_1 lst, int arity)
+    ML_univ_list_to_array(list.List_1<univ.Univ_0> lst, int arity)
     {
         final Object[] args = new Object[arity];
+        final Ref<TypeInfo_Struct> ti_ref = new Ref<TypeInfo_Struct>();
+        final Ref<Object> obj_ref = new Ref<Object>();
 
         for (int i = 0; i < arity; i++) {
-            univ.Univ_0 head = (univ.Univ_0) list.det_head(lst);
-            args[i] = univ.ML_unravel_univ(head)[1];
+            univ.ML_unravel_univ(ti_ref, list.det_head(lst), obj_ref);
+            args[i] = obj_ref.val;
             lst = list.det_tail(lst);
         }
 
@@ -1705,12 +1706,14 @@ construct(_, _, _) = _ :-
     [will_not_call_mercury, promise_pure, thread_safe,
         may_not_duplicate],
 "
-    list.List_1 args_list = Args;
+    list.List_1<univ.Univ_0> args_list = Args;
     Object[] args_array = new Object[Arity];
+    Ref<TypeInfo_Struct> ti_ref = new Ref<TypeInfo_Struct>();
+    Ref<Object> obj_ref = new Ref<Object>();
 
     for (int i = 0; i < Arity; i++) {
-        univ.Univ_0 head = (univ.Univ_0) list.det_head(args_list);
-        args_array[i] = univ.ML_unravel_univ(head)[1];
+        univ.ML_unravel_univ(ti_ref, list.det_head(args_list), obj_ref);
+        args_array[i] = obj_ref.val;
         args_list = list.det_tail(args_list);
     }
 
diff --git a/library/string.m b/library/string.m
index e109f55..5fabd52 100644
--- a/library/string.m
+++ b/library/string.m
@@ -1363,7 +1363,7 @@ string.to_char_list(Str::uo, CharList::in) :-
     [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
         does_not_affect_liveness, no_sharing],
 "
-    list.List_1 lst = list.empty_list();
+    list.List_1<Character> lst = list.empty_list();
     for (int i = Str.length() - 1; i >= 0; i--) {
         char c = Str.charAt(i);
         lst = list.cons(c, lst);
diff --git a/library/type_desc.m b/library/type_desc.m
index c2303e3..4184f7f 100644
--- a/library/type_desc.m
+++ b/library/type_desc.m
@@ -911,13 +911,13 @@ make_type_ctor_desc_with_arity(_, _, _) :-
     PseudoTypeInfo[] as = new PseudoTypeInfo[TypeCtorDesc.arity];
 
     succeeded = true;
-    list.List_1 arg_types = ArgTypes;
+    list.List_1<TypeInfo_Struct> arg_types = ArgTypes;
     for (int i = 0; i < TypeCtorDesc.arity; i++) {
         if (list.is_empty(arg_types)) {
             succeeded = false;
             break;
         }
-        as[i] = (TypeInfo_Struct) list.det_head(arg_types);
+        as[i] = list.det_head(arg_types);
         arg_types = list.det_tail(arg_types);
     }
 
diff --git a/tests/hard_coded/exceptions/Mmakefile b/tests/hard_coded/exceptions/Mmakefile
index 34982f3..cf94720 100644
--- a/tests/hard_coded/exceptions/Mmakefile
+++ b/tests/hard_coded/exceptions/Mmakefile
@@ -35,9 +35,8 @@ EXCEPTION_PROGS = \
 
 # Deep profiling grades cannot yet handle catching exceptions, either
 # explicitly or implicitly by the runtime system.
-# We currently don't do any testing in grade java on this directory.
 
-ifneq "$(findstring profdeep,$(GRADE))$(findstring java,$(GRADE))" ""
+ifneq "$(findstring profdeep,$(GRADE))" ""
 	PROGS=
 else
 	PROGS=$(EXCEPTION_PROGS)

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