Files
mercury/compiler/java_names.m
Zoltan Somogyi fa5eee77c5 Specialize qual/3 for each type it was applied to.
The MLDS either module- or type-qualifies several kinds of entities.
It used to use the same qual/3 wrapper for all these entities. However,
many kinds of entities are never (and can never be) type-qualified,
because they are not defined inside a type.

This diff replaces the mlds_fully_qualified_name type, and its qual/3 wrapper,
with a separate type and a separate wrapper for each kind of entity.
For those entities that can be both module- and type-qualified, have this
wrapper continue to include a mlds_qual_kind (module_qual or type_qual) field;
for the entities that are only ever module qualified, omit this field.

compiler/mlds.m:
    Make the change described above.

    There are some related changes.

    The first is that the argument of the ml_field_named rval specifying
    the field used to be a string. Change this to be a field_var_name,
    because if a field's name is given by a field_var_name in its definition,
    it should be given by that same field_var_name in its uses as well.
    Without this, it is unnecessarily hard to ensure that the code that
    generates the target language versions of the field's name match
    in definitions and uses; specification, it would be unnecessarily hard
    to ensure that they do module- or type-qualification the same way.

    The second is required by the first. We used to use "ptr_num"
    as the name of only a compiler-generated local variable, but it is
    actually the name of a field in a compiler-generated class, and the
    local variable use actually refers to the field. Therefore this diff
    moves the reference to this from the mlds_local_var_name type
    to the mlds_field_var_name type.

    The third is switching to a more consistent naming scheme:
    having the unqualified name of entities of kind xxx be mlds_xxx_name
    and the qualified version of those names being qual_xxx_name.

compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_code_util.m:
compiler/ml_elim_nested.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_global_data.m:
compiler/ml_optimize.m:
compiler/ml_proc_gen.m:
compiler/ml_tailcall.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
compiler/rtti_to_mlds.m:
    Conform to the changes above.

compiler/java_names.m:
    Clarify a variable name.
2017-07-22 22:48:30 +02:00

