Recent

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

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 635
Re: A suggestion for a new FPC feature
« Reply #15 on: June 24, 2019, 05:09:13 pm »
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.

Interesting. That does sound very Microsoft. I would strongly prefer not to have something like that in fpc.

lucamar

  • Hero Member
  • *****
  • Posts: 2025
Re: A suggestion for a new FPC feature
« Reply #16 on: June 24, 2019, 07:25:30 pm »
Interesting. That does sound very Microsoft. I would strongly prefer not to have something like that in fpc.

But you do have something like that in Pascal:
Code: Pascal  [Select]
  1. TVariableRecord = record
  2.   Size: Integer;
  3.   Data: array [0..0] of byte;
  4. end;
:o
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 #17 on: June 24, 2019, 07:41:00 pm »
And how do I put data in Data? SetLength doesn't work.

I don't really believe it.

440bx

  • Hero Member
  • *****
  • Posts: 1132
Re: A suggestion for a new FPC feature
« Reply #18 on: June 24, 2019, 07:50:21 pm »
Interesting. That does sound very Microsoft. I would strongly prefer not to have something like that in fpc.
Microsoft isn't the only one who has used that "feature".  It's not what could be characterized as common but, it isn't really rare either.   

It's a lot of "fun" when not only the field size varies but the semantics of the field - including its data type - vary depending on the value of some other variable in the structure/record.   Basically a record whose variant is "squeezed" to fit each type.

It's more something of a C programmer's thing than a Microsoft thing.

Programmers always find ways to abuse a feature. <chuckle>  I suspect that's what's made the C language popular.

Going back to the topic of the thread, removing the restriction that a variant must be the last field in a record and allowing multiple variants in a record would really ease porting C data structures to Pascal.  We live in a C world whether we like it or not.

ETA:

And how do I put data in Data? SetLength doesn't work.

I don't really believe it.
you load data in that field the same way you load data into an array (the field is an array), you're simply not respecting the array bounds (whatever they may be) and, since you are ignoring the declared array bounds, you need to either manually, set the count of elements or the size in bytes, into some variable dedicated to hold it for the structure to be usable.

Believe or not... and it's not Ripley's, it's Pascal (and C, C++ and quite a few other languages that implement that "trick".)
« Last Edit: June 24, 2019, 07:58:25 pm by 440bx »
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 #19 on: June 24, 2019, 07:58:10 pm »
So, you malloc() a buffer, memcpy() the record into it, and then manage everything yourself? Like increasing the pointer to the right location?

You don't need the record for that. It has no purpose.

Edit: and make sure to turn off any range or bounds checking. Yes, C. Not Pascal.
« Last Edit: June 24, 2019, 08:00:45 pm by SymbolicFrank »

440bx

  • Hero Member
  • *****
  • Posts: 1132
Re: A suggestion for a new FPC feature
« Reply #20 on: June 24, 2019, 08:09:02 pm »
So, you malloc() a buffer, memcpy() the record into it, and then manage everything yourself? Like increasing the pointer to the right location?

You don't need the record for that. It has no purpose.
You're getting the idea... it is almost always used with dynamically allocated memory.  It definitely has a purpose, when the size of the array can vary a significant amount and the program needs to keep track of many such records, it is very useful.

For instance, if you write a text editor with an "undo" feature (good feature to have in a text editor), you can have the fixed part of the record describe the memory block it applies to, its sequence and whatever should be put back when the "undo" function is carried out (that part obviously varies in size.) Having every potential undo action neatly packaged in its own variable length record is a much better solution than keeping a pointer to the undo data in the record (the reason is because, using a pointer to another block means there could be a very significant amount of fragmentation.)

Anytime you want to lessen memory fragmentation, records of that kind are good candidates.
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 #21 on: June 24, 2019, 08:28:36 pm »
If you want to program like that, I would suggest using assembler or C.

lucamar

  • Hero Member
  • *****
  • Posts: 2025
