Recent

Author Topic: A suggestion for a new FPC feature  (Read 5866 times)

440bx

  • Hero Member
  • *****
  • Posts: 1047
A suggestion for a new FPC feature
« on: June 23, 2019, 12:05:17 pm »
Hello,

Pascal/Delphi/FPC limit the declaration of "variant"(s) in records to be the last field in the record.

It would very nice if that limitation was removed thus allowing variants to appear anywhere and, in multiple places, in a record type.

It would simplify porting C data type definitions to FPC/Pascal and increase the expressive power of the language.

Just a wish upon a binary star....


using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Re: A suggestion for a new FPC feature
« Reply #1 on: June 23, 2019, 01:02:20 pm »
AFAIK, in both Pascal and C/C++ records (structs) are fixed length. If you want to add something that isn't (like a string), you have to store that outside the record and add a pointer.

Thaddy

  • Hero Member
  • *****
  • Posts: 8458
Re: A suggestion for a new FPC feature
« Reply #2 on: June 23, 2019, 01:33:46 pm »
That's not correct. Variant parts of records always have the size of its largest possible member.
I actually agree with such a feature, although you can work around it without reordering by pre-declaring sub records and use those as members of the final record  or nested variant parts.

Because the size of a variant record part is always known, it can't be too difficult to implement such a feature, although this is more like syntax sugar than absolute necessity.
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.

440bx

  • Hero Member
  • *****
  • Posts: 1047
Re: A suggestion for a new FPC feature
« Reply #3 on: June 23, 2019, 01:33:57 pm »
AFAIK, in both Pascal and C/C++ records (structs) are fixed length. If you want to add something that isn't (like a string), you have to store that outside the record and add a pointer.
They are fixed length only if their definition makes them that way.   They can vary in length if the programmer chooses to define them as variable.  Here is an example (from MSDN):
Code: Pascal  [Select]
  1. typedef struct {
  2.   GUID  PowerSetting;
  3.   DWORD DataLength;
  4.   UCHAR Data[1];
  5. } POWERBROADCAST_SETTING, *PPOWERBROADCAST_SETTING;
the size of the record varies depending on the size of the "Data" array which is specified in the field "DataLength".  Another example that comes to mind is the size of the IMAGE_LOAD_CONFIG_DIRECTORY32/64 in a PE file.  It varies depending on how many fields the compiler decided to use and its size is determined by the first field "Size".  Dumpbin seems to be the only PE dump utility that handles that structure correctly.

But, that really isn't a new feature, Pascal can do either of those already the same way it's done in C.

OTH, translating/converting a definition like:
Code: Pascal  [Select]
  1. typedef struct JOBOBJECT_NOTIFICATION_LIMIT_INFORMATION_2 {
  2.     DWORD64 IoReadBytesLimit;
  3.     DWORD64 IoWriteBytesLimit;
  4.     LARGE_INTEGER PerJobUserTimeLimit;
  5.     union {
  6.         DWORD64 JobHighMemoryLimit;
  7.         DWORD64 JobMemoryLimit;
  8.     } DUMMYUNIONNAME;
  9.  
  10.     union {
  11.         JOBOBJECT_RATE_CONTROL_TOLERANCE RateControlTolerance;
  12.         JOBOBJECT_RATE_CONTROL_TOLERANCE CpuRateControlTolerance;
  13.     } DUMMYUNIONNAME2;
  14.  
  15.     union {
  16.         JOBOBJECT_RATE_CONTROL_TOLERANCE_INTERVAL RateControlToleranceInterval;
  17.         JOBOBJECT_RATE_CONTROL_TOLERANCE_INTERVAL
  18.             CpuRateControlToleranceInterval;
  19.     } DUMMYUNIONNAME3;
  20.  
  21.     DWORD LimitFlags;
  22.     JOBOBJECT_RATE_CONTROL_TOLERANCE IoRateControlTolerance;
  23.     DWORD64 JobLowMemoryLimit;
  24.     JOBOBJECT_RATE_CONTROL_TOLERANCE_INTERVAL IoRateControlToleranceInterval;
  25.     JOBOBJECT_RATE_CONTROL_TOLERANCE NetRateControlTolerance;
  26.     JOBOBJECT_RATE_CONTROL_TOLERANCE_INTERVAL NetRateControlToleranceInterval;
  27. } JOBOBJECT_NOTIFICATION_LIMIT_INFORMATION_2;
  28.  
  29.  
