Hi!

Today I was thinking about fpc packages (whenever I am using this word, I mean Delphi-style-DLL-packages) and what difficulties might arise when implementing them. In my opinion, doing packages for D6-like Pascal should not be conceptually hard. It'll be more of a technical challenge to fiddle with the compiler internals.

However, since FPC supports more then the "simple" D6 language, I had a look at generics in particular. First, let me say that I am really glad to see this feature in FPC. However, I have to say that generics are NOT equivalent to C++ templates and should not be. (I strongly dislike the specialize keyword, btw., even though it makes the process of 'instantiating' the 'template' more apparent.) So, generics are _not_ pre-processor style macros - generic types are proper types. Let me explain.

Normally, a generic type can be statically checked by the compiler on it's own. You do not need to specialize it. The reason is simple: for most of the time, you could think of a generic type parameter as a variable with the type 'class of X' (which Pascal already supports). With the content of this variable you can do everything that is described in the public interface of its type. Nothing more, nothing less. For generic classes, this means that the compiler is able to check the correctness of the use of a value with a generic type without the need for specialization. Here is a catch: Pascal has quite a lot of types that are not classes. And this makes things a bit uncomfortable.

I would say that it is (almost) impossible to do packages in a sane way if we allow all sorts of operations on 'generically typed' values: If someone defines such a generic class, the compiler will need to pre-generate all possible type specializations of that class for the package file. Thereby 'all possible instantiations' means one for each non-oo type and at least one for all the object types (and possible combinations). Still worse, this would even break the 'one-implementation for all classes thing', because different classes could provide a method with the same name... (which would end up at different places in memory).

I don't know how Delphi solves these issues (w. regards to packages) but I think the one way to deal with this is to restrict the operations that can be done with values of generic types so that these operations match the type-information of the generic type parameters (e.g., generic A = class <T1 :Ordinal...> ...).

As said, all the class/interface types are no problem - they probably just need one specialization. Primitive types are basically grouped in Ordinals, Reals, Characters, Structures, Pointers, Functions. Each group comes with a set of operations that is valid and quite a lot of them end up being passed around as pointers. Refcounting aside, a common operation allowed on all types would be the assignment. This is enough for simple generic containers. Hence, if no other operation is needed, one common specialization could do. (Refcounting issue would still need to be solved, though.) If the developer needs more advanced operations, he/she has to narrow down the type that is allowed for specialization: Oridnal, or Real, or some TMyClass... . You get the basic idea. The more one restricts the generic parameter, the more one is allowed to do with values of that type. Which is the big difference to C++ templates, and the way generics should work.

So I am of the opinion that 'real' generics would make packages possible: Yes, generated code might be less efficient (int64 implementation for all signed ordinals), or there might be code duplication (for each ordinal type one implementation), but things would work. With the current implementation of generics packages are a no-go, I am afraid.


Cheers,
 Willi


_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to