mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-19 07:45:09 +00:00
compiler/mlds.m:
Replace the old definition of mlds_var_name, which was a string
with an optional integer. The integer was intended to be the number
of a HLDS variable, while auxiliary variables created by the compiler,
which do not correspond to a HLDS variable, would not have the optional
integer.
This design has a couple of minor problems. The first is that there is
no place in the compiler where all the variable names are visible at once,
and without such a place, we cannot be sure that two names constructed
for different purposes don't accidentally end up with the same name.
The probability of such a clash used to be astronomically small
(which is why this hasn't been a problem), but it was not zero.
The second problem is that several kinds of compiler-created MLDS variables
want to have numerical suffixes too, usually with the suffix being a
unique sequence number used as a means of disambiguation. Most of the
places where these were created put the numerical suffix into the name
string itself, while some put the sequence number as the optional integer.
As it happens, neither of those actions is good when one wants to take
the independently generated MLDS code of several procedures in an SCC
and merge them into a single piece of MLDS code. For this, we want to
rename apart both the HLDS variable numbers and the sequence numbers.
Having the sequence number baked into the strings themselves obviously
makes such renumbering unnecessarily hard, while having sequence numbers
in the slots intended for HLDS variable numbers makes the job impossible
to do safely.
This diff switches to a new representation of mlds_var_names that
has a separate function symbol for each different "origin story"
that is possible for MLDS variables. This addresses both problems.
The single predicate that converts this structured representation
to a string is the place where we can ensure that two semantically
different MLDS variables never get translated to the same string.
The current version of this predicate does *not* offer this guarantee,
but later versions could.
And having all the integers used in mlds_var_names for different purposes
stored as arguments of different function symbols (that clearly indicate
their meaning) makes it possible to rename apart different sets
of MLDS variables easily and reliably.
Move the code for converting mlds_var_names from ml_code_util.m to here,
to make it easier to maintain it together with the mlds_var_name type.
compiler/ml_code_util.m:
Conform to the above change by generating structured MLDS var names.
Delete a predicate that is not needed with structured var names.
Delete the code moved to mlds.m.
Delete a predicate that has been unused since we deleted the IL backend.
Add ml_make_boxed_type as a version of ml_make_boxed_types that returns
exactly one type. This simplifies some code elsewhere.
Add "hld" to some predicate names to make clear that they are intended
for use only with --high-level-data.
compiler/ml_type_gen.m:
Conform to the above change by generating structured MLDS var names.
Add "hld" to the names of the (many) predicates here that are used
only with --high-level-data to make clear that fact.
compiler/mlds_to_cs.m:
compiler/mlds_to_java.m:
Conform to the above change by generating structured MLDS var names.
Add a "for_csharp" or "for_java" suffix to some predicate names
to avoid ambiguities.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_commit_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_elim_nested.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_gen_info.m:
compiler/ml_global_data.m:
compiler/ml_lookup_switch.m:
compiler/ml_optimize.m:
compiler/ml_string_switch.m:
compiler/ml_unify_gen.m:
compiler/ml_util.m:
compiler/mlds_to_c.m:
Conform to the above change by generating structured MLDS var names.
compiler/prog_type.m:
Add var_to_type, as a version of var_list_to_type_list that returns
exactly one type. This simplifies some code elsewhere.
compiler/java_names.m:
Give some predicates and functions better names.
compiler/ml_code_gen.m:
Fix typo.
369 lines
12 KiB
Mathematica
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,
|
|
FlippedName = MangledName
|
|
;
|
|
QualKind = type_qual,
|
|
FlippedName = flip_initial_case(MangledName)
|
|
),
|
|
JavaSafeName = make_valid_java_symbol_name(FlippedName).
|
|
|
|
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.
|
|
%-----------------------------------------------------------------------------%
|