[m-dev.] for review: Java backend

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Feb 15 21:46:35 AEDT 2001


On 14-Feb-2001, Julien Fischer <juliensf at students.cs.mu.oz.au> wrote:
> 
> +:- pred mlds_sym_name_mangle_java(sym_name, string).
> +:- mode mlds_sym_name_mangle_java(in, out) is det.
> +
> +mlds_sym_name_mangle_java(unqualified(Name), MangledName) :-
> +	llds_out__name_mangle(Name, MangledName).
> +mlds_sym_name_mangle_java(qualified(ModuleName, PlainName), MangledName) :-
> +	mlds_sym_name_mangle_java(ModuleName, MangledModuleName),
> +	llds_out__name_mangle(PlainName, MangledPlainName),
> +	mlds_qualify_mangled_name(MangledModuleName, MangledPlainName, 
> +		MangledName).
> +
> +:- pred mlds_qualify_mangled_name(string, string, string).
> +:- mode mlds_qualify_mangled_name(in, in, out) is det.
> +
> +mlds_qualify_mangled_name(Module0, Name0, Name) :-
> +	string__append_list([Module0,".",Name0], Name).

The `mlds_' doesn't really make sense there, since these are just
strings; there's nothing MLDS-specific about that routine, rather
it is Java-specific.  So I suggest
s/mlds_qualify_mangled_name/java_qualify_mangled_name/
or perhaps just s/mlds_qualify_mangled_name/qualify_mangled_name/.

Also mlds_sym_name_mangle_java isn't great; I think
`java_mangle_mlds_sym_name' or `mangle_mlds_sym_name_for_java' would
be better.

> +mlds_output_src_file(Indent, MLDS) -->
...
> +	% XXX Need to handle non-Java foriegn code at this point.

s/foriegn/foreign/

> +%------------------------------------------------------------------------------%
> +%
> +% MLDS->MLDS Transformations 
> +%
> +
> +	% For each Unify and Compare predicate create a class that 
> +	% implements either the Unify or Compare interface respectively.  

s/predicate/predicate,/

> +	% The call function that is implemented in the class then 
> +	% calls Unify and Compare.

s/call/`call'/

> +	%
> +:- pred transform_special_predicates(mercury_module_name, mlds__defns, 
> +		mlds__defns).
> +:- mode transform_special_predicates(in, in, out) is det.
> +
> +transform_special_predicates(ModuleName, Defns0, Defns) :- 
> +	list__filter(defn_is_special_pred, Defns0, SpecialPredDefns), 
> +	wrap_predicates(ModuleName, SpecialPredDefns, WrappedDefns),
> +	list__append(WrappedDefns, Defns0, Defns). 
> +
> +:- pred wrap_predicates(mercury_module_name, mlds__defns, mlds__defns).
> +:- mode wrap_predicates(in, in, out) is det.
> +
> +wrap_predicates(_, [], []). 
> +wrap_predicates(ModuleName, [Defn0 | Defns0], Defns) :-
> +	wrap_predicate(ModuleName, Defn0, Defn), 
> +	wrap_predicates(ModuleName, Defns0, Defns1),
> +	list__append([Defn], Defns1, Defns).

The last line should be just `Defns = [Defn | Defns1]',
or even better write it as a head unification

	wrap_predicates(_, [], []). 
	wrap_predicates(ModuleName, [Defn0 | Defns0], [Defn | Defns]) :-
		wrap_predicate(ModuleName, Defn0, Defn), 
		wrap_predicates(ModuleName, Defns0, Defns).

(Or alternatively, just use list__map.)

