Procedural Types in Oxygene


(Matt Robertson) #1

I am trying to use the below Pascal code in Oxygene, but it is failing to compile. The idea is to have a base generic class OTArrayList, from which a number of specialized classes descend (Boolean, LongInt, Object, etc). TEqualFunction allows for each child class to determine equalness of two elements (in the case of Boolean, with a simple operator).

A few minor syntactical changes are required, as reflected in the Oxygene code in the second code block below. (Note, this is obviously a reduced version of the actual code - this should contain everything relevant to the issue, though).

Pascal:

TYPE
	GENERIC OTArrayList<T> = OBJECT(TObject)
		TYPE
			TEqualFunction = FUNCTION (item1, item2: T;
										options: LONGINT): BOOLEAN;
		VAR
			fEqualFunc: TEqualFunction;
			
		CONSTRUCTOR Create (equalFunc: TEqualFunction);
	END;

	TBooleanArray = OBJECT(specialize OTArrayList<BOOLEAN>)
		CONSTRUCTOR Create;
	END;

...

CONSTRUCTOR OTArrayList.Create (equalFunc: TEqualFunction);

BEGIN
	fEqualFunc := equalFunc;
END;

{--- TBooleanArray ---}

FUNCTION OTEqualBools (item1, item2: BOOLEAN; options: LONGINT): BOOLEAN; INLINE;

BEGIN
	OTEqualBools := (item1 = item2);
END;


CONSTRUCTOR TBooleanArray.Create;

BEGIN
	INHERITED Create(OTEqualBools);
END;

Oxygene:

TYPE
	OTArrayList<T> = PUBLIC CLASS(TObject)
		TYPE
			TEqualFunction = FUNCTION (item1, item2: T;
										options: LONGINT): BOOLEAN;
		VAR
			fEqualFunc: TEqualFunction;
			
			CONSTRUCTOR (equalFunc: TEqualFunction);
	END;

	TBooleanArray = PUBLIC CLASS(OTArrayList<BOOLEAN>)
		CONSTRUCTOR;
	END;

...

CONSTRUCTOR OTArrayList<T> (equalFunc: TEqualFunction);

BEGIN
	fEqualFunc := equalFunc;
END;


{--- TBooleanArray ---}

FUNCTION OTEqualBools (item1, item2: BOOLEAN; options: LONGINT): BOOLEAN;

BEGIN
	EXIT (item1 = item2);
END;


CONSTRUCTOR TBooleanArray;

BEGIN
	INHERITED Create(OTEqualBools);
END;

Attempting to compile the Oxygene code gives this error:
(E397) No overloaded global function “OTEqualBools” with 0 parameters in namespace…

Does Oxygene allow procedural types like this? If not, is there a way to accomplish this using an anonymous function or another approach?


(Carlo Kok) #2

Yes it allows it except that you shoulfd use:

INHERITED Create(@OTEqualBools);

instead
of
INHERITED Create(OTEqualBools);


(Matt Robertson) #3

Thanks Carlo. I thought that originally but get this error:

(E407) No overloaded constructor with these parameters for type “OTArrayList”, best matching overload is "constructor (equalFunc: OTArrayList.TEqualFunction)"

Not sure what I’m missing here…


(Carlo Kok) #4

do you have a more complete example? The one I tried didn’t fulyl compile.


(Matt Robertson) #5

Sure. Only a couple minor changes from what I posted above, but this exact code compiles on my machine if I change @OTEqualBools to NIL as noted in the code. As it stands, I get this compile error:

(E486) Parameter 1 is “<method pointer>”, should be “OTArrayList.TEqualFunction”, in call to constructor OTArrayList(equalFunc: OTArrayList.TEqualFunction)"

INTERFACE

	USES
		java.util;

{------------------ Data Array Types -----------------}

	TYPE
		OTArrayList<T> = PUBLIC CLASS(Object)
			TYPE
				TEqualFunction = FUNCTION (item1, item2: T;
											options: LONGINT): BOOLEAN;
			VAR
				fEqualFunc: TEqualFunction;
			
				CONSTRUCTOR (equalFunc: TEqualFunction);
		END;

		TBooleanArray = PUBLIC CLASS(OTArrayList<BOOLEAN>)
			CONSTRUCTOR;
		END;

IMPLEMENTATION

{------------------ Generic OTArrayList implementation -----------------}

	

	CONSTRUCTOR OTArrayList<T> (equalFunc: TEqualFunction);

	BEGIN
		fEqualFunc := equalFunc;
	END;


	{--- TBooleanArray ---}

	FUNCTION OTEqualBools (item1, item2: BOOLEAN; options: LONGINT): BOOLEAN;

	BEGIN
		EXIT (item1 = item2);
	END;


	CONSTRUCTOR TBooleanArray;

	BEGIN
		INHERITED Create(@OTEqualBools); { Note: Changing the parameter to NIL compiles succesfully }
	END;
END.

(Matt Robertson) #6

I should also note, I’m compiling with RemObjects Elements 9.3.103.2211. I’ve tried updating, but attempting to compile my project on the latest compiler version gives me over 10,000 compile errors. I’m planning to work through that soon so I can update to the latest compiler, but for now 9.3.103.2211 is working for us.


(Carlo Kok) #7

Ah yes. the problem stems from how Java does generics.

type
  TEqualFunction = FUNCTION (item1, item2: T;options: LONGINT): BOOLEAN;

OTArrayList<BOOLEAN>

FUNCTION OTEqualBools (item1, item2: BOOLEAN; options: LONGINT): BOOLEAN;

In Java, generics are erased, which means that it has some compiler info that the parameters item, item2 are T, but for the runtime it’s Object.

What we do is when you pass Boolean, is that it really matches nullable Boolean, which is an object, not a value type, so it wants it as nullable boolean.

I’m going to log a bug to fix this. As a workaround you can use nullable boolean for now in the OTEqualsBool.


(RemObjects) #8

Thanks, logged as bugs://81535


(Matt Robertson) #9

Thanks for the workaround, it seems to be working correctly. Out of curiosity, does nullable signal for the compiler to treat the boolean as a java.lang.boolean object rather than as the boolean primitive?


(Carlo Kok) #10

Yes.

The only time we do this is inside generics of course (or if you actually type nullable Boolean)