Re: A suggestion for a new FPC feature
« Reply #22 on: June 24, 2019, 08:55:48 pm »
If you want to program like that, I would suggest using assembler or C.

It is not usually a question of "want" but of "need". As a Pascal programmer I love having everytihng as neat and tidy and elegant as possible. But sometimes the real world  insists on intruding with these frankly outrageous demands and, isn't it nice that if you need it you have this kind of features available? :)
« Last Edit: June 24, 2019, 09:00:45 pm by lucamar »
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 #23 on: June 25, 2019, 01:43:29 am »
No. I don't agree. There are always many good ways to do something.

Every project I do is custom and completely different from all my previous ones. I'll adjust and use what the others that cannot have to use.

It's not that I didn't try other things than Object Pascal, most of the time I use something else. I like Object Pascal because it is the most dependable. It won't try to get me to shoot in my own foot. It still works 10 years later.

If you're young, you try to outsmart the others by coming up with border cases that are hard to understand, but work. If you become older, you want things to be understandable.

And not in the first place for me. I'm smart enough to figure it out. But for everyone else.

lucamar

  • Hero Member
  • *****
  • Posts: 2025
Re: A suggestion for a new FPC feature
« Reply #24 on: June 25, 2019, 05:01:57 am »
If you're young, you try to outsmart the others by coming up with border cases that are hard to understand, but work. If you become older, you want things to be understandable.

I'm not so young as I used to be and I don't fell the need to outsmart anybody. Just to write the best code I can, with all it means in terms of speed, accuracy and maintainability.

But sometimes those border cases come to you, whether you like them or not, and the best solution one can find is not exactly "by the book". In those, admitedly few, cases it's good that the language, and the compiler, you're using can cope with your solution.

Yes, there are always many ways to do something. The problem really is deciding which is the "good" one. And sometimes the "good" one is not the "easy, easily undertood" one.

In the cases I were referring to? You either "cheat" by ignoring array limits or start handling pointers like mad. Frankly, I prefer to "cheat" with the array and let pointers and pointer math for when they are really needed. And, of course, comment in the source what I'm doing and why.

But we'll have to agree to disagree, I fear.
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.

trev

  • Full Member
  • ***
  • Posts: 214
  • Former Delphi 7 and Delphi 10.2 User
Re: A suggestion for a new FPC feature
« Reply #25 on: June 25, 2019, 06:42:54 am »
FWIW, as an old and retired C programmer I agree with lucamar. Nice to have, maybe not essential.
o Lazarus v2.1.0 r61775, FPC v3.3.1 r42640, macOS 10.14.6 (with sup update), Xcode 10.3
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.0 (Parallels VM)
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 18.04 (Parallels VM)

PascalDragon

  • Hero Member
  • *****
  • Posts: 636
  • Compiler Developer
Re: A suggestion for a new FPC feature
« Reply #26 on: June 25, 2019, 09:20:48 am »
If you want to program like that, I would suggest using assembler or C.
This has nothing to do with wanting to program like that, but needing to program like that, because such constructs are required to interact with the Windows API.

So, you malloc() a buffer, memcpy() the record into it, and then manage everything yourself? Like increasing the pointer to the right location?

You don't need the record for that. It has no purpose.
That's not how it usually works.

Let's take the example of POWERBROADCAST_SETTING given above. Assume there exists the following function (don't know right now how the real one is defined, but it's enough for the example):
Code: Pascal  [Select]
  1. function GetPowerBroadcastSetting(aSetting: PPOWERBROADCAST_SETTING; out aLen: DWORD): BOOL;
You then typically use it like this:
Code: Pascal  [Select]
  1. var
  2.   setting: PPOWERBROADCAST_SETTING;
  3.   i, len: DWORD;
  4. begin
  5.   if not GetPowerBroadcastSetting(Nil, len) then
  6.     Exit;
  7.   setting := PPOWERBROADCAST_SETTING(GetMem(len));
  8.   if not GetPowerBroadcastSetting(setting, len) then begin
  9.     FreeMem(setting);
  10.     Exit;
  11.   end;
  12.   for i := 0 to setting^.DataLength - 1 do
  13.     Write(IntToHex(setting^.Data[i], 2), ' ');
  14. end.
