Various fixes to make the Java back-end work better.

Estimated hours taken: 24
Branches: main

Various fixes to make the Java back-end work better.

compiler/ml_code_gen.m:
	Make sure that no module in the generated MLDS
	tries to import itself.

	Also, add some XXX comments about the handling of
	model_semi foreign_procs for Java and IL.

compiler/ml_code_util.m:
	Fix a bug with the handling of `top_unused' modes with `--det-copy-out'.

compiler/mlds_to_java.m:
	Add an XXX comment about the problem with type names clashing
	with constructor names.
	Add an XXX comment about ignoring `pragma foreign_import'
	and `pragma export' for Java.

	Fix the code so that we handle `foreign_decl' and `foreign_code'
	for Java properly -- previously, we were generating code for
	`foreign_decl' in the wrong place, and `foreign_code' was just
	ignored.

	Handle procedures defined as `external' by calling `extern_Foo',
	rather than generating a declaration with no body, because
	Java syntax doesn't allow that.

	Fix a bug where some names weren't getting mangled properly.

	Fix some bugs where it was not generating correct package
	names or module qualifiers for modules in the Mercury
	standard library.

library/Mmakefile:
	Add support for the `java' grade.
	This involved adding new targets `javas' and `classes',
	and making the main `library' target depend on these if
	the grade is `java'.

library/builtin.m:
	Add (stub) Java implementations of various builtins:
	- the type_ctor_infos for the builtin types int, string, character
	- builtin.unify/2 and builtin.compare/3
library/private_builtin.m:
	Add (stub) Java implementations of various builtins:
	- the type_ctor_info for private_builtin.type_info/1
	- builtin_compare_int/3, builtin_compare_string/3,
	  builtin_strcmp/3

library/math.m:
	- Fix a couple of bugs in the Mercury code for "log" and "log2".

library/std_util.m:
	Provide a Java implementation for cc_multi_equal/2.
	Avoid a compiler warning for the Mercury implementation
	of semidet_succeed and semidet_fail.

