[fpc-devel] Packages, Generics
Willibald Krenn
Willibald.Krenn at gmx.at
Sun Sep 12 03:59:17 CEST 2010
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
More information about the fpc-devel
mailing list