[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