[m-rev.] for review: Modifications to the Java back-end

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Jan 23 11:59:12 AEDT 2002


On 22-Jan-2002, Michael Wybrow <mjwybrow at students.cs.mu.oz.au> wrote:
> +generate_call_method(CodeAddr, MethodDefn) :-
...
> +	ReturnDecFlags = init_decl_flags(private, one_copy, non_virtual,
> +			final, modifiable, concrete),

That's wrong -- it shouldn't be "private" or "one_copy".

Use ml_gen_local_var_decl_flags.

> +	ReturnEntityDefn = mlds__data(ReturnVarType, no_initializer, no), 

It might be a good idea to write that as

	GCTraceCode = no,
	ReturnEntityDefn = mlds__data(ReturnVarType, no_initializer,
		GCTraceCode), 

and to add a comment explaining why it's OK to set GCTraceCode = no here.

> +	%
> +	% Create a return statement that returns the result of the call to the
> +	% original method, boxed as a java.lang.Object.
> +	% 
> +	ReturnRval = unop(box(mlds__generic_type), lval(ReturnLval)),

The argument of box/1 should be the *original* type of the entity being boxed
(i.e. `MethodRetType' in this case, I think), not the type of the boxed result.

> +	Block = block(MethodDefns, [CallStatement|[ReturnStatement]]),

Write that as `[CallStatement, ReturnStatement]'.

> +:- pred generate_call_method_args(list(mlds__type), mlds__var, int, 
> +		list(mlds__rval), list(mlds__rval)).
> +:- mode generate_call_method_args(in, in, in, in, out) is det.
> +
> +generate_call_method_args([], _, _, Args, Args).
> +generate_call_method_args([_Type|Types], Variable, Counter, Args0, Args) :-
> +	ArrayRval = mlds__lval(mlds__var(Variable, mlds__native_int_type)),

Using mlds__native_int_type here is wrong.
The type that should be used is the type of the array
(`mlds__array(mlds__generic_type)', I think).

> +	Rval = binop(array_index(elem_type_generic), ArrayRval, IndexRval),
> +	BoxedRval = unop(unbox(mlds__generic_type), Rval),

s/BoxedRval/UnboxedRval/g

The argument of unbox/1 should the final unboxed type,
i.e. the variable `_Type' in this case.

> +:- pred symbol_name_to_string(sym_name, string, string).
> +:- mode symbol_name_to_string(in, in, out) is det.
> +
> +symbol_name_to_string(unqualified(SymName), SymNameStr0, SymNameStr) :-
> +	SymNameStr = SymNameStr0 ++ SymName.
> +symbol_name_to_string(qualified(Qualifier, SymName), SymNameStr0, SymNameStr) :-
> +	symbol_name_to_string(Qualifier, SymNameStr0, SymNameStr1),
> +	SymNameStr = SymNameStr1 ++ "__" ++ SymName.

It would be better to make that a function rather than a predicate.

> @@ -610,38 +1097,49 @@
...
> +	% Discriminated union which allows us to pass down the class name if 
> +	% a definition is a constructor, this is needed since the class name
> +	% is not available for a constructor in the mlds.

s/,/;/

> @@ -675,6 +1168,12 @@
>  	output_implements_list(Implements),
>  	io__write_string(" {\n"),
>  	output_class_body(Indent + 1, Kind, Name, AllMembers, ModuleName),
> +	io__nl,
> +	( { Ctors = [] } ->
> +		[]		% No constructors.
> +	;
> +		output_defns(Indent + 1, ModuleName, cname(UnqualName),	Ctors)
> +	),

Do you need to special-case the Ctors = [] case here?
Why not just call output_defns unconditionally?

> @@ -1556,21 +2075,94 @@
>  		%
>  		io__write_string("java.lang.Object [] result = ")
>  	),
> -	( { MaybeObject = yes(Object) } ->
> -		output_bracketed_rval(Object),
> -		io__write_string(".")
> +	( { FuncRval = lval(var(_, func_type(_))) } -> 

That's not the right way to test if it is a call via a function pointer.
For example, the function pointer might be a field of some data structure,
rather than a variable.

Instead, you should test for

	( { FuncRval \= const(code_addr_const(_)) } ->

and then it would be nicer to swap the "then" and the "else" parts
so you can test for "=" rather than "\=".

> +		( { MaybeObject = yes(Object) } ->
> +			output_bracketed_rval(Object),
> +			io__write_string(".")
> +		;
> +			[]
> +		),

These five lines seem to be the same for both the "then" and then "else"
parts, in which case they should be extracted out

> +		%
> +		% Here we do downcasting, as a call will always return
> +		% something of type java.lang.Object
> +		%
> +		% XXX This is a hack, I can't see any way to do this
> +		%     downcasting nicely, as it needs to effectively be
> +		%     wrapped around the method call itself, so it acts
> +		%     before this predicate's solution to multiple return
> +		%     values, see above.

Maybe the best way to do it is to write a higher-order Mercury
predicate to do an unbox operation; this would take as an argument
a closure that prints out the Java expression which is being unboxed.

However, don't worry about that until after the rest of this is committed.

> +		%
> +		% This is a function pointer call. It may look strange that we
> +		% use "output_nonaddressed_rval" with the call, this is
> +		% because the "AddOf__whatever" will have been stored as a 
> +		% MethodPtr variable - "FuncRval" will be that variable, so we
> +		% want to output it normally.
> +		%
> +		output_nonaddressed_rval(FuncRval),

s/AddOf/AddrOf/

But actually this comment is bogus -- you can (and probably should) just use
`output_bracketed_rval' here.  The rval won't be a code_addr_const
anyway, because the condition of the if-then-else that this code is
inside already checked that.

...
> +:- pred output_args_as_array(list(mlds__rval), io__state, io__state).
> +:- mode output_args_as_array(in, di, uo) is det.
> +
> +output_args_as_array(CallArgs) -->
> +	io__write_string("new java.lang.Object[] { "),
> +	output_boxed_args(CallArgs, mlds__generic_type),

Again you've got the type for the argument of box/1 wrong.
You need to pass in the list of the argument types to this routine
and use the appropriate type for each

> -output_atomic_stmt(Indent, _FuncInfo, NewObject, Context) -->
> +output_atomic_stmt(Indent, _FuncInfo, NewObject, _Context) -->
>  	{ NewObject = new_object(Target, _MaybeTag, _HasSecTag, Type,
>  		_MaybeSize, MaybeCtorName, Args, ArgTypes) },
>  	
>  	indent_line(Indent),
> -	io__write_string("{\n"),
> -	indent_line(Context, Indent + 1),

The `{' is needed, I'm pretty sure,
in case this statement is the body of an if-then-else.

> -	io__write_string("();\n"),
> -	output_init_args(Args, ArgTypes, CtorDefn, Context, 0, Target, 0,
> -		Indent + 1),
> -	indent_line(Context, Indent),
> -	io__write_string("}\n").
> +	( { Type = mlds__func_type(_FuncParams);
> +	    Type =mlds__mercury_type(_Type, pred_type, _) } 
> +	->

The condition of the if-then-else should be indented if it doesn't fit
on a single line, and the ";" for a disjunction should be at the start
of a line.  Also s/=m/= m/

> +		%
> +		% The new object will be an array of java.lang.Object, we need
> +		% to initialise it using array literals syntax.

Isn't this true only for closures (mercury_type(_, pred_type, _)),
not for function pointers?  Function pointers should never be
used in new_object() instructions.

Also s/, we/, so we/

> @@ -1937,8 +2500,25 @@
> +output_lval(field(_MaybeTag, Rval, offset(OffsetRval), FieldType,
> +		_ClassType)) -->
> +	(
> +		{ FieldType = mlds__generic_type
> +		; FieldType = mlds__mercury_type(term__variable(_), _, _)
> +		}
> +	->
> +		io__write_string("(")
> +	;
> +		% The field type for field(_, _, offset(_), _, _) lvals
> +		% must be something that maps to MR_Box.
> +		{ error("unexpected field type") }
> +	),
> +	output_rval(Rval),
> +	io__write_string("["),
> +	output_rval(OffsetRval),
> +	io__write_string("]))").

Move the call to io__write_string("(") to after the if-then-else
(change the "then" part of the if-then-else to just "[]").

> +:- pred output_nonaddressed_rval(mlds__rval, io__state, io__state).
> +:- mode output_nonaddressed_rval(in, di, uo) is det.

There should be a comment here explaining what you mean by a "nonaddressed"
rval.

> +output_nonaddressed_rval(Rval) -->
> +	(
> +		{ Rval = mlds__const(Const),
> +		Const = mlds__code_addr_const(CodeAddr) }
> +	->
> +		io__write_char('('),
> +		{ IsCall = yes },
> +		mlds_output_code_addr(CodeAddr, IsCall),
> +		io__write_char(')')

I'm pretty sure the '(' and ')' aren't needed here, are they?

> Index: java_util.m
...
> +java_util__unary_prefix_op(unmktag, 		"/* unmaktag */ ").

s/mak/mk/

> +java_util__unary_prefix_op(unmkbody,		"/* unmakbody */ ").

Likewise.

Otherwise this change looks fine.

Please post both a relative diff (e.g. using `interdiff -h')
and a new full diff when you've addressed these review comments.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list