> +:- pred wrap_predicate(mercury_module_name, mlds__defn, mlds__defn).
> +:- mode wrap_predicate(in, in, out) is det.
> +
> +wrap_predicate(ModuleName, Defn, ClassDefn) :-
> +	Defn = mlds__defn(Name, _, _, _),
> +	( 
> +		Name = function(Label, _, _, _),
> +   	 	Label = special_pred(PredName, _, _, _) 
> +	  
> +	->
> +		
> +		( PredName = "__Unify__" 
> +		
> +		-> 
> +			InterfaceName = "Unify"
> +		
> +		; 	PredName = "__Compare__" 
> +		
> +		->
> +			InterfaceName = "Compare"
> +		;
> +			InterfaceName = ""
> +		
> +		),

There's lots of blank lines here in wierd places.  Plese delete them.
In general, fix the layout of that code.

The line `InterfaceName = ""' looks wrong.
Perhaps that should call error/1.
If not, it would be better to use a maybe(string) rather
than using "" as a special value.

You may need to handle the "Index" special predicates here.

> +generate_wrapper_class(ModuleName, Interface, MethodDefn, ClassDefn) :-
> +	MethodDefn = mlds__defn(Name, Context, _DeclFlags, _DefnBody),
> +	( 	
> +		Name = function(Label, _ProcID, _MaybeSeqNum, _PredID),
> +		Label = special_pred(PredName0, _, Type, Arity)
> +	->
> +	   
> +		%
> +		% Create class components. 
> +		%
> +		ClassImports  = [],
> +		ClassExtends = [],
> +		InterfaceDefn = mlds__class_type(Interface, 0, mlds__interface),
> +		ClassImplements = [InterfaceDefn],
> +		%
> +		% Create a method that calls the orignal predicate.
> +		%

s/orignal/original/

> +	%
> +	% Transform a list of function arguments into a list of local
> +	% variable declarations of the same name and type.  Create
> +	% initializers that initalize each new local variable to the
> +	% correct element in the `args' array.
> +	%
> +:- pred generate_wrapper_decls(mercury_module_name, mlds__context, 
> +	mlds__arguments, int, mlds__defns).
> +:- mode generate_wrapper_decls(in, in, in, in, out) is det.
> +
> +generate_wrapper_decls(_, _, [], _, []).
> +generate_wrapper_decls(ModuleName, Context, [Arg | Args], Count, Defns) :-
> +	Arg = Name - Type,
> +	Flags = ml_gen_local_var_decl_flags,
> +	string__int_to_string(Count, Index),
> +	string__append("args[", Index, UnqualName0),
> +	string__append(UnqualName0, "]", UnqualName),
> +	NewVarName = qual(mercury_module_name_to_mlds(ModuleName), UnqualName),

Hmm, here you're using "args[0]" as a _variable name_?

I think it would be much nicer to use the `array_index' unary_op.

> +	%		
> +	% Package everything together.
> +	%
> +	NewArgLval = var(NewVarName, mlds__generic_type),
> +	Initializer = lval(NewArgLval),
> +	Body = mlds__data(Type, init_obj(Initializer)),	
> +	Defn = mlds__defn(Name, Context, Flags, Body),
> +	%	
> +	% Recrusively call ourself to process the next argument.		
> +	%
> +	generate_wrapper_decls(ModuleName, Context, Args, Count + 1, Defns0),
> +	list__append([Defn], Defns0, Defns).

s/Recrus/Recurs/

See comments above regarding use of list__append here.

> +%------------------------------------------------------------------------------
> +%
> +% Code to output the start and end of a source file. 
> +% 
> +
> +:- pred mlds_output_src_start(indent, mercury_module_name, mlds__imports, 
> +	mlds__defns, io__state, io__state).
> +
> +:- mode mlds_output_src_start(in, in, in, in, di, uo) is det.
> +
> +mlds_output_src_start(Indent, ModuleName, Imports, Defns) -->
> +	mlds_output_auto_gen_comment(ModuleName),
> +	mlds_indent(Indent),
> +	io__write_string("/* :- module "),
> +	prog_out__write_sym_name(ModuleName),
> +	io__write_string(". */\n\n"),
> +	mlds_output_package_info(ModuleName),	
> +	mlds_output_imports(Imports),
> +	io__write_string("public class "),
> +	prog_out__write_sym_name(ModuleName),
> +	io__write_string(" {\n"),
> +	mlds_maybe_write_main_driver(Indent + 1, ModuleName, Defns).

All of these `mlds_' prefixes are inappropriate here;
they should be replaced with `java_', or perhaps just deleted.

> +	% Check if this module contains a main predicate and if it does insert
> +	% a dummy main function in the resulting Java class that calls 
> +	% the main predicate.

The use of the word `dummy' here isn't quite right.
So I suggest s/dummy main/main/
(or perhaps s/dummy main/Java main/)

Also s/main/`main'/g would make it clearer.

> +mlds_maybe_write_main_driver(Indent, ModuleName, Defns) -->
> +	(
> +		{ list__member(Defn, Defns) },
> +		{ Defn = mlds__defn(Name, _, _, _) },
> +		{ Name = function(FuncName, _, _, _) },
> +		{ FuncName = pred(predicate, _, "main", 2) } 

That code duplicates some code in mercury_compile.m;
it would be a good idea to abstract that code out into
a routine in ml_util.m.

> +mlds_output_class(Indent, Name, _Context, ClassDefn) -->
> +	{ Name = qual(ModuleName, UnqualName) },
> +	({ UnqualName = type(_, _) } ->

s/({/( {/

> +		[]	
> +	;
> +		{error("mlds_to_java.m: mlds_output_class")}

s/{/{ /
s/}/} /

Use unexpected/2 from error_util.m, and this_file/0.

> +	% Output superclass that this class extends.  Java does
> +	% not support multiple inheritance, so more than one superclass
> +	% is an error.
> +	%
> +:- pred mlds_output_extends_list(list(mlds__class_id), io__state, io__state).
> +:- mode mlds_output_extends_list(in, di, uo) is det.
> +
> +mlds_output_extends_list([]) --> [].
> +mlds_output_extends_list([SuperClass]) -->
> +	io__write_string(" extends "),
> +	mlds_output_type(SuperClass).
> +mlds_output_extends_list([_, _ | _]) -->
> +	{ error("mlds_to_java.m: multiple inheritance not supported in Java") }.

Use unexpected/2 from error_util.m, and this_file/0.

> +:- pred mlds_output_class_body(indent, mlds__class_kind, 
> +	mlds__qualified_entity_name, mlds__defns, mlds_module_name, io__state, 
> +	io__state).

Please indent wrapped type declarations by two tabs.

> +mlds_output_class_body(_Indent, mlds__struct, _, _AllMembers, _) -->	
> +	{ error("mlds_to_java.m: structs not supported in Java.") }.

Use unexpected/2 and this_file/0.

> +mlds_output_enum_constant(Indent, EnumModuleName, Defn) -->
...
> +	;
> +		{ error("mlds_to_java.m: mlds_output_enum_constant: definition body was not data.") }
> +	).

Likewise here.

> +%-----------------------------------------------------------------------------%
> +%
> +% Code to output data declarations/definitions
> +%
> +
> +:- pred mlds_output_data_decl(mlds__qualified_entity_name, mlds__type,
> +			initializer_array_size, io__state, io__state).
> +:- mode mlds_output_data_decl(in, in, in, di, uo) is det.
> +
> +mlds_output_data_decl(Name, Type, InitializerSize) -->
> +	mlds_output_data_decl_ho(mlds_output_type,
> +			(pred(Tp::in, di, uo) is det -->
> +				mlds_output_type_suffix(Tp, InitializerSize)),
> +			Name, Type).
>
> +:- pred mlds_output_data_decl_ho(output_type, output_type,
> +		mlds__qualified_entity_name, mlds__type, io__state, io__state).
> +:- mode mlds_output_data_decl_ho(in(output_type), in(output_type),
> +		in, in, di, uo) is det.
> +
> +mlds_output_data_decl_ho(OutputPrefix, OutputSuffix, Name, Type) -->
> +	OutputPrefix(Type),
> +	io__write_char(' '),
> +	mlds_output_fully_qualified_name(Name),
> +	OutputSuffix(Type).

Java doesn't require suffixes for its type declarations, so *all*
of that stuff do with output_type_suffix should go.

> +	% We need to provide initializers for local variables
> +	% to avoid problems with definite assignment.

I suggest s/definite assignment/Java's rules for definite assignment/

> +:- pred mlds_output_initializer(mlds__type, mlds__initializer,
> +		io__state, io__state).
> +:- mode mlds_output_initializer(in, in, di, uo) is det.
> +
> +mlds_output_initializer(Type, Initializer) -->
> +	io__write_string(" = "),
> +	( { mlds_needs_initialization(Initializer) = yes } ->
> +			( { Initializer = init_obj(Rval) }
> +			
> +			->
> +				( 	{ type_is_object(Type),
> +					rval_is_int_const(Rval) } 
> +				->
> +					%
> +					% If it is a enumeration object
> +					% create new object.
> +					%
> +					io__write_string("new "),
> +					mlds_output_type(Type),
> +					io__write_char('('),
> +					mlds_output_initializer_body(
> +						Initializer),
> +					io__write_char(')')
> +				;
> +					% If it is an non-enumeration
> +					% object, insert appropriate
> +					% cast.
> +					% XXX The logic of this is a bit
> +					% wrong.  Fixing it would eliminate
> +					% some of the unecessary casting
> +					% that happens
> +					%
> +					io__write_string("("),
> +					mlds_output_type(Type),
> +					io__write_string(") "),
> +					mlds_output_initializer_body(
> +						Initializer)
> +				)
> +			;
> +				mlds_output_initializer_body(Initializer)
> +			)
> +	;

Fix the indentation and layout.

[to be continued]

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list