[fpc-pascal] Constants in generics
Sven Barth
pascaldragon at googlemail.com
Sun Nov 25 18:09:37 CET 2018
Am 14.11.2018 um 03:25 schrieb Ryan Joseph:
> I think I have this done except for cleanup. Here’s the status:
>
> - Integer,string,real,set and nil constant for parameters.
> - Consts can have type restrictions which correspond to the above types.
> - Const can be assigned to from generic const params.
> - PPU loading.
>
> Technical compiler issues:
>
> - I couldn’t figure out how to extend PPU loading for a ttypesym subclass so I put 2 fields into ttypesym. Those are probably best moved to a subclass later.
> - We may need new error messages but I just left place holders in for now.
>
> https://github.com/genericptr/freepascal/tree/generic_constants
In contrast to the multiple helper ones I have much more to complain
about here:
- your pretty name is wrong; the pretty name for a specialization with
constants should be "TSomeGeneric<TSomeType, 42>", not
"TSomeGeneric<SomeUnit.TSomeType, System.LongInt#42>" as it would be now
- remove those tgenericparasym and tgeneric_*_parasym types; use simply
tconstsym instead of ttypesym for const parameters, other code will have
to check that correctly
- even though you'll remove is_const and const_type from ttypesym again
due to the above it's wrong to use putsmallset/getsmallset for an enum;
use putbyte/getbyte or one of the "larger" put*/get* functions depending
on the number of entries contained in the enum (Note: not a runtime
check, just pick the correct one at compile time)
- get rid of tscannerfile.parsing_generic_type; it's not only at the
wrong location (the name "parsing_generic_type" should already tell you
that it has no place inside the *scanner*), but it's also used to solve
something in a completely wrong way: you must *not* use
current_structdef for the generic parameters as the only valid parameter
list inside parse_generic_specialization_types_internal *is* paradeflist
and genericdef.genericparas. If there is still a problem then you need
to handle that differently (Note: also don't Exit from
parse_generic_specialization_type_internal, because the idea is that all
incompatibilities are shown at once, so use Continue to check the next
parameter)
- remove the check for m_objfpc; yes it won't work with inline
specializations in mode Delphi for now, but it can still be used for
specializations in type or var sections; also one idea for an
improvement I have for parsing inline specializations in mode Delphi
would be if the compiler knows that the symbol left of the "<" can only
be a generic (cause let's be honest: in most code types aren't
overloaded with variables/constants and more often than not types begin
with "T", so they shouldn't conflict with the names of more local
variables/constants/fields either)
Also thinking about the feature a bit it would be better to enforce the
type of the constant during the generic's declaration. After all I can
do different things with a string const, an ordinal const or a set
const. So it would be better to use "const <NAME>: <TYPE>" where type
can be any type that results in a tconstsym. After all the type of the
constant inside the generic is usually fixed and those few cases were a
variadic constant would be necessary could be handled by "TMyGeneric<T;
const N: T>" (which would not work right now, but as we also need to
support "TMyGeneric<T; S: SomeIntf<T>>" due to Delphi compatibility that
would be handled by the same solution).
This way you can also get rid of the cconstundefined and you can create
a correct tconstsym right of the bat.
And as I had written for the helper extension: add tests. A feature like
this will need many tests (you can use "tgenconst" as test name prefix).
Also don't forget to test this with generic routines.
Don't forget to check the code formatting as well, I saw a few locations
where you had spaces where they don't belong. ;)
Regards,
Sven
More information about the fpc-pascal
mailing list