[m-rev.] for review: implement equals method for Mercury enumerations

Ian MacLarty maclarty at csse.unimelb.edu.au
Tue Sep 22 16:12:53 AEST 2009


For review by Peter.

Estimated hours taken: 2
Branches: main

Override Object#equals for Mercury enumerations in the Java grades
and document that this should be used for equality testing in Java
code.  The problem with using == is that instances might not have
the same addresses if they are serialized and then deserialized.

MercuryEnum is now a class and not an interface.

compiler/ml_type_gen.m:
    Inherit the MercuryEnum class in Mercury enumerations
    instead of implementing the MercuryEnum interface.

compiler/mlds_to_java.m:
    Don't output the MR_value member in Java classes that correspond to
    Mercury enumerations.  This member is now inherited from MercuryEnum.

    Don't mangle classes in the Mercury runtime.

doc/reference_manual.texi:
    Document that the equals method should be used for exported
    Mercury enumerations.

java/runtime/MercuryEnum.java:
    Make MercuryEnum a class and implement the equals method.

Index: compiler/ml_type_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_type_gen.m,v
retrieving revision 1.87
diff -u -r1.87 ml_type_gen.m
--- compiler/ml_type_gen.m	4 Sep 2009 02:27:52 -0000	1.87
+++ compiler/ml_type_gen.m	22 Sep 2009 05:52:34 -0000
@@ -224,6 +224,9 @@
     % generator can treat it specially if need be (e.g. generating
     % a C enum rather than a class).
     %
+    % Note that for Java the MR_value field is inherited from the
+    % MercuryEnum class.
+    %
 :- pred ml_gen_enum_type(compilation_target::in, type_ctor::in,
     hlds_type_defn::in, list(constructor)::in, cons_tag_values::in,
     list(mlds_defn)::in, list(mlds_defn)::in, list(mlds_defn)::out) is det.
@@ -245,21 +248,21 @@
     Members = MaybeEqualityMembers ++
         [ValueMember | EnumConstMembers],
 
-    % Enums don't import or inherit anything.
+    % Enums don't import anything.
     Imports = [],
-    Inherits = [],
 
     % Make all Java classes corresponding to types implement the MercuryType
-    % and MercuryEnum interfaces.
+    % 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),
-        EnumInterface = qual(InterfaceModuleName, module_qual, "MercuryEnum"),
-        EnumInterfaceDefn = mlds_class_type(EnumInterface, 0, mlds_interface),
-        Implements = [TypeInterfaceDefn, EnumInterfaceDefn]
+        EnumClass = qual(InterfaceModuleName, module_qual, "MercuryEnum"),
+        EnumClassDefn = mlds_class_type(EnumClass, 0, mlds_class),
+        Implements = [TypeInterfaceDefn],
+        Inherits = [EnumClassDefn]
     ;
         ( Target = target_c
         ; Target = target_il
@@ -267,7 +270,8 @@
         ; Target = target_x86_64
         ; Target = target_erlang
         ),
-        Implements = []
+        Implements = [],
+        Inherits = []
     ),
 
     % Put it all together.
Index: compiler/mlds_to_java.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_java.m,v
retrieving revision 1.141
diff -u -r1.141 mlds_to_java.m
--- compiler/mlds_to_java.m	21 Sep 2009 04:08:57 -0000	1.141
+++ compiler/mlds_to_java.m	22 Sep 2009 05:52:36 -0000
@@ -99,6 +99,7 @@
 :- import_module ml_backend.ml_global_data.
 :- import_module ml_backend.ml_type_gen.   % for ml_gen_type_name
 :- import_module ml_backend.ml_util.
+:- import_module ml_backend.mlds.
 :- import_module ml_backend.rtti_to_mlds.
 :- import_module parse_tree.builtin_lib_types.
 :- import_module parse_tree.file_names.    % for mercury_std_library_name.
@@ -231,7 +232,6 @@
     %
 :- pred interface_is_special(string::in) is semidet.
 
-interface_is_special("MercuryEnum").
 interface_is_special("MercuryType").
 interface_is_special("MethodPtr").
 interface_is_special("MethodPtr1").
