Files
mercury/compiler/mlds_to_java_name.m
Zoltan Somogyi 24078e6e75 Write to explicitly named streams in the MLDS backend.
compiler/mlds_to_c_class.m:
compiler/mlds_to_c_data.m:
compiler/mlds_to_c_export.m:
compiler/mlds_to_c_file.m:
compiler/mlds_to_c_func.m:
compiler/mlds_to_c_global.m:
compiler/mlds_to_c_name.m:
compiler/mlds_to_c_stmt.m:
compiler/mlds_to_c_type.m:
compiler/mlds_to_c_util.m:
compiler/mlds_to_cs_class.m:
compiler/mlds_to_cs_data.m:
compiler/mlds_to_cs_export.m:
compiler/mlds_to_cs_file.m:
compiler/mlds_to_cs_func.m:
compiler/mlds_to_cs_global.m:
compiler/mlds_to_cs_name.m:
compiler/mlds_to_cs_stmt.m:
compiler/mlds_to_cs_type.m:
compiler/mlds_to_cs_util.m:
compiler/mlds_to_java_class.m:
compiler/mlds_to_java_data.m:
compiler/mlds_to_java_export.m:
compiler/mlds_to_java_file.m:
compiler/mlds_to_java_func.m:
compiler/mlds_to_java_global.m:
compiler/mlds_to_java_name.m:
compiler/mlds_to_java_stmt.m:
compiler/mlds_to_java_type.m:
compiler/mlds_to_java_util.m:
compiler/mlds_to_target_util.m:
    As above.

compiler/Mercury.options:
    Specify --warn-impliciy-stream-calls for all the modules above.

compiler/file_util.m:
    Delete a utility predicate that expects its clients to operate on
    implicit streams, since the changes above replaced the last calls to it
    with the variant that expects its client to operate on explicit streams.
2020-11-17 11:20:43 +11:00