to Pascal is tedious and cumbersome because Pascal only allows one variant part and it _must_ be last in the record definition.

Removing the limitation that variant parts can only occur once and last in a record definition would definitely simplify some data type definitions.






using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 8458
Re: A suggestion for a new FPC feature
« Reply #4 on: June 23, 2019, 01:38:21 pm »
read my previous reply, the crossed.
A variant record is fixed length based on largest member, just like a union.
But  can be type checked on all members, that's something different.

For that reason, your suggestion is sound.
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.

440bx

  • Hero Member
  • *****
  • Posts: 1047
Re: A suggestion for a new FPC feature
« Reply #5 on: June 23, 2019, 02:11:01 pm »
read my previous reply, the crossed.
A variant record is fixed length based on largest member, just like a union.
But  can be type checked on all members, that's something different.

For that reason, your suggestion is sound.
I noticed our posts crossed. I didn't reply at the time because I concur with what you said.

It's more than just syntactic sugar though.  Having that feature would make it much easier to write a general ".h to .pas" header translator because the translator wouldn't be faced with the necessity of having to generate an additional definition and a name for the union to use in the record declaration.

There are quite a few debugging structures that use multiple unions to cover type definitions, not to mention structures like:
Code: Pascal  [Select]
  1. typedef struct _D3DKMT_VIDMM_ESCAPE                        {
  2.     D3DKMT_VIDMMESCAPETYPE Type;
  3.     union
  4.     {
  5.         struct
  6.         {
  7.             union
  8.             {
  9.                 struct
  10.                 {
  11.                     ULONG ProbeAndLock : 1;
  12.                     ULONG SplitPoint : 1;
  13.                     ULONG NoDemotion : 1;
  14.                     ULONG SwizzlingAperture : 1;
  15.                     ULONG PagingPathLockSubRange : 1;
  16.                     ULONG PagingPathLockMinRange : 1;
  17.                     ULONG ComplexLock : 1;
  18.                     ULONG FailVARotation : 1;
  19.                     ULONG NoWriteCombined : 1;
  20.                     ULONG NoPrePatching : 1;
  21.                     ULONG AlwaysRepatch : 1;
  22.                     ULONG ExpectPreparationFailure : 1;
  23.                     ULONG FailUserModeVAMapping : 1;
  24. #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN8)
  25.                     ULONG NeverDiscardOfferedAllocation : 1;
  26.                     ULONG AlwaysDiscardOfferedAllocation : 1;
  27.                     ULONG Reserved : 17;
  28. #else
  29.                     ULONG Reserved : 19;
  30. #endif
  31.                 };
  32.                 ULONG Value;
  33.             } DUMMYUNIONNAME;
  34.         } SetFault;
  35.         struct
  36.         {
  37.             D3DKMT_HANDLE ResourceHandle;
  38.             D3DKMT_HANDLE AllocationHandle;
  39.             HANDLE hProcess;        // 0 to evict memory for the current process, otherwise it is a process handle from OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId).
  40.         } Evict;
  41.         struct
  42.         {
  43.             UINT64 NtHandle;           // Used by D3DKMT_VIDMMESCAPETYPE_EVICT_BY_NT_HANDLE
  44.         } EvictByNtHandle;
  45.         struct
  46.         {
  47.             union
  48.             {
  49.                 struct
  50.                 {
  51.                     UINT NumVads;
  52.                 } GetNumVads;
  53.                 D3DKMT_VAD_DESC GetVad;
  54.                 D3DKMT_VA_RANGE_DESC GetVadRange;
  55.                 D3DKMT_GET_GPUMMU_CAPS GetGpuMmuCaps;
  56.                 D3DKMT_GET_PTE  GetPte;
  57.                 D3DKMT_GET_SEGMENT_CAPS GetSegmentCaps;
  58.             } DUMMYUNIONNAME;
  59.             D3DKMT_VAD_ESCAPE_COMMAND Command;      // in
  60.             NTSTATUS    Status;                     // out
  61.         } GetVads;
  62.         struct
  63.         {
  64.             ULONGLONG   LocalMemoryBudget;
  65.             ULONGLONG   SystemMemoryBudget;
  66.         } SetBudget;
  67.         struct
  68.         {
  69.             HANDLE hProcess;
  70.             BOOL bAllowWakeOnSubmission;
  71.         } SuspendProcess;
  72.         struct
  73.         {
  74.             HANDLE hProcess;
  75.         } ResumeProcess;
  76.         struct
  77.         {
  78.             UINT64 NumBytesToTrim;
  79.         } GetBudget;
  80.         struct
  81.         {
  82.             ULONG MinTrimInterval; // In 100ns units
  83.             ULONG MaxTrimInterval; // In 100ns units
  84.             ULONG IdleTrimInterval; // In 100ns units
  85.         } SetTrimIntervals;
  86.         D3DKMT_EVICTION_CRITERIA EvictByCriteria;
  87.         struct
  88.         {
  89.             BOOL bFlush;
  90.         } Wake;
  91.         struct
  92.         {
  93.             D3DKMT_DEFRAG_ESCAPE_OPERATION  Operation;
  94.  
  95.             UINT                            SegmentId;
  96.  
  97.             ULONGLONG                       TotalCommitted;
  98.             ULONGLONG                       TotalFree;
  99.             ULONGLONG                       LargestGapBefore;
  100.             ULONGLONG                       LargestGapAfter;
  101.         } Defrag;
  102.     } DUMMYUNIONNAME;
  103. } D3DKMT_VIDMM_ESCAPE;
  104.  