369 lines
12 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2002-2011 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
%
% File: java_names.m.
% Main authors: juliensf, mjwybrow, wangp.
%
% This module contains utility routines related to naming things in Java/C#
% which are also required in the frontend.
%
%-----------------------------------------------------------------------------%
:- module parse_tree.java_names.
:- interface.
:- import_module mdbcomp.sym_name.
%-----------------------------------------------------------------------------%
% For the C# and Java back-ends, we need to distinguish between module
% qualifiers and type qualifiers, because type names get the case of their
% initial letter inverted (i.e. lowercase => uppercase).
%
% This duplicates mlds_qual_kind so as not to introduce unwanted
% dependencies in either direction.
%
:- type csj_qual_kind
---> module_qual
; type_qual.
% Mangle a name so that it is suitable for Java.
%
:- pred mangle_sym_name_for_java(sym_name::in, csj_qual_kind::in,
string::in, string::out) is det.
% If the given name conflicts with a reserved Java word,
% add a prefix to it to avoid compilation errors.
%
:- func make_valid_java_symbol_name(string) = string.
% Succeeds iff the given string matches a reserved word in Java.
%
:- pred is_java_keyword(string::in) is semidet.
% The package containing the Mercury Java runtime classes.
%
:- func java_mercury_runtime_package_name = sym_name.
%-----------------------------------------------------------------------------%
% Mangle a name so that it is suitable for C#.
%
:- pred mangle_sym_name_for_csharp(sym_name::in, csj_qual_kind::in,
string::in, string::out) is det.
% If the given name conflicts with a reserved C# word,
% add a prefix to it to avoid compilation errors.
%
:- func make_valid_csharp_symbol_name(string) = string.
% Succeeds iff the given string matches a reserved word in C#.
%
:- pred is_csharp_keyword(string::in) is semidet.
% The package containing the Mercury C# runtime classes.
%
:- func csharp_mercury_runtime_package_name = sym_name.
%-----------------------------------------------------------------------------%
% Invert the case of the first letter of the string.
%
:- func flip_initial_case(string) = string.
% Invert the case of the first letter of the last component of
% a (possibly) qualified name.
%
:- func flip_initial_case_of_final_part(sym_name) = sym_name.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module parse_tree.prog_foreign. % for name_mangle
:- import_module char.
:- import_module string.
%-----------------------------------------------------------------------------%
%
% Java naming.
%
mangle_sym_name_for_java(SymName0, QualKind, QualifierOp, JavaSafeName) :-
% Modules in the Mercury standard library get a `mercury' prefix when
% mapped to MLDS module names. Since we place all Java classes inside a
% `jmercury' package, the extra prefix is just redundant so we remove it.
( if strip_outermost_qualifier(SymName0, "mercury", StrippedSymName) then
SymName = StrippedSymName
else
SymName = SymName0
),
mangle_sym_name_for_java_2(SymName, QualKind, MangledSymName),
JavaSafeName = sym_name_to_string_sep(MangledSymName, QualifierOp).
:- pred mangle_sym_name_for_java_2(sym_name::in, csj_qual_kind::in,
sym_name::out) is det.
mangle_sym_name_for_java_2(SymName, QualKind, MangledSymName) :-
(
SymName = unqualified(Name),
JavaSafeName = java_safe_name_component(QualKind, Name),
MangledSymName = unqualified(JavaSafeName)
;
SymName = qualified(ModuleName0, PlainName),
mangle_sym_name_for_java_2(ModuleName0, module_qual,
MangledModuleName),
JavaSafePlainName = java_safe_name_component(QualKind, PlainName),
MangledSymName = qualified(MangledModuleName, JavaSafePlainName)
).
:- func java_safe_name_component(csj_qual_kind, string) = string.
java_safe_name_component(QualKind, Name) = JavaSafeName :-
MangledName = name_mangle_no_leading_digit(Name),
(
QualKind = module_qual,
MaybeFlippedName = MangledName
;
QualKind = type_qual,
MaybeFlippedName = flip_initial_case(MangledName)
),
JavaSafeName = make_valid_java_symbol_name(MaybeFlippedName).
make_valid_java_symbol_name(SymName) = ValidSymName :-
Prefix = "mr_",
( if is_java_keyword(SymName) then
% This is a reserved Java word, add the above prefix.
ValidSymName = Prefix ++ SymName
else if string.append(Prefix, Suffix, SymName) then
% This name already contains the prefix we are adding to
% variables to avoid conflicts, so add an additional '_'.
ValidSymName = Prefix ++ "_" ++ Suffix
else
% Normal name; do nothing.
ValidSymName = SymName
).
is_java_keyword("abstract").
is_java_keyword("boolean").
is_java_keyword("break").
is_java_keyword("byte").
is_java_keyword("case").
is_java_keyword("catch").
is_java_keyword("char").
is_java_keyword("class").
is_java_keyword("const").
is_java_keyword("continue").
is_java_keyword("default").
is_java_keyword("do").
is_java_keyword("double").
is_java_keyword("else").
is_java_keyword("enum").
is_java_keyword("extends").
is_java_keyword("false").
is_java_keyword("final").
is_java_keyword("finally").
is_java_keyword("float").
is_java_keyword("for").
is_java_keyword("goto").
is_java_keyword("if").
is_java_keyword("implements").
is_java_keyword("import").
is_java_keyword("instanceof").
is_java_keyword("int").
is_java_keyword("interface").
is_java_keyword("long").
is_java_keyword("native").
is_java_keyword("new").
is_java_keyword("null").
is_java_keyword("package").
is_java_keyword("private").
is_java_keyword("protected").
is_java_keyword("public").
is_java_keyword("return").
is_java_keyword("short").
is_java_keyword("static").
is_java_keyword("strictfp").
is_java_keyword("super").
is_java_keyword("switch").
is_java_keyword("synchronized").
is_java_keyword("this").
is_java_keyword("throw").
is_java_keyword("throws").
is_java_keyword("transient").
is_java_keyword("true").
is_java_keyword("try").
is_java_keyword("void").
is_java_keyword("volatile").
is_java_keyword("while").
java_mercury_runtime_package_name =
qualified(unqualified("jmercury"), "runtime").
%-----------------------------------------------------------------------------%
%
% C# naming.
%
% XXX Reduce code duplication between C# and Java routines.
mangle_sym_name_for_csharp(SymName, QualKind, QualifierOp, SafeName) :-
mangle_sym_name_for_csharp_2(SymName, QualKind, MangledSymName),
SafeName = sym_name_to_string_sep(MangledSymName, QualifierOp).
:- pred mangle_sym_name_for_csharp_2(sym_name::in, csj_qual_kind::in,
sym_name::out) is det.
mangle_sym_name_for_csharp_2(SymName, QualKind, MangledSymName) :-
(
SymName = unqualified(Name),
SafeName = csharp_safe_name_component(QualKind, Name),
MangledSymName = unqualified(SafeName)
;
SymName = qualified(ModuleName0, PlainName),
mangle_sym_name_for_csharp_2(ModuleName0, module_qual,
MangledModuleName),
SafePlainName = csharp_safe_name_component(QualKind, PlainName),
MangledSymName = qualified(MangledModuleName, SafePlainName)
).
:- func csharp_safe_name_component(csj_qual_kind, string) = string.
csharp_safe_name_component(QualKind, Name) = SafeName :-
MangledName = name_mangle_no_leading_digit(Name),
(
QualKind = module_qual,
FlippedName = MangledName
;
QualKind = type_qual,
FlippedName = flip_initial_case(MangledName)
),
SafeName = make_valid_csharp_symbol_name(FlippedName).
make_valid_csharp_symbol_name(SymName) = ValidSymName :-
Prefix = "mr_",
( if is_csharp_keyword(SymName) then
% This is a reserved word, add the above prefix.
ValidSymName = Prefix ++ SymName
else if string.append(Prefix, Suffix, SymName) then
% This name already contains the prefix we are adding to
% variables to avoid conflicts, so add an additional '_'.
ValidSymName = Prefix ++ "_" ++ Suffix
else
% Normal name; do nothing.
ValidSymName = SymName
).
is_csharp_keyword("abstract").
is_csharp_keyword("as").
is_csharp_keyword("base").
is_csharp_keyword("bool").
is_csharp_keyword("break").
is_csharp_keyword("byte").
is_csharp_keyword("case").
is_csharp_keyword("catch").
is_csharp_keyword("char").
is_csharp_keyword("checked").
is_csharp_keyword("class").
is_csharp_keyword("const").
is_csharp_keyword("continue").
is_csharp_keyword("decimal").
is_csharp_keyword("default").
is_csharp_keyword("delegate").
is_csharp_keyword("do").
is_csharp_keyword("double").
is_csharp_keyword("else").
is_csharp_keyword("enum").
is_csharp_keyword("event").
is_csharp_keyword("explicit").
is_csharp_keyword("extern").
is_csharp_keyword("false").
is_csharp_keyword("finally").
is_csharp_keyword("fixed").
is_csharp_keyword("float").
is_csharp_keyword("for").
is_csharp_keyword("foreach").
is_csharp_keyword("goto").
is_csharp_keyword("if").
is_csharp_keyword("implicit").
is_csharp_keyword("in").
is_csharp_keyword("int").
is_csharp_keyword("interface").
is_csharp_keyword("internal").
is_csharp_keyword("is").
is_csharp_keyword("lock").
is_csharp_keyword("long").
is_csharp_keyword("namespace").
is_csharp_keyword("new").
is_csharp_keyword("null").
is_csharp_keyword("object").
is_csharp_keyword("operator").
is_csharp_keyword("out").
is_csharp_keyword("override").
is_csharp_keyword("params").
is_csharp_keyword("private").
is_csharp_keyword("protected").
is_csharp_keyword("public").
is_csharp_keyword("readonly").
is_csharp_keyword("ref").
is_csharp_keyword("return").
is_csharp_keyword("sbyte").
is_csharp_keyword("sealed").
is_csharp_keyword("short").
is_csharp_keyword("sizeof").
is_csharp_keyword("stackalloc").
is_csharp_keyword("static").
is_csharp_keyword("string").
is_csharp_keyword("struct").
is_csharp_keyword("switch").
is_csharp_keyword("this").
is_csharp_keyword("throw").
is_csharp_keyword("true").
is_csharp_keyword("try").
is_csharp_keyword("typeof").
is_csharp_keyword("uint").
is_csharp_keyword("ulong").
is_csharp_keyword("unchecked").
is_csharp_keyword("unsafe").
is_csharp_keyword("ushort").
is_csharp_keyword("using").
is_csharp_keyword("virtual").
is_csharp_keyword("volatile").
is_csharp_keyword("void").
is_csharp_keyword("while").
csharp_mercury_runtime_package_name =
qualified(unqualified("mercury"), "runtime").
%-----------------------------------------------------------------------------%
flip_initial_case(S0) = S :-
( if string.first_char(S0, First0, Rest) then
( if char.is_upper(First0) then
First = char.to_lower(First0)
else if char.is_lower(First0) then
First = char.to_upper(First0)
else
First = First0
),
string.first_char(S, First, Rest)
else
S = S0
).
flip_initial_case_of_final_part(unqualified(Name)) =
unqualified(flip_initial_case(Name)).
flip_initial_case_of_final_part(qualified(Qual, Name)) =
qualified(Qual, flip_initial_case(Name)).
%-----------------------------------------------------------------------------%
:- end_module parse_tree.java_names.
%-----------------------------------------------------------------------------%