@@ -2015,8 +2015,7 @@
     Name = qual(ModuleName, _QualKind, UnqualName),
     output_enum_constants(Indent + 1, ModuleInfo, ModuleName, UnqualName,
         EnumConsts, !IO),
-    indent_line(Indent + 1, !IO),
-    io.write_string("public final int MR_value;\n\n", !IO),
+    io.nl(!IO),
     output_enum_ctor(Indent + 1, UnqualName, !IO).
 
 %-----------------------------------------------------------------------------%
@@ -2045,12 +2044,8 @@
     output_name(UnqualName, !IO),
     io.write_string("(int val) {\n", !IO),
     indent_line(Indent + 1, !IO),
-
-    % The use of `MR_value' is hardcoded into ml_type_gen.m. Any changes there
-    % should probably be reflected here.
-    io.write_string("this.MR_value = val;\n", !IO),
-    indent_line(Indent + 1, !IO),
-    io.write_string("return;\n", !IO),
+    % Call the MercuryEnum constructor, which will set the MR_value field.
+    io.write_string("super(val);\n", !IO),
     indent_line(Indent, !IO),
     io.write_string("}\n", !IO).
 
@@ -2795,10 +2790,20 @@
         unexpected(this_file, "output_type: erlang foreign_type")
     ).
 output_type(_, mlds_class_type(Name, Arity, _ClassKind), !IO) :-
-    % We used to treat enumerations specially here, outputting
-    % them as "int", but now we do the same for all classes.
-    output_fully_qualified_thing(Name, output_class_name, !IO),
-    io.format("_%d", [i(Arity)], !IO).
+    (
+        Name = qual(ModuleName, _, ClassName),
+        SymName = mlds_module_name_to_sym_name(ModuleName),
+        qualified(unqualified("jmercury"), "runtime") = SymName
+    ->
+        % Don't mangle runtime class names.
+        io.write_string("jmercury.runtime.", !IO),
+        io.write_string(ClassName, !IO)
+    ;
+        % We used to treat enumerations specially here, outputting
+        % them as "int", but now we do the same for all classes.
+        output_fully_qualified_thing(Name, output_class_name, !IO),
+        io.format("_%d", [i(Arity)], !IO)
+    ).
 output_type(Style, mlds_ptr_type(Type), !IO) :-
     % XXX should we report an error here, if the type pointed to
     % is not a class type?
Index: doc/reference_manual.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/reference_manual.texi,v
retrieving revision 1.432
diff -u -r1.432 reference_manual.texi
--- doc/reference_manual.texi	12 Aug 2009 01:56:25 -0000	1.432
+++ doc/reference_manual.texi	22 Sep 2009 05:52:40 -0000
@@ -8143,6 +8143,9 @@
 These identifiers are used as the names of static class members
 which are assigned instances of the enumeration class.
 
+The @samp{equals} method should be used for equality testing of enumeration
+values in Java code.
+
 The default mapping used by @samp{pragma foreign_export_enum}
 declarations for Java is to use the Mercury constructor name as the
 base of the symbolic name.  For example, the symbolic name for
Index: java/runtime/MercuryEnum.java
===================================================================
RCS file: /home/mercury1/repository/mercury/java/runtime/MercuryEnum.java,v
retrieving revision 1.1
diff -u -r1.1 MercuryEnum.java
--- java/runtime/MercuryEnum.java	9 Jul 2009 05:18:08 -0000	1.1
+++ java/runtime/MercuryEnum.java	22 Sep 2009 05:52:41 -0000
@@ -3,11 +3,21 @@
 // This file may only be copied under the terms of the GNU Library General
 // Public License - see the file COPYING.LIB in the Mercury distribution.
 //
-// This interface is implemented by all classes generated by the Java back-end
+// This is the superclass of all classes generated by the Java back-end
 // which correspond to Mercury-defined enumeration types.
 //
 
 package jmercury.runtime;
 
-public interface MercuryEnum {
+public abstract class MercuryEnum {
+    public final int MR_value;
+
+    protected MercuryEnum(int val) {
+        MR_value = val;
+    }
+
+    @Override 
+    public boolean equals(Object o) {
+        return ((MercuryEnum)o).MR_value == this.MR_value;
+    }
 }
--------------------------------------------------------------------------
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