library/store.m:
	Rename the constructor for the `store/1' type,
	to work around a bug in the Java back-end.

library/string.m:
	Fix bugs in the Mercury implementation of string__contains_char
	and string__split.
	Provide a Java implementation of string__length.

library/type_desc.m:
	Provide Java implementations of type_of/1 and has_type/2.
	Provide (stub) implementations of the builtin types type_desc/0
	and type_ctor_desc/0.
This commit is contained in:
Fergus Henderson
2003-05-14 14:38:48 +00:00
parent a023af4380
commit 8e9c813e37
11 changed files with 306 additions and 39 deletions

View File

@@ -23,6 +23,10 @@
% handle foreign code written in Java
%
% TODO:
% Support for Java in Mmake and mmc --make
% Fix problem with type names and constructor names that are the same
% (Java does not allow the name of a nested class to be
% the same as its enclosing class)
% General code cleanup
% handle static ground terms
% RTTI (requires static ground terms)
@@ -83,6 +87,7 @@
:- import_module parse_tree__modules. % for mercury_std_library_name.
:- import_module parse_tree__prog_data.
:- import_module parse_tree__prog_out.
:- import_module parse_tree__prog_util.
:- import_module bool, int, string, library, list, map, set.
:- import_module assoc_list, term, std_util, require.
@@ -90,6 +95,9 @@
%-----------------------------------------------------------------------------%
mlds_to_java__output_mlds(MLDS) -->
% Note that the Java file name that we use for modules in the
% Mercury standard library do not include a "mercury." prefix;
% that's why we don't call mercury_module_name_to_mlds here.
{ ModuleName = mlds__get_module_name(MLDS) },
{ JavaSafeModuleName = valid_module_name(ModuleName) },
module_name_to_file_name(JavaSafeModuleName, ".java", yes,
@@ -303,8 +311,9 @@ valid_symbol_name(SymName) = ValidSymName :-
ValidSymName = SymName
).
:- type java_module_name == sym_name.
:- func valid_module_name(mercury_module_name) = mercury_module_name.
:- func valid_module_name(java_module_name) = java_module_name.
:- mode valid_module_name(in) = out is det.
valid_module_name(unqualified(String)) = ValidModuleName :-
@@ -383,19 +392,21 @@ output_java_src_file(Indent, MLDS) -->
{ Defns = WrapperDefns ++ Defns0 },
%
% Get the foreign code for Java
% XXX We should not ignore _RevImports and _ExportDefns
%
{ ForeignCode = mlds_get_java_foreign_code(AllForeignCode) },
{ ForeignCode = mlds__foreign_code(RevForeignDecls, _RevImports,
_RevBodyCode, _ExportDefns) },
RevBodyCode, _ExportDefns) },
{ ForeignDecls = list__reverse(RevForeignDecls) },
{ ForeignBodyCode = list__reverse(RevBodyCode) },
%
% Output transformed MLDS as Java source.
%
output_src_start(Indent, ModuleName, Imports, Defns),
output_src_start(Indent, ModuleName, Imports, ForeignDecls, Defns),
{ list__filter(defn_is_rtti_data, Defns, _RttiDefns, NonRttiDefns) },
% XXX Need to output RTTI data at this point.
% Output Java foreign code declarations.
io__write_list(ForeignDecls, "\n", output_java_decl(Indent)),
io__write_list(ForeignBodyCode, "\n", output_java_body_code(Indent)),
{ CtorData = none }, % Not a constructor.
output_defns(Indent + 1, MLDS_ModuleName, CtorData, NonRttiDefns),
output_src_end(Indent, ModuleName).
@@ -419,6 +430,17 @@ output_java_decl(Indent, foreign_decl_code(Lang, Code, Context)) -->
{ sorry(this_file, "foreign code other than Java") }
).
:- pred output_java_body_code(indent, user_foreign_code, io__state, io__state).
:- mode output_java_body_code(in, in, di, uo) is det.
output_java_body_code(Indent, user_foreign_code(Lang, Code, Context)) -->
% only output Java code
( { Lang = java } ->
indent_line(make_context(Context), Indent),
io__write_string(Code), io__nl
;
{ sorry(this_file, "foreign code other than Java") }
).
:- func mlds_get_java_foreign_code(map(foreign_language, mlds__foreign_code))
= mlds__foreign_code.
@@ -428,8 +450,6 @@ mlds_get_java_foreign_code(AllForeignCode) = ForeignCode :-
( map__search(AllForeignCode, java, ForeignCode0) ->
ForeignCode = ForeignCode0
;
% This can occur when compiling to a non-C target
% using "--mlds-dump all"
ForeignCode = foreign_code([], [], [], [])
).
@@ -940,21 +960,25 @@ pred_label_string(special_pred(PredName, MaybeTypeModule,
%
:- pred output_src_start(indent, mercury_module_name, mlds__imports,
mlds__defns, io__state, io__state).
list(foreign_decl_code), mlds__defns, io__state, io__state).
:- mode output_src_start(in, in, in, in, di, uo) is det.
:- mode output_src_start(in, in, in, in, in, di, uo) is det.
output_src_start(Indent, ModuleName, Imports, Defns) -->
{ JavaSafeModuleName = valid_module_name(ModuleName) },
output_auto_gen_comment(ModuleName),
output_src_start(Indent, MercuryModuleName, Imports, ForeignDecls, Defns) -->
{ MLDSModuleName = mercury_module_name_to_mlds(MercuryModuleName) },
{ ModuleSymName = mlds_module_name_to_sym_name(MLDSModuleName) },
{ JavaSafeModuleName = valid_module_name(ModuleSymName) },
output_auto_gen_comment(MercuryModuleName),
indent_line(Indent),
io__write_string("/* :- module "),
prog_out__write_sym_name(JavaSafeModuleName),
prog_out__write_sym_name(MercuryModuleName),
io__write_string(". */\n\n"),
output_package_info(JavaSafeModuleName),
output_imports(Imports),
io__write_list(ForeignDecls, "\n", output_java_decl(Indent)),
io__write_string("public class "),
prog_out__write_sym_name(JavaSafeModuleName),
{ unqualify_name(JavaSafeModuleName, ClassName) },
io__write_string(ClassName),
io__write_string(" {\n"),
maybe_write_main_driver(Indent + 1, JavaSafeModuleName, Defns).
@@ -976,11 +1000,11 @@ output_package_info(qualified(Module, _)) -->
% `main' predicate. Save the command line arguments in the class
% variable `args' in the class `mercury.runtime.JavaInternal'.
%
:- pred maybe_write_main_driver(indent, mercury_module_name,
:- pred maybe_write_main_driver(indent, java_module_name,
mlds__defns, io__state, io__state).
:- mode maybe_write_main_driver(in, in, in, di, uo) is det.
maybe_write_main_driver(Indent, ModuleName, Defns) -->
maybe_write_main_driver(Indent, JavaSafeModuleName, Defns) -->
(
{ defns_contain_main(Defns) }
->
@@ -996,7 +1020,7 @@ maybe_write_main_driver(Indent, ModuleName, Defns) -->
%
io__write_string("mercury.runtime.JavaInternal.args = args;\n"),
indent_line(Indent + 1),
prog_out__write_sym_name(ModuleName),
prog_out__write_sym_name(JavaSafeModuleName),
io__write_string(".main_2_p_0();\n"),
indent_line(Indent + 1),
io__write_string("return;\n"),
@@ -1011,17 +1035,16 @@ maybe_write_main_driver(Indent, ModuleName, Defns) -->
:- mode output_src_end(in, in, di, uo) is det.
output_src_end(Indent, ModuleName) -->
{ JavaSafeModuleName = valid_module_name(ModuleName) },
io__write_string("}\n"),
indent_line(Indent),
io__write_string("// :- end_module "),
prog_out__write_sym_name(JavaSafeModuleName),
prog_out__write_sym_name(ModuleName),
io__write_string(".\n").
% Output a Java comment saying that the file was automatically
% generated and give details such as the compiler version.
%
:- pred output_auto_gen_comment(module_name, io__state, io__state).
:- pred output_auto_gen_comment(mercury_module_name, io__state, io__state).
:- mode output_auto_gen_comment(in, di, uo) is det.
output_auto_gen_comment(ModuleName) -->
@@ -1035,6 +1058,7 @@ output_auto_gen_comment(ModuleName) -->
io__write_string("//\n"),
io__write_string("//\n"),
io__nl.
%-----------------------------------------------------------------------------%
%
% Code to output declarations and definitions.
@@ -1443,9 +1467,6 @@ output_func(Indent, Name, CtorData, Context, Signature, MaybeBody)
-->
output_func_decl(Indent, Name, CtorData, Context, Signature),
(
{ MaybeBody = external },
io__write_string(";\n")
;
{ MaybeBody = defined_here(Body) },
io__write_string("\n"),
indent_line(Context, Indent),
@@ -1454,6 +1475,18 @@ output_func(Indent, Name, CtorData, Context, Signature, MaybeBody)
output_statement(Indent + 1, FuncInfo, Body, _ExitMethods),
indent_line(Context, Indent),
io__write_string("}\n") % end the function
;
{ MaybeBody = external },
% Java requires that all function definitions have a body.
% So for each external function "Foo", we emit a body
% which is just a call to "extern_Foo" with the same
% parameters.
io__write_string("\n"),
indent_line(Context, Indent),
io__write_string("{\n"),
output_extern_call(Indent + 1, Name, Context, Signature),
indent_line(Context, Indent),
io__write_string("}\n") % end the function
).
:- pred output_func_decl(indent, qualified_entity_name, ctor_data,
@@ -1482,8 +1515,6 @@ output_func_decl(Indent, QualifiedName, none, Context, Signature) -->
output_name(Name),
output_params(Indent, ModuleName, Context, Parameters).
:- pred output_params(indent, mlds_module_name, mlds__context,
mlds__arguments, io__state, io__state).
:- mode output_params(in, in, in, in, di, uo) is det.
@@ -1510,6 +1541,55 @@ output_param(Indent, ModuleName, Context, Arg) -->
io__write_char(' '),
output_fully_qualified_name(qual(ModuleName, Name)).
%-----------------------------------------------------------------------------%
% Java requires that all function declarations have a body.
% So for each function "Foo" which is declared as "external",
% we emit a body which is just a call to "extern_Foo" with the same
% parameters.
:- pred output_extern_call(indent, qualified_entity_name,
mlds__context, func_params, io__state, io__state).
:- mode output_extern_call(in, in, in, in, di, uo) is det.
output_extern_call(Indent, QualifiedName, Context, Signature) -->
{ Signature = mlds__func_params(Parameters, RetTypes) },
{ QualifiedName = qual(ModuleName, Name) },
indent_line(Context, Indent),
( { RetTypes \= [] } ->
io__write_string("return ")
;
[]
),
io__write_string("extern_"),
output_name(Name),
output_extern_call_args(Indent, ModuleName, Context, Parameters),
io__write_string(";\n").
:- pred output_extern_call_args(indent, mlds_module_name, mlds__context,
mlds__arguments, io__state, io__state).
:- mode output_extern_call_args(in, in, in, in, di, uo) is det.
output_extern_call_args(Indent, ModuleName, Context, Parameters) -->
io__write_char('('),
( { Parameters = [] } ->
[]
;
io__nl,
io__write_list(Parameters, ",\n",
output_extern_call_arg(Indent + 1, ModuleName, Context))
),
io__write_char(')').
:- pred output_extern_call_arg(indent, mlds_module_name, mlds__context,
mlds__argument, io__state, io__state).
:- mode output_extern_call_arg(in, in, in, in, di, uo) is det.
output_extern_call_arg(Indent, ModuleName, Context, Arg) -->
{ Arg = mlds__argument(Name, _Type, _GC_TraceCode) },
indent_line(Context, Indent),
output_fully_qualified_name(qual(ModuleName, Name)).
%-----------------------------------------------------------------------------%
%
% Code to output names of various entities
@@ -2741,7 +2821,9 @@ output_lval(var(qual(_ModuleName, Name), _VarType)) -->
:- mode output_mangled_name(in, di, uo) is det.
output_mangled_name(Name) -->
io__write_string(name_mangle(Name)).
{ MangledName = name_mangle(Name) },
{ JavaSafeName = valid_symbol_name(MangledName) },
io__write_string(JavaSafeName).
:- pred mlds_output_bracketed_lval(mlds__lval, io__state, io__state).
:- mode mlds_output_bracketed_lval(in, di, uo) is det.