[fpc-devel] New feature announcement: constant parameters for generics
Benito van der Zander
benito at benibela.de
Sun Apr 26 14:01:19 CEST 2020
Hi,
perhaps it could be used to merge specializations (if fpc cannot do that
on its own):
Like when you have a hashmap THashMap<Key,Value>, and need three
specializations:
THashMap<string, pointer>
THashMap<string, TObject>
THashMap<string, sizeint>
It is basically three times the same hashmap, but if fpc does not detect
that, it might generate three times the same assembly code, which waste
a lot of space.
But with constants it can be merged to TBaseHashMap<Key, ValueSize:
integer> and then you only have one map in the assembly code, and three
wrappers to remove the casting:
THashMap<string, pointer> = TBaseHashMap<string, sizeof(pointer) > =
TBaseHashMap<string, 8 >
THashMap<string, TObject> = TBaseHashMap<string, sizeof(TObject) > =
TBaseHashMap<string, 8 >
THashMap<string, sizeint> = TBaseHashMap<string, sizeof(sizeint) > =
TBaseHashMap<string, 8 >
Cheers,
Benito
On 26.04.20 11:48, Sven Barth via fpc-devel wrote:
> Am 26.04.2020 um 09:38 schrieb Michael Van Canneyt:
>>
>>
>> On Sun, 26 Apr 2020, Ryan Joseph via fpc-devel wrote:
>>
>>>
>>>
>>>> On Apr 26, 2020, at 5:13 AM, Sven Barth via fpc-devel
>>>> <fpc-devel at lists.freepascal.org> wrote:
>>>>
>>>> The Free Pascal team is happy to announce the addition of a new
>>>> language feature: constant parameters for generics.
>>>
>>> Excellent! Thanks for getting this merged. It was a long battle but
>>> it's finally over. ;)
>>
>> As the original author, can you say something about the intended use
>> of this feature ?
>>
>> Sven gave some examples, and they show how it works, but from his
>> examples I don't see the point
>> of this feature.
>
> Jeppe had provided a potential usecase on the core mailing list in
> October '18. His example is not useable as-is, but to give you an idea:
>
> === code begin ===
>
> program tgpio;
>
> {$mode objfpc}
> {$modeswitch advancedrecords}
>
> type
> generic TSomeMicroGPIO<const Base: PtrUInt> = record
> private
> procedure SetPin(aIndex: SizeInt; aEnable: Boolean); inline;
> function GetPin(aIndex: SizeInt): Boolean; inline;
> public
> property Pin[Index: SizeInt]: Boolean read GetPin write SetPin;
> end;
>
> procedure TSomeMicroGPIO.SetPin(aIndex: SizeInt; aEnable: Boolean);
> begin
> if aEnable then
> PLongWord(Base)[2] := PLongWord(Base)[2] or (1 shl aIndex)
> else
> PLongWord(Base)[2] := PLongWord(Base)[2] and not (1 shl aIndex);
> end;
>
> function TSomeMicroGPIO.GetPin(aIndex: SizeInt): Boolean;
> begin
> Result := (PLongWord(Base)[2] and (1 shl aIndex)) <> 0
> end;
>
> var
> GPIOA: specialize TSomeMicroGPIO<$8000F000>;
> GPIOB: specialize TSomeMicroGPIO<$8000F100>;
> GPIOC: specialize TSomeMicroGPIO<$8000F200>;
>
> begin
> GPIOA.Pin[2] := True;
> end.
>
> === code end ===
>
> As the compiler can inline all this, the writing of maintainable,
> hardware agnostic frameworks for embedded controllers becomes easier.
>
> In general I agree with you that the use of constants as generic
> parameters is less wide. But there cases where one might want them.
>
> A further example could be to determine the size of a hash table:
> Determining that at compile time instead of runtime might allow for
> better code. At the same time the user of that code would still be
> able to influence it.
>
> In the bug report there was a further example by Akira1364. At its
> core it's about static arrays again, but it shows what can be done
> with this:
>
> === code begin ===
>
> program ConstMatrixExampleObjFPC;
>
> {$mode ObjFPC}
> {$modeswitch AdvancedRecords}
>
> type
> String3 = String[3];
>
> generic TRawMatrix<T; const N: SizeUInt> = array[0..N-1] of
> array[0..N-1] of T;
>
> generic TMatrix<T; const N: SizeUInt> = record
> private type
> ArrayType = specialize TRawMatrix<T, N>;
> private
> Data: ArrayType;
> public
> class operator :=(constref Arr: ArrayType): TMatrix; inline;
> procedure Display;
> end;
>
> class operator TMatrix.:=(constref Arr: ArrayType): TMatrix;
> begin
> Result.Data := Arr;
> end;
>
> procedure TMatrix.Display;
> var I, J: SizeInt;
> begin
> WriteLn('[');
> for I := 0 to N - 1 do begin
> Write(' [');
> for J := 0 to N - 2 do
> Write(Data[I, J], ', ');
> Write(Data[I, N - 1]);
> Writeln('] ');
> end;
> Write(']');
> end;
>
> const RawMat: specialize TRawMatrix<String3, 4> = (
> ('AAA', 'BBB', 'CCC', 'DDD'),
> ('EEE', 'FFF', 'GGG', 'HHH'),
> ('III', 'JJJ', 'KKK', 'LLL'),
> ('MMM', 'NNN', 'OOO', 'PPP')
> );
>
> var Mat: specialize TMatrix<String3, 4>;
>
> begin
> Mat := RawMat;
> Mat.Display();
> end.
>
> === code end ===
>
> I'm sure the future will show more potential examples. Or one could
> look at C++ examples that allow constants as well.
>
> Regards,
> Sven
> _______________________________________________
> fpc-devel maillist - fpc-devel at lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20200426/3c854b31/attachment.html>
More information about the fpc-devel
mailing list