[m-rev.] for review: fix conflicting type/constructor names in java
Peter Wang
novalazy at gmail.com
Tue May 12 16:06:04 AEST 2009
Branches: main
Avoid a problem with type names and constructor names that are the same.
Java does not allow the name of a nested class to be the same as its
enclosing class. If we would violate that rule (when generating Java) then
add the prefix "mr_" to the constructor name. The user can still trigger the
problem by naming a different constructor with the "mr_" prefix.
compiler/ml_type_gen.m:
Add functions to generate constructor names that avoid the problem.
Use the functions for naming d.u. constructors.
compiler/ml_unify_gen.m:
Use the functions for naming d.u. constructors.
compiler/mlds_to_java.m:
Delete TODO.
diff --git a/compiler/ml_type_gen.m b/compiler/ml_type_gen.m
index 6686661..c906359 100644
--- a/compiler/ml_type_gen.m
+++ b/compiler/ml_type_gen.m
@@ -28,6 +28,8 @@
:- import_module hlds.hlds_data.
:- import_module hlds.hlds_module.
+:- import_module libs.globals.
+:- import_module mdbcomp.prim_data.
:- import_module ml_backend.mlds.
:- import_module parse_tree.prog_data.
@@ -46,6 +48,16 @@
%
:- pred ml_gen_type_name(type_ctor::in, mlds_class::out, arity::out) is det.
+ % Generate a data constructor name given the type constructor.
+ %
+:- func ml_gen_du_ctor_name(compilation_target, type_ctor, sym_name, int)
+ = string.
+
+ % As above but pass the unqualified type name directly.
+ %
+:- func ml_gen_du_ctor_name_unqual_type(compilation_target, string, int,
+ sym_name, int) = string.
+
% Return the declaration flags appropriate for a type.
%
:- func ml_gen_type_decl_flags = mlds_decl_flags.
@@ -92,9 +104,7 @@
:- import_module check_hlds.polymorphism.
:- import_module hlds.hlds_pred.
:- import_module libs.compiler_util.
-:- import_module libs.globals.
:- import_module libs.options.
-:- import_module mdbcomp.prim_data.
:- import_module ml_backend.ml_code_util.
:- import_module ml_backend.ml_util.
:- import_module parse_tree.prog_data.
@@ -109,6 +119,7 @@
:- import_module maybe.
:- import_module pair.
:- import_module set.
+:- import_module string.
:- import_module term.
%-----------------------------------------------------------------------------%
@@ -450,7 +461,7 @@ ml_gen_du_parent_type(ModuleInfo, TypeCtor,
TypeDefn, Ctors, TagValues,
% reserved_object representations, or fields and a constructor method
% for the single_functor case.
list.foldl2(ml_gen_du_ctor_member(ModuleInfo, BaseClassId,
- BaseClassQualifier, TagClassId, TypeDefn, TagValues),
+ BaseClassQualifier, TagClassId, TypeCtor, TypeDefn, TagValues),
Ctors, [], CtorMembers, [], BaseClassCtorMethods),
% The base class doesn't import or inherit anything.
@@ -600,13 +611,13 @@ ml_gen_secondary_tag_class(MLDS_Context,
BaseClassQualifier, BaseClassId,
% a constructor method.
%
:- pred ml_gen_du_ctor_member(module_info::in, mlds_class_id::in,
- mlds_module_name::in, mlds_class_id::in, hlds_type_defn::in,
+ mlds_module_name::in, mlds_class_id::in, type_ctor::in, hlds_type_defn::in,
cons_tag_values::in, constructor::in,
list(mlds_defn)::in, list(mlds_defn)::out,
list(mlds_defn)::in, list(mlds_defn)::out) is det.
ml_gen_du_ctor_member(ModuleInfo, BaseClassId, BaseClassQualifier,
- SecondaryTagClassId, TypeDefn, ConsTagValues, Ctor,
+ SecondaryTagClassId, TypeCtor, TypeDefn, ConsTagValues, Ctor,
MLDS_Members0, MLDS_Members, MLDS_CtorMethods0, MLDS_CtorMethods) :-
Ctor = ctor(ExistQTVars, Constraints, CtorName, Args, _Ctxt),
@@ -616,8 +627,11 @@ ml_gen_du_ctor_member(ModuleInfo, BaseClassId,
BaseClassQualifier,
MLDS_Context = mlds_make_context(Context),
% Generate the class name for this constructor.
- UnqualCtorName = unqualify_name(CtorName),
+ module_info_get_globals(ModuleInfo, Globals),
+ globals.get_target(Globals, Target),
list.length(Args, CtorArity),
+ UnqualCtorName = ml_gen_du_ctor_name(Target, TypeCtor,
+ CtorName, CtorArity),
TagVal = get_tagval(ConsTagValues, Ctor),
( tagval_is_reserved_addr(TagVal, ReservedAddr) ->
@@ -681,8 +695,6 @@ ml_gen_du_ctor_member(ModuleInfo, BaseClassId,
BaseClassQualifier,
% Generate a constructor function to initialize the fields, if needed
% (not all back-ends use constructor functions).
MaybeSecTagVal = get_secondary_tag(TagVal),
- module_info_get_globals(ModuleInfo, Globals),
- globals.get_target(Globals, Target),
UsesConstructors = target_uses_constructors(Target),
(
UsesConstructors = yes,
@@ -1004,6 +1016,29 @@ ml_gen_type_name(type_ctor(Name, Arity),
QualifiedTypeName, Arity) :-
MLDS_Module = mercury_module_name_to_mlds(ModuleName),
QualifiedTypeName = qual(MLDS_Module, module_qual, TypeName).
+ml_gen_du_ctor_name(CompilationTarget, TypeCtor, Name, Arity) = CtorName :-
+ TypeCtor = type_ctor(TypeName, TypeArity),
+ UnqualTypeName = unqualify_name(TypeName),
+ CtorName = ml_gen_du_ctor_name_unqual_type(CompilationTarget,
+ UnqualTypeName, TypeArity, Name, Arity).
+
+ml_gen_du_ctor_name_unqual_type(CompilationTarget, UnqualTypeName, TypeArity,
+ Name, Arity) = CtorName :-
+ UnqualName = unqualify_name(Name),
+ (
+ CompilationTarget = target_java,
+ UnqualName = UnqualTypeName,
+ Arity = TypeArity
+ ->
+ % In Java we must not generate a class with the same name as its
+ % enclosing class. We add the prefix to avoid that situation arising.
+ % (A user may name another functor of the same type with "mr_" to
+ % trigger the problem.)
+ CtorName = "mr_" ++ UnqualName
+ ;
+ CtorName = UnqualName
+ ).
+
% For interoperability, we ought to generate an `==' member for types
% which have a user-defined equality, if the target language supports it
% (as do e.g. C++, Java).
diff --git a/compiler/ml_unify_gen.m b/compiler/ml_unify_gen.m
index 4bf6a36..30f942b 100644
--- a/compiler/ml_unify_gen.m
+++ b/compiler/ml_unify_gen.m
@@ -297,7 +297,8 @@ ml_gen_construct_2(Tag, Type, Var, ConsId, Args,
ArgModes, TakeAddr,
; Tag = unshared_tag(_TagVal)
; Tag = shared_remote_tag(_PrimaryTag, _SecondaryTag)
),
- ml_gen_compound(Tag, ConsId, Var, Args, ArgModes, TakeAddr,
+ type_to_ctor_and_args_det(Type, TypeCtor, _),
+ ml_gen_compound(Tag, TypeCtor, ConsId, Var, Args, ArgModes, TakeAddr,
HowToConstruct, Context, Decls, Statements, !Info)
;
% Constants.
@@ -577,13 +578,13 @@ ml_cons_id_to_tag(Info, ConsId, Type, Tag) :-
% Generate code to construct a new object.
%
-:- pred ml_gen_compound(cons_tag::in, cons_id::in, prog_var::in, prog_vars::in,
- list(uni_mode)::in, list(int)::in, how_to_construct::in, prog_context::in,
- list(mlds_defn)::out, list(statement)::out,
+:- pred ml_gen_compound(cons_tag::in, type_ctor::in, cons_id::in, prog_var::in,
+ prog_vars::in, list(uni_mode)::in, list(int)::in, how_to_construct::in,
+ prog_context::in, list(mlds_defn)::out, list(statement)::out,
ml_gen_info::in, ml_gen_info::out) is det.
-ml_gen_compound(Tag, ConsId, Var, ArgVars, ArgModes, TakeAddr, HowToConstruct,
- Context, Decls, Statements, !Info) :-
+ml_gen_compound(Tag, TypeCtor, ConsId, Var, ArgVars, ArgModes, TakeAddr,
+ HowToConstruct, Context, Decls, Statements, !Info) :-
% Get the primary and secondary tags.
( get_primary_tag(Tag) = yes(PrimaryTag0) ->
PrimaryTag = PrimaryTag0
@@ -592,11 +593,15 @@ ml_gen_compound(Tag, ConsId, Var, ArgVars,
ArgModes, TakeAddr, HowToConstruct,
),
MaybeSecondaryTag = get_secondary_tag(Tag),
+ ml_gen_info_get_module_info(!.Info, ModuleInfo),
+ module_info_get_globals(ModuleInfo, Globals),
+
% Figure out which class name to construct.
( ml_tag_uses_base_class(Tag) ->
MaybeCtorName = no
;
- ml_cons_name(ConsId, CtorName),
+ globals.get_target(Globals, CompilationTarget),
+ ml_cons_name(CompilationTarget, TypeCtor, ConsId, CtorName),
MaybeCtorName = yes(CtorName)
),
@@ -610,8 +615,6 @@ ml_gen_compound(Tag, ConsId, Var, ArgVars,
ArgModes, TakeAddr, HowToConstruct,
% With the low-level data representation, all fields -- even the
% secondary tag -- are boxed, and so we need box it here.
- ml_gen_info_get_module_info(!.Info, ModuleInfo),
- module_info_get_globals(ModuleInfo, Globals),
globals.lookup_bool_option(Globals, highlevel_data, HighLevelData),
(
HighLevelData = no,
@@ -923,7 +926,10 @@ get_type_for_cons_id(MLDS_Type, UsesBaseClass,
MaybeConsId, HighLevelData,
% If so, append the name of the derived class to the name of the
% base class for this type (since the derived class will also be
% nested inside the base class).
- CtorName = unqualify_name(CtorSymName),
+ globals.get_target(Globals, CompilationTarget),
+ QualTypeName = qual(_, _, UnqualTypeName),
+ CtorName = ml_gen_du_ctor_name_unqual_type(CompilationTarget,
+ UnqualTypeName, TypeArity, CtorSymName, CtorArity),
QualTypeName = qual(MLDS_Module, _QualKind, TypeName),
ClassQualifier = mlds_append_class_qualifier(MLDS_Module,
module_qual, Globals, TypeName, TypeArity),
@@ -1235,14 +1241,17 @@ ml_gen_static_const_addr(Info, Var, Type,
ConstAddrRval) :-
ml_gen_var_lval(Info, ConstName, Type, ConstLval),
ConstAddrRval = mem_addr(ConstLval).
-:- pred ml_cons_name(cons_id::in, ctor_name::out) is det.
+:- pred ml_cons_name(compilation_target::in, type_ctor::in,
+ cons_id::in, ctor_name::out) is det.
-ml_cons_name(HLDS_ConsId, QualifiedConsId) :-
+ml_cons_name(CompilationTarget, TypeCtor, HLDS_ConsId, QualifiedConsId) :-
(
- HLDS_ConsId = cons(SymName, Arity),
- SymName = qualified(SymModuleName, ConsName)
+ HLDS_ConsId = cons(ConsSymName, ConsArity),
+ ConsSymName = qualified(SymModuleName, _)
->
- ConsId = ctor_id(ConsName, Arity),
+ ConsName = ml_gen_du_ctor_name(CompilationTarget, TypeCtor,
+ ConsSymName, ConsArity),
+ ConsId = ctor_id(ConsName, ConsArity),
ModuleName = mercury_module_name_to_mlds(SymModuleName)
;
ConsName = hlds_out.cons_id_to_string(HLDS_ConsId),
@@ -1668,7 +1677,10 @@ ml_gen_unify_arg(ConsId, Arg, Mode, ArgType,
Field, VarType, VarLval,
;
FieldName = ml_gen_field_name(MaybeFieldName, ArgNum),
( ConsId = cons(ConsName, ConsArity) ->
- UnqualConsName = unqualify_name(ConsName),
+ globals.get_target(Globals, CompilationTarget),
+ type_to_ctor_and_args_det(VarType, TypeCtor, _),
+ UnqualConsName = ml_gen_du_ctor_name(CompilationTarget,
+ TypeCtor, ConsName, ConsArity),
FieldId = ml_gen_field_id(VarType, Tag, UnqualConsName,
ConsArity, FieldName, Globals)
;
diff --git a/compiler/mlds_to_java.m b/compiler/mlds_to_java.m
index 9c26ea5..6ffdc54 100644
--- a/compiler/mlds_to_java.m
+++ b/compiler/mlds_to_java.m
@@ -29,10 +29,6 @@
% Support for Java in Mmake and mmc --make (except for nested modules)
%
% TODO:
-% - Fix problem with type names and constructor names that are the same
-% (Java does not allow the name of a nested class to be the same as its
-% enclosing class)
-%
% - Support nested modules
% (The problem with current code generation scheme for nested
% modules is that Java does not allow the name of a class to
--------------------------------------------------------------------------
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