343 lines
13 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2000-2012 The University of Melbourne.
% Copyright (C) 2013-2018 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% Output the names of various entities.
%
% XXX Much of this code will not work when we start enforcing names properly.
%
%---------------------------------------------------------------------------%
:- module ml_backend.mlds_to_java_name.
:- interface.
:- import_module ml_backend.mlds.
:- import_module ml_backend.mlds_to_java_util.
:- import_module parse_tree.
:- import_module parse_tree.prog_data.
:- import_module io.
%---------------------------------------------------------------------------%
:- pred output_maybe_qualified_global_var_name_for_java(java_out_info::in,
io.text_output_stream::in, qual_global_var_name::in,
io::di, io::uo) is det.
:- pred output_global_var_name_for_java(io.text_output_stream::in,
mlds_global_var_name::in, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
:- pred output_maybe_qualified_function_name_for_java(java_out_info::in,
io.text_output_stream::in, qual_function_name::in, io::di, io::uo) is det.
:- pred output_function_name_for_java(io.text_output_stream::in,
mlds_function_name::in, io::di, io::uo) is det.
:- pred mlds_output_proc_label_for_java(io.text_output_stream::in,
mlds_proc_label::in, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
:- pred qual_class_name_to_string_for_java(qual_class_name::in, arity::in,
string::out) is det.
:- pred output_unqual_class_name_for_java(io.text_output_stream::in,
mlds_class_name::in, arity::in, io::di, io::uo) is det.
:- pred output_class_name_arity_for_java(io.text_output_stream::in,
mlds_class_name::in, arity::in, io::di, io::uo) is det.
:- pred output_field_var_name_for_java(io.text_output_stream::in,
mlds_field_var_name::in, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
:- pred output_local_var_name_for_java(io.text_output_stream::in,
mlds_local_var_name::in, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
:- pred output_qual_name_prefix_java(io.text_output_stream::in,
mlds_module_name::in, mlds_qual_kind::in, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module backend_libs.
:- import_module backend_libs.rtti.
:- import_module hlds.
:- import_module hlds.hlds_module.
:- import_module hlds.hlds_pred. % for pred_proc_id.
:- import_module mdbcomp.
:- import_module mdbcomp.prim_data.
:- import_module mdbcomp.sym_name.
:- import_module ml_backend.ml_util.
:- import_module ml_backend.mlds_to_target_util.
:- import_module parse_tree.java_names.
:- import_module parse_tree.prog_foreign.
:- import_module bool.
:- import_module int.
:- import_module list.
:- import_module maybe.
:- import_module string.
:- import_module term.
%---------------------------------------------------------------------------%
output_maybe_qualified_global_var_name_for_java(Info, Stream,
QualGlobalVarName, !IO) :-
% Don't module qualify names which are defined in the current module.
% This avoids unnecessary verbosity.
QualGlobalVarName = qual_global_var_name(ModuleName, GlobalVarName),
CurrentModuleName = Info ^ joi_module_name,
( if ModuleName = CurrentModuleName then
true
else
output_qual_name_prefix_java(Stream, ModuleName, module_qual, !IO)
),
output_global_var_name_for_java(Stream, GlobalVarName, !IO).
output_global_var_name_for_java(Stream, GlobalVarName, !IO) :-
(
GlobalVarName = gvn_const_var(ConstVar, Num),
NameStr = ml_global_const_var_name_to_string(ConstVar, Num),
output_valid_mangled_name_for_java(Stream, NameStr, !IO)
;
GlobalVarName = gvn_rtti_var(RttiId),
rtti.id_to_c_identifier(RttiId, RttiAddrName),
io.write_string(Stream, RttiAddrName, !IO)
;
GlobalVarName = gvn_tabling_var(ProcLabel, Id),
Prefix = tabling_info_id_str(Id) ++ "_",
io.write_string(Stream, Prefix, !IO),
mlds_output_proc_label_for_java(Stream,
mlds_std_tabling_proc_label(ProcLabel), !IO)
;
GlobalVarName = gvn_dummy_var,
io.write_string(Stream, "dummy_var", !IO)
).
%---------------------------------------------------------------------------%
output_maybe_qualified_function_name_for_java(Info, Stream, QualFuncName,
!IO) :-
% Don't module qualify names which are defined in the current module.
% This avoids unnecessary verbosity.
QualFuncName = qual_function_name(ModuleName, FuncName),
CurrentModuleName = Info ^ joi_module_name,
( if ModuleName = CurrentModuleName then
true
else
output_qual_name_prefix_java(Stream, ModuleName, module_qual, !IO)
),
output_function_name_for_java(Stream, FuncName, !IO).
output_function_name_for_java(Stream, FunctionName, !IO) :-
(
FunctionName = mlds_function_name(PlainFuncName),
PlainFuncName = mlds_plain_func_name(FuncLabel, _PredId),
FuncLabel = mlds_func_label(ProcLabel, MaybeAux),
ProcLabel = mlds_proc_label(PredLabel, ProcId),
output_pred_label_for_java(Stream, PredLabel, !IO),
proc_id_to_int(ProcId, ModeNum),
io.format(Stream, "_%d", [i(ModeNum)], !IO),
io.write_string(Stream,
mlds_maybe_aux_func_id_to_suffix(MaybeAux), !IO)
;
FunctionName = mlds_function_export(Name),
io.write_string(Stream, Name, !IO)
).
%---------------------------------------------------------------------------%
:- pred output_pred_label_for_java(io.text_output_stream::in,
mlds_pred_label::in, io::di, io::uo) is det.
output_pred_label_for_java(Stream, PredLabel, !IO) :-
(
PredLabel = mlds_user_pred_label(PredOrFunc, MaybeDefiningModule, Name,
PredArity, _, _),
(
PredOrFunc = pf_predicate,
Suffix = "p",
OrigArity = PredArity
;
PredOrFunc = pf_function,
Suffix = "f",
OrigArity = PredArity - 1
),
MangledName = name_mangle_no_leading_digit(Name),
io.format(Stream, "%s_%d_%s",
[s(MangledName), i(OrigArity), s(Suffix)], !IO),
(
MaybeDefiningModule = yes(DefiningModule),
io.write_string(Stream, "_in__", !IO),
output_module_name(Stream, DefiningModule, !IO)
;
MaybeDefiningModule = no
)
;
PredLabel = mlds_special_pred_label(PredName, MaybeTypeModule,
TypeName, TypeArity),
MangledPredName = name_mangle_no_leading_digit(PredName),
MangledTypeName = name_mangle(TypeName),
io.write_string(Stream, MangledPredName, !IO),
io.write_string(Stream, "__", !IO),
(
MaybeTypeModule = yes(TypeModule),
output_module_name(Stream, TypeModule, !IO),
io.write_string(Stream, "__", !IO)
;
MaybeTypeModule = no
),
io.format(Stream, "%s_%d", [s(MangledTypeName), i(TypeArity)], !IO)
).
mlds_output_proc_label_for_java(Stream, mlds_proc_label(PredLabel, ProcId),
!IO) :-
output_pred_label_for_java(Stream, PredLabel, !IO),
proc_id_to_int(ProcId, ModeNum),
io.format(Stream, "_%d", [i(ModeNum)], !IO).
%---------------------------------------------------------------------------%
qual_class_name_to_string_for_java(QualClassName, Arity, String) :-
QualClassName = qual_class_name(MLDS_ModuleName, QualKind, ClassName),
( if
SymName = mlds_module_name_to_sym_name(MLDS_ModuleName),
SymName = java_mercury_runtime_package_name
then
% Don't mangle runtime class names.
String = "jmercury.runtime." ++ ClassName
else
qualifier_to_string_for_java(MLDS_ModuleName, QualKind, QualString),
unqual_class_name_to_string_for_java(ClassName, Arity, UnqualString),
String = QualString ++ "." ++ UnqualString
).
output_unqual_class_name_for_java(Stream, Name, Arity, !IO) :-
unqual_class_name_to_string_for_java(Name, Arity, String),
io.write_string(Stream, String, !IO).
output_class_name_arity_for_java(Stream, ClassName, ClassArity, !IO) :-
output_unqual_class_name_for_java(Stream, ClassName, ClassArity, !IO).
:- pred unqual_class_name_to_string_for_java(mlds_class_name::in, arity::in,
string::out) is det.
unqual_class_name_to_string_for_java(Name, Arity, String) :-
MangledName = name_mangle_no_leading_digit(Name),
% By convention, class names should start with a capital letter.
UppercaseMangledName = flip_initial_case(MangledName),
String = UppercaseMangledName ++ "_" ++ string.from_int(Arity).
output_field_var_name_for_java(Stream, FieldVarName, !IO) :-
NameStr = ml_field_var_name_to_string(FieldVarName),
output_valid_mangled_name_for_java(Stream, NameStr, !IO).
%---------------------------------------------------------------------------%
output_local_var_name_for_java(Stream, LocalVarName, !IO) :-
NameStr = ml_local_var_name_to_string(LocalVarName),
output_valid_mangled_name_for_java(Stream, NameStr, !IO).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
output_qual_name_prefix_java(Stream, ModuleName, QualKind, !IO) :-
qualifier_to_string_for_java(ModuleName, QualKind, QualifierString),
io.write_string(Stream, QualifierString, !IO),
io.write_string(Stream, ".", !IO).
:- pred qualifier_to_string_for_java(mlds_module_name::in, mlds_qual_kind::in,
string::out) is det.
qualifier_to_string_for_java(MLDS_ModuleName, QualKind, String) :-
mlds_module_name_to_package_name(MLDS_ModuleName) = OuterName,
mlds_module_name_to_sym_name(MLDS_ModuleName) = InnerName,
% The part of the qualifier that corresponds to a top-level Java class.
mangle_sym_name_for_java(OuterName, module_qual, "__", MangledOuterName),
% The later parts of the qualifier correspond to nested Java classes.
( if OuterName = InnerName then
MangledSuffix = ""
else
remove_sym_name_prefix(InnerName, OuterName, Suffix),
mangle_sym_name_for_java(Suffix, convert_qual_kind(QualKind), ".",
MangledSuffix0),
MangledSuffix = "." ++ MangledSuffix0
),
String = MangledOuterName ++ MangledSuffix.
%---------------------------------------------------------------------------%
:- pred output_module_name(io.text_output_stream::in, mercury_module_name::in,
io::di, io::uo) is det.
output_module_name(Stream, ModuleName, !IO) :-
io.write_string(Stream, sym_name_mangle(ModuleName), !IO).
:- pred output_valid_mangled_name_for_java(io.text_output_stream::in,
string::in, io::di, io::uo) is det.
output_valid_mangled_name_for_java(Stream, Name, !IO) :-
MangledName = name_mangle(Name),
JavaSafeName = make_valid_java_symbol_name(MangledName),
io.write_string(Stream, JavaSafeName, !IO).
%---------------------------------------------------------------------------%
%
% Code to mangle names, enforce Java code conventions regarding class names
% etc.
% XXX None of this stuff works as it should. The idea is that class names
% should start with an uppercase letter, while method names and package
% specifiers should start with a lowercase letter.
% The current implementation of the MLDS makes this rather harder to achieve
% than it might initially seem. The current position is that coding conventions
% are only enforced on library modules.
% This is needed as Java compilers don't take too well to compiling
% classes named `char',`int', `float' etc.
%
% XXX This won't work if we start using the Java coding conventions
% for all names. At the moment it only affects library modules.
%
:- pred enforce_java_names(string::in, string::out) is det.
:- pragma consider_used(enforce_java_names/2).
enforce_java_names(Name, JavaName) :-
% If the Name contains one or more dots (`.'), then capitalize
% the first letter after the last dot.
reverse_string(Name, RevName),
( if string.sub_string_search(RevName, ".", Pos) then
string.split(RevName, Pos, Head0, Tail0),
reverse_string(Tail0, Tail),
reverse_string(Head0, Head1),
string.capitalize_first(Head1, Head),
string.append(Tail, Head, JavaName)
else
JavaName = Name
).
:- pred reverse_string(string::in, string::out) is det.
reverse_string(String0, String) :-
string.to_char_list(String0, String1),
string.from_rev_char_list(String1, String).
%---------------------------------------------------------------------------%
:- end_module ml_backend.mlds_to_java_name.
%---------------------------------------------------------------------------%