Files
mercury/compiler/mlds_to_java_util.m
Zoltan Somogyi 4404d7d884 Split up mlds_to_java.m.
compiler/mlds_to_java.m:
    Delete this module. Move its contents to the following eleven modules.

compiler/mlds_to_java_class.m:
    Code to output class definitions.

compiler/mlds_to_java_data.m:
    Code to output lvals, rvals and initializers.

compiler/mlds_to_java_export.m:
    Code to output entities (e.g. enums) exported to Java.

compiler/mlds_to_java_file.m:
    The top level code, generating whole Java files.

compiler/mlds_to_java_func.m:
    Code to output function definitions.

compiler/mlds_to_java_global.m:
    Code to output the definitions of global variables.

compiler/mlds_to_java_name.m:
    Code to output various kinds of names.

compiler/mlds_to_java_stmt.m:
    Code to output statements.

compiler/mlds_to_java_type.m:
    Code to output types.

compiler/mlds_to_java_util.m:
    Utilities used by the other mlds_to_java_*.m modules.

compiler/mlds_to_java_wrap.m:
    Code to create wrapper classes, to help implement function pointers.

compiler/ml_backend.m:
    Delete the old module, add the new modules.

compiler/Mercury.options:
    Require the new modules to have the declarations and definitions
    of their predicates in a consistent order.

compiler/mercury_compile_mlds_back_end.m:
    Import mlds_to_java_file.m instead of mlds_to_java.m.

compiler/mlds.m:
compiler/mlds_to_cs.m:
    Update some references to the deleted file.

compiler/mlds_to_c_class.m:
    Delete some stray ZZZs.
2018-06-29 18:13:12 +02:00

