[m-dev.] generating boxed version of special pred

Peter Ross pro at missioncriticalit.com
Sun Nov 30 00:27:18 AEDT 2003


The attached code highlights a bug on the IL backend.

It should generate
$ ./equality_pred_which_requires_boxing
float (boxed): true
float (unboxed): true
foreign_type (boxed): true
foreign_type (unboxed): true

but it generates 

$ ./equality_pred_which_requires_boxing
float (boxed): false
float (unboxed): true
foreign_type (boxed): false
foreign_type (unboxed): true

The problem is that when we are generating the RTTI for a value type
(builtin or defined using a foreign_type) we generate the unification
predicate using the unboxed types.

However when we call this unification predicate from the generic
unification predicate the arguments are boxed and so we get the wrong
behaviour.

What needs to happen is that we need to generate two versions of the
special pred, one with the boxed arguments and one without.  The only
problem is that I am not sure how and where to do this?  I looked at
doing it in rtti_to_mlds.m but I found it really difficult to do, so I
was hoping someone can give me some advice on the best way to do this.
-------------- next part --------------
% equality_pred_which_requires_boxing
%
% Check that the unification predicate we generate handles the case where
% the arguments are boxed and unboxed correctly.

:- module equality_pred_which_requires_boxing.

:- interface.

:- import_module io.

:- pred main(io::di, io::uo) is det.

:- implementation.

:- type type_which_needs_boxing.
:- pragma foreign_type(c, type_which_needs_boxing, "double")
		where equality is unify_ft.
:- pragma foreign_type(il, type_which_needs_boxing,
		"valuetype [mscorlib]System.Double") where equality is unify_ft.

main(!IO) :-
	A = float_a,
	B = float_b,
	unify("float (boxed)", A, B, !IO),
	( A = B ->
		io__write_string("float (unboxed): true\n", !IO)
	;
		io__write_string("float (unboxed): false\n", !IO)
	),
	X = create(float_a),
	Y = create(float_b),
	unify("foreign_type (boxed)", X, Y, !IO),
	( X = Y ->
		io__write_string("foreign_type (unboxed): true\n", !IO)
	;
		io__write_string("foreign_type (unboxed): false\n", !IO)
	).

	% Here we pass in a generic type, so if needed the input
	% arguments will have been boxed.  We then test if the
	% unification pred handles this correctly.
:- pred unify(string::in, T::in, T::in, io::di, io::uo) is det.
unify(S, X, Y, !IO) :-
	io__write_string(S, !IO),
	( X = Y ->
		io__write_string(": true\n", !IO)
	;
		io__write_string(": false\n", !IO)
	).

:- func create(float) = type_which_needs_boxing.
:- pragma foreign_proc("C", create(X::in) = (Y::out), [promise_pure], "
	Y = X;
").
:- pragma foreign_proc("C#", create(X::in) = (Y::out), [promise_pure], "
	Y = X;
").

:- pred unify_ft(type_which_needs_boxing::in, type_which_needs_boxing::in)
		is semidet.
:- pragma foreign_proc("C", unify_ft(X::in, Y::in), [promise_pure], "
	SUCCESS_INDICATOR = (X == Y);
").
:- pragma foreign_proc("C#", unify_ft(X::in, Y::in), [promise_pure], "
	SUCCESS_INDICATOR = (X == Y);
").

:- pragma no_inline(float_a/0).
:- func float_a = float.
float_a = 1.0.

:- pragma no_inline(float_b/0).
:- func float_b = float.
float_b = 1.0.


More information about the developers mailing list