[fpc-devel] New feature announcement: constant parameters for generics

Sven Barth pascaldragon at googlemail.com
Sun Apr 26 11:48:59 CEST 2020


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


More information about the fpc-devel mailing list