246 lines
8.6 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.
%---------------------------------------------------------------------------%
%
% Utility services required by the other mlds_to_java*.m modules.
%
%---------------------------------------------------------------------------%
:- module ml_backend.mlds_to_java_util.
:- interface.
:- import_module hlds.
:- import_module hlds.hlds_module.
:- import_module ml_backend.mlds.
:- import_module ml_backend.mlds_to_target_util.
:- import_module parse_tree.
:- import_module parse_tree.prog_data.
:- import_module bool.
:- import_module io.
:- import_module list.
:- import_module map.
:- import_module maybe.
%---------------------------------------------------------------------------%
:- type code_addr_wrapper
---> code_addr_wrapper(
caw_class :: string,
caw_ptr_num :: maybe(int)
).
% Keep the enum fields together, so they can be packed into one word.
:- type java_out_info
---> java_out_info(
% These are static.
joi_module_info :: module_info,
joi_auto_comments :: bool,
joi_line_numbers :: bool,
joi_foreign_line_numbers :: bool,
joi_module_name :: mlds_module_name,
joi_source_filename :: string,
joi_addrof_map :: map(mlds_code_addr, code_addr_wrapper),
% These are dynamic.
joi_output_generics :: output_generics,
joi_break_context :: break_context,
joi_univ_tvars :: list(tvar)
).
:- func init_java_out_info(module_info, string,
map(mlds_code_addr, code_addr_wrapper)) = java_out_info.
%---------------------------------------------------------------------------%
:- type context_marker
---> marker_begin_block
% The beginning of some Java foreign code whose errors
% should be reported with Mercury line numbers.
; marker_end_block
% The end of such a block.
; marker_comment.
% This marks Mercury generated code for which Java's line numbers
% should be used, it is just a comment for the Mercury developers.
:- pred output_context_for_java(bool::in, context_marker::in,
prog_context::in, io::di, io::uo) is det.
:- pred indent_line_after_context(bool::in, context_marker::in,
prog_context::in, indent::in, io::di, io::uo) is det.
:- pred write_string_with_context_block(java_out_info::in, indent::in,
string::in, prog_context::in, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
:- pred maybe_output_comment_for_java(java_out_info::in, string::in,
io::di, io::uo) is det.
%---------------------------------------------------------------------------%
:- pred is_specialised_method_ptr_arity(int::in) is semidet.
%---------------------------------------------------------------------------%
:- implementation.
:- import_module libs.
:- import_module libs.globals.
:- import_module libs.options.
:- import_module mdbcomp.
:- import_module mdbcomp.sym_name.
:- import_module char.
:- import_module int.
:- import_module string.
:- import_module term.
%---------------------------------------------------------------------------%
init_java_out_info(ModuleInfo, SourceFileName, AddrOfMap) = Info :-
module_info_get_globals(ModuleInfo, Globals),
globals.lookup_bool_option(Globals, auto_comments, AutoComments),
globals.lookup_bool_option(Globals, line_numbers, LineNumbers),
globals.lookup_bool_option(Globals, line_numbers_around_foreign_code,
ForeignLineNumbers),
module_info_get_name(ModuleInfo, ModuleName),
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
Info = java_out_info(ModuleInfo, AutoComments,
LineNumbers, ForeignLineNumbers, MLDS_ModuleName, SourceFileName,
AddrOfMap, do_not_output_generics, bc_none, []).
%---------------------------------------------------------------------------%
:- mutable(last_context, prog_context, context_init, ground,
[untrailed, attach_to_io_state]).
output_context_for_java(OutputLineNumbers, Marker, ProgContext, !IO) :-
(
OutputLineNumbers = yes,
get_last_context(LastContext, !IO),
term.context_file(ProgContext, File),
term.context_line(ProgContext, Line),
( if
% It is safe to ignore marker comments when the comment isn't
% useful. All other marker types must be emitted in all cases.
(
Marker = marker_comment
=>
(
ProgContext \= LastContext,
Line > 0,
File \= ""
)
)
then
% Java doesn't have an equivalent of #line directives.
% We use the token MER_LINE to allow us to filter these lines out
% of the file when mangling javac's output.
% \u is treated as a Unicode escape even with comments.
string.replace_all(File, "\\u", "\\\\u", SafePath),
% Do not modify this format string without modifying
% mfilterjavac/mfilterjavac.m.
io.format("// %s %s:%d\n",
[s(marker_string(Marker)), s(SafePath), i(Line)], !IO),
set_last_context(ProgContext, !IO)
else
true
)
;
OutputLineNumbers = no
).
% Do not modify these strings without modifying util/mfilterjavac.m.
%
:- func marker_string(context_marker) = string.
marker_string(marker_begin_block) = "MER_FOREIGN_BEGIN".
marker_string(marker_end_block) = "MER_FOREIGN_END".
marker_string(marker_comment) = "".
%---------------------------------------------------------------------------%
indent_line_after_context(OutputLineNumbers, Marker, Context, N, !IO) :-
output_context_for_java(OutputLineNumbers, Marker, Context, !IO),
output_n_indents(N, !IO).
write_string_with_context_block(Info, Indent, Code, Context, !IO) :-
indent_line_after_context(Info ^ joi_foreign_line_numbers,
marker_begin_block, Context, Indent, !IO),
io.write_string(Code, !IO),
io.nl(!IO),
% The num_lines(Code) call is supposed to count the number of lines
% occupied by Code in the source file. The result will be incorrect if
% there were any escape sequences representing CR or LF characters --
% they are expanded out in Code.
Context = context(File, Lines0),
ContextEnd = context(File, Lines0 + num_lines(Code)),
indent_line_after_context(Info ^ joi_foreign_line_numbers,
marker_end_block, ContextEnd, Indent, !IO).
:- func num_lines(string) = int.
num_lines(String) = Num :-
% The initial "previous" character may be anything other than \r.
string.foldl2(count_new_lines, String, 1, Num, 'x', _).
% Increment the line count !N whenever we see CR or LF or CRLF,
% ensuring that the latter counts as only ONE newline.
%
:- pred count_new_lines(char::in, int::in, int::out, char::in, char::out)
is det.
count_new_lines(C, !N, Prev, C) :-
( if
(
C = '\r'
;
(
C = '\n',
Prev \= '\r'
)
)
then
!:N = !.N + 1
else
true
).
%---------------------------------------------------------------------------%
maybe_output_comment_for_java(Info, Comment, !IO) :-
AutoComments = Info ^ joi_auto_comments,
(
AutoComments = yes,
io.write_string("/* ", !IO),
io.write_string(Comment, !IO),
io.write_string(" */", !IO)
;
AutoComments = no
).
%---------------------------------------------------------------------------%
is_specialised_method_ptr_arity(Arity) :-
Arity > 0, % No specialised method ptr for arity zero predicates.
Arity =< max_specialised_method_ptr_arity.
% The highest arity for which there is a specialised MethodPtr<n>
% interface.
%
:- func max_specialised_method_ptr_arity = int.
max_specialised_method_ptr_arity = 15.
%---------------------------------------------------------------------------%
:- end_module ml_backend.mlds_to_java_util.
%---------------------------------------------------------------------------%