[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