and that still isn't as bad as it can get, add some bitfields in there and there is plenty of fun to be had translating that to Pascal, particularly to versions of Pascal that, unlike FPC, don't support bitfields.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

lucamar

  • Hero Member
  • *****
  • Posts: 1943
Re: A suggestion for a new FPC feature
« Reply #6 on: June 23, 2019, 05:04:22 pm »
I would like this feature too, if it had a clean syntax. I have missed it almost from my Pascal beginnings: implementing some of DOS structures (DPB, LoL, etc.) was a good eye-opener for this.


OT ... This will sound stupid and nitpicking but, please, use the correct "[code=whatever]" tags. Using "Pascal" highlighting for C code, for exampe, makes most code look like a comment, which (at least here) means decreased visibility.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Re: A suggestion for a new FPC feature
« Reply #7 on: June 23, 2019, 05:26:04 pm »
Ok, I should have added that arrays and unions reserve the space of the largest item. But they're still all the same size.

Code: Pascal  [Select]
  1. typedef struct {
  2.   GUID  PowerSetting;
  3.   DWORD DataLength;
  4.   UCHAR Data[1];
  5. } POWERBROADCAST_SETTING, *PPOWERBROADCAST_SETTING;

It stores a pointer to Data.

Yes, you can make variable-length "structures", but you have to store them in a different way. As a dynamic array, for example.

Almir.Bispo

  • Jr. Member
  • **
  • Posts: 76
  • CSV Comp DB is the Best NoSQL
    • CSV Comp DB (NoSQL)
Re: A suggestion for a new FPC feature
« Reply #8 on: June 23, 2019, 05:41:02 pm »
The variable length in structure in Pascal shall be not a feature,but a BUG.
Please forget it.

