mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-18 10:53:40 +00:00
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.
254 lines
9.1 KiB
Mathematica
254 lines
9.1 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.
|
|
|
|
:- func get_debug_class_init(java_out_info) = bool.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- 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(io.text_output_stream::in, bool::in,
|
|
context_marker::in, prog_context::in, io::di, io::uo) is det.
|
|
|
|
:- pred indent_line_after_context(io.text_output_stream::in, 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,
|
|
io.text_output_stream::in, indent::in, string::in, prog_context::in,
|
|
io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred maybe_output_comment_for_java(java_out_info::in,
|
|
io.text_output_stream::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, []).
|
|
|
|
get_debug_class_init(Info) = DebugClassInit :-
|
|
% It is not worth having an extra field in Info for this option,
|
|
% since we only look it up twice per module.
|
|
ModuleInfo = Info ^ joi_module_info,
|
|
module_info_get_globals(ModuleInfo, Globals),
|
|
lookup_bool_option(Globals, debug_class_init, DebugClassInit).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- mutable(last_context, prog_context, context_init, ground,
|
|
[untrailed, attach_to_io_state]).
|
|
|
|
output_context_for_java(Stream, 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(Stream, "// %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(Stream, OutputLineNumbers, Marker, Context, N, !IO) :-
|
|
output_context_for_java(Stream, OutputLineNumbers, Marker, Context, !IO),
|
|
output_n_indents(Stream, N, !IO).
|
|
|
|
write_string_with_context_block(Info, Stream, Indent, Code, Context, !IO) :-
|
|
indent_line_after_context(Stream, Info ^ joi_foreign_line_numbers,
|
|
marker_begin_block, Context, Indent, !IO),
|
|
io.write_string(Stream, Code, !IO),
|
|
io.nl(Stream, !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(Stream, 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, Stream, Comment, !IO) :-
|
|
AutoComments = Info ^ joi_auto_comments,
|
|
(
|
|
AutoComments = yes,
|
|
io.write_string(Stream, "/* ", !IO),
|
|
io.write_string(Stream, Comment, !IO),
|
|
io.write_string(Stream, " */", !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.
|
|
%---------------------------------------------------------------------------%
|