Forum > Suggestions

Proposal: unions as a new type and arrays with number of elements

(1/24) > >>

flowCRANE:
Lately I've been working with records that should have a variable-type content and it drives me crazy when I have to declare such structures. Can Free Pascal finally make readable unions instead of forcing the use of variant-record-abomination? Their syntax is so idiotic that it is hard to believe that someone who has seen Pascal at least once in their life was responsible for their design.

Finally, I suggest that unions be implemented legibly, so that they can be conveniently declared and matched to the structures used in the C language. There must be a normal, Pascal syntax, the ability to create named fields (of any type) and the ability to declare fields under a field that is a union (which is impossible with variant-records, without declaring additional structures).

Suggested syntax:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFoo = union    // union fields  end; 
The same as in the case of records. All fields of such a union occupy the same memory area. For example:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFoo = union    Letter: Char;  // TFoo.Letter    Code:   UInt8; // TFoo.Code  end; 
The size of such a union is one byte. Unions can have fields of simple types, but also arrays, structures, and other unions. A more complex example to illustrate nesting:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFoo = union    Chunks: union                           // TFoo.Chunks      Number: UInt32;                       // TFoo.Chunks.Number      Words:  array [0 .. 1] of UInt16;     // TFoo.Chunks.Words      Bytes:  union                         // TFoo.Chunks.Bytes        Unsigned: array [0 .. 3] of UInt8;  // TFoo.Chunks.Bytes.Unsigned        Signed:   array [0 .. 3] of Int8;   // TFoo.Chunks.Bytes.Signed      end;    end;    Other: UInt32;                          // TFoo.Other  end; 
The size of TFoo union is 8 bytes — Chunks occupies 4 bytes, Other occupies 4 bytes (is below the union). This syntax is not only readable and consistent with the syntax of other Pascal blocks (explicit termination of the union body, including a nested union), but also allows fields to be declared as unions, and subsequent fields (including structures and unions) below them. You don't need to declare complex field types outside of the main union body. Thus, even very complex unions containing many fields, including nested unions and structures, can be declared as a single and readable data type.

I am asking FPC developers to consider implementing support for such unions to say goodbye to stupid variant-records once and for all. By the way — I don't know why, but the snippet syntax highlighter recognizes the word union and colors it like Pascal's keywords. Good sign. 8)

marcov:
It is extremely unlikely to reimplement working features for stylistic reasons only. 

And even if, I would frown on language proposals with examples that even don't show the intended method of having multiple fields per union case, a feat the "horrible" syntax DOES do.

Similarly, to map onto C you need anonymous unions (which your example also doesn't showcase), as the biggest problem of the current Pascal way is that nesting requires changing the reference syntax.

If some change would be done, I'd bet it be a minimal change proposal that allowed anonymous nesting (union without field  name) to achieve closer mapping with the current syntax, not putting a complete new syntax next to it.

TRon:
I feel and share your pain furious programmer. Especially the part that you can't (easily) add another field after the variant part makes it very difficult to make concise definitions for supporting both big and small endian structures.

I asked the same questions (some eons ago) and got the response that it can be solved with existing constructs (which is true). That basically means (to my understanding) if it does not add something new other then so called sugar coating then there is not really a incentive to add such a feature.

I can respect that, though this particular issue sometimes feels like using a broomstick to get yourself form point a to b. Unless you have some magic then that is fine, otherwise a bus (or even a bicycle or having good footwear) would be the better option  :D

flowCRANE:

--- Quote from: marcov on April 27, 2023, 05:48:21 pm ---It is extremely unlikely to reimplement working features for stylistic reasons only.
--- End quote ---

As you know, you can't currently declare fields in a variant-record, under a common part, so it is not for stylistic reasons only.


--- Quote ---And even if, I would frown on language proposals with examples that even don't show the intended method of having multiple fields per union case, a feat the "horrible" syntax DOES do.
--- End quote ---

I didn't give all possible examples, because it's rather redundant and you can guess some things. Yes, declaring anonymous fields as nested unions is necessary and not unusual.


--- Quote ---If some change would be done, I'd bet it be a minimal change proposal that allowed anonymous nesting (union without field  name) to achieve closer mapping with the current syntax, not putting a complete new syntax next to it.
--- End quote ---

It's not about being able to declare anonymous fields, it's about being able to declare normal unions as single data structures, with the ability to declare fields under common parts, without having to declare completely separate data types outside the union. And for a better syntax and higher readability, because the current one is a joke.

korba812:

--- Quote from: furious programming on April 27, 2023, 05:14:41 pm ---
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFoo = union    Chunks: union                           // TFoo.Chunks      Number: UInt32;                       // TFoo.Chunks.Number      Words:  array [0 .. 1] of UInt16;     // TFoo.Chunks.Words      Bytes:  union                         // TFoo.Chunks.Bytes        Unsigned: array [0 .. 3] of UInt8;  // TFoo.Chunks.Bytes.Unsigned        Signed:   array [0 .. 3] of Int8;   // TFoo.Chunks.Bytes.Signed      end;    end;    Other: UInt32;                          // TFoo.Other  end; 
The size of TFoo union is 8 bytes — Chunks occupies 4 bytes, Other occupies 4 bytes (is below the union).

--- End quote ---

Maybe I don't fully understand your proposal, but shouldn't SizeOf(TFoo) be 4? If I understand correctly, the pascal equivalent is:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  TFoo = record    case Boolean of    True: (Chunks: record                              // TFoo.Chunks      case Byte of      0: (Number: UInt32);                             // TFoo.Chunks.Number      1: (Words:  array [0 .. 1] of UInt16);           // TFoo.Chunks.Words      2: (Bytes:  record                               // TFoo.Chunks.Bytes        case Boolean of          True: (Unsigned: array [0 .. 3] of UInt8);   // TFoo.Chunks.Bytes.Unsigned          False: (Signed:   array [0 .. 3] of Int8);   // TFoo.Chunks.Bytes.Signed        end;);      end;);    False: (Other: UInt32;)                            // TFoo.Other  end; 

Navigation

[0] Message Index

[#] Next page

Go to full version