(Please don't let C programmers work in FPC !!)
CSV Comp DB Developer {Pascal Lover}

440bx

  • Hero Member
  • *****
  • Posts: 1047
Re: A suggestion for a new FPC feature
« Reply #9 on: June 23, 2019, 06:12:09 pm »
OT ... This will sound stupid and nitpicking but, please, use the correct "[code=whatever]" tags. Using "Pascal" highlighting for C code, for exampe, makes most code look like a comment, which (at least here) means decreased visibility.
I agree with you but, I don't see a "C" option in the list...  because of that, I picked Pascal.


Code: Pascal  [Select]
  1. typedef struct {
  2.   GUID  PowerSetting;
  3.   DWORD DataLength;
  4.   UCHAR Data[1];
  5. } POWERBROADCAST_SETTING, *PPOWERBROADCAST_SETTING;

It stores a pointer to Data.
No.  It doesn't store a pointer.  It stores the array of UCHAR directly in the structure.  The compiler doesn't know that there is (likely) more than 1 character stored in the last field which is the reason for the "DataLength" field.  That's the field that allows the programmer to use the correct array size at runtime.

The structure size varies but, the compiler sees it as a fixed size structure because it is being "lied" to by specifying [1] as the number of array elements.


The variable length in structure in Pascal shall be not a feature,but a BUG.
Please forget it.
Two things for you to realize: 1. that's not the feature I suggested.  2. variable length structures have long been available in Pascal (by lying to the compiler.)
Don't forget it.

(Please don't let C programmers work in FPC !!)
Don't worry, the majority of C programmers don't use FPC.  You're welcome.





using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 8458
Re: A suggestion for a new FPC feature
« Reply #10 on: June 23, 2019, 06:40:31 pm »
Don't worry, the majority of C programmers don't use FPC.  You're welcome.
A large majority of Pascal programmers are also proficient in C........ Certainly the old hands
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.

440bx

  • Hero Member
  • *****
  • Posts: 1047
Re: A suggestion for a new FPC feature
« Reply #11 on: June 23, 2019, 06:53:27 pm »
A large majority of Pascal programmers are also proficient in C........ Certainly the old hands
Yes, that is true. 

The thing about C programmers is that they are usually die-hards who won't use anything else unless it is strongly C "flavored".

Other programmers, such as Pascal programmers, usually get at least acquainted with the C language because it is very influential and because of that, it pays to be somewhat proficient in the language.

using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Kays

  • Full Member
  • ***
  • Posts: 170
  • Whasup!?
    • KaiBurghardt.de
Re: A suggestion for a new FPC feature
« Reply #12 on: June 24, 2019, 04:14:40 pm »
[…] allowing variants to appear anywhere and, in multiple places, in a record type. […]
Veto!

Putting the variant part at the end is the only sane conclusion. The year dot computers didn’t have a buttload of memory and worked considerably slower. The status quo is a good compromise between having bloated data structures (bad [if you allow it, you will have it]) and not having to mov data because the memory model has changed (good), as soon as the selected variant changes.
Yours Sincerely
Kai Burghardt

Thaddy

  • Hero Member
  • *****
  • Posts: 8458
Re: A suggestion for a new FPC feature
« Reply #13 on: June 24, 2019, 04:22:11 pm »
Putting the variant part at the end is the only sane conclusion.y model has changed (good), as soon as the selected variant changes.
No. not at all. size is known, There is no reason at all to not implement it. This is a very valid and serious request.
Would help to take some compiler classes..... O:-)
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.

ASerge

  • Hero Member
  • *****
  • Posts: 1352
Re: A suggestion for a new FPC feature
« Reply #14 on: June 24, 2019, 04:43:31 pm »
It would very nice if that limitation was removed thus allowing variants to appear anywhere and, in multiple places, in a record type.
If I understand you correctly, then comparing the code on C:
Code: C  [Select]
  1. typedef struct TRec {
  2.   union
  3.   {
  4.     byte FieldA;
  5.     byte OrFieldB;
  6.   }
  7.   union
  8.   {
  9.     byte FieldC;
  10.     byte OrFieldD;
  11.   }
  12. }
  13. //...
  14. TRec rec;
  15. //...
  16. rec.FieldA = 1;
  17. rec.FieldC = 2;
with the similar code on Pascal:
Code: Pascal  [Select]
  1. type
  2.   TRec = record
  3.     DummyName1: record
  4.       case Byte of
  5.         0: (FieldA: Byte);
  6.         1: (OrFieldB: Byte);
  7.       end;
  8.     DummyName2: record
  9.       case Byte of
  10.         0: (FieldC: Byte);
  11.         1: (OrFieldD: Byte);
  12.       end;
  13.   end;
  14. //...
  15. var
  16.   Rec: TRec;
  17. //...
  18.   Rec.DummyName1.FieldA := 1;
  19.   Rec.DummyName2.FieldC := 2;
you want to syntactically exclude the names DummyNameX?