This is just an example, but that's essentially how such constructs are used.

Don't forget that a Pascal program isn't isolated by itself, but interacts with the surrounding operating system and thus it needs to interact with the APIs of that (and it's much easier to simply point someone to MSDN than to explain and let them use the C examples then having to explain how that structure needs to be used compared to that other one).

440bx

  • Hero Member
  • *****
  • Posts: 1132
Re: A suggestion for a new FPC feature
« Reply #27 on: June 25, 2019, 09:49:43 am »
First, I apologize for the late reply.  Somehow I missed -- some of -- the replies in this thread...

@Serge,

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?
Personally, I believe the union/variant names should always be required.  I am not fond of unnamed/anonymous unions.  What you suggested looks good to me, of course, I would rather see more descriptive names being used for the variants but, as we all know, no compiler can enforce that. ;)


ETA:

Don't forget that a Pascal program isn't isolated by itself, but interacts with the surrounding operating system and thus it needs to interact with the APIs
That's what it really is all about. 
« Last Edit: June 25, 2019, 10:30:04 am by 440bx »
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 8967
Re: A suggestion for a new FPC feature
« Reply #28 on: June 25, 2019, 10:47:03 am »
First, I apologize for the late reply.  Somehow I missed -- some of -- the replies in this thread...

@Serge,

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?
Personally, I believe the union/variant names should always be required.  I am not fond of unnamed/anonymous unions.  What you suggested looks good to me, of course, I would rather see more descriptive names being used for the variants but, as we all know, no compiler can enforce that. ;)


ETA:

Don't forget that a Pascal program isn't isolated by itself, but interacts with the surrounding operating system and thus it needs to interact with the APIs
That's what it really is all about.

That's more or less what I meant.
You can expand this with a liitle macro, so the "union" becomes quite understandable:
Code: Pascal  [Select]
  1. {$mode objfpc}{$macro on}{$Define union :=}
  2. type
  3.   TRec = record
  4.     DummyName1: record
  5.       union case Byte of
  6.         0: (FieldA: Byte);
  7.         1: (OrFieldB: longword);
  8.       end;
  9.     DummyName2: record
  10.       union case Byte of
  11.         0: (FieldC: longint);
  12.         1: (OrFieldD: Byte);
  13.       end;
  14.   end;
  15. begin
  16. end.

Most people that want to use threading should learn to patch their jeans first: use a needle.

440bx

  • Hero Member
  • *****
  • Posts: 1132
Re: A suggestion for a new FPC feature
« Reply #29 on: June 25, 2019, 12:07:27 pm »
Code: Pascal  [Select]
  1. {$mode objfpc}{$macro on}{$Define union :=}
  2. type
  3.   TRec = record
  4.     DummyName1: record
  5.       union case Byte of
  6.         0: (FieldA: Byte);
  7.         1: (OrFieldB: longword);
  8.       end;
  9.     DummyName2: record
  10.       union case Byte of
  11.         0: (FieldC: longint);
  12.         1: (OrFieldD: Byte);
  13.       end;
  14.   end;
  15. begin
  16. end.

That looks good... another possibility that comes to mind would be to directly replace "record" with "union".  Using your example, the result would look like this:
Code: Pascal  [Select]
  1. type
  2.   TRec = record
  3.     DummyName1: union
  4.       case Byte of
  5.         0: (FieldA: Byte);
  6.         1: (OrFieldB: longword);
  7.       end;
  8.     DummyName2: union
  9.       case Byte of
  10.         0: (FieldC: longint);
  11.         1: (OrFieldD: Byte);
  12.       end;
  13.   end;
  14. begin
  15. end.
Of course, that presumes a new "union" keyword would be added to the language.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.