Recent

Author Topic: Proposal: Record Composition  (Read 3490 times)

Curt Carpenter

  • Sr. Member
  • ****
  • Posts: 342
Re: Proposal: Record Composition
« Reply #15 on: September 18, 2023, 05:59:27 pm »
...
So when you look at the manual, and it states that the operation for the opcode 0x02 is LD A -> (BC), writing:
Code: Pascal  [Select][+][-]
  1. RAMState[CPURegs.BC] := CPURegs.A;
is much more concise and easier to understand than having to go over a seperate hop:
Code: Pascal  [Select][+][-]
  1. MemState[CPURegs.BC.Reg16] := CPURegs.AF.Reg8[0];
It allows you to much closer follow the manual and having the code being easy to map onto these constructs.
...

You make your case very well.  But strictly as a matter or curiosity, when you do LD A -> (BC), does A go into B, or C, or perhaps both, or perhaps one or the other depending on whether the "BigEndian" switch is on or off?  And if A goes into B, is C left alone, or set to zero?

The programmer knows the answers having the manual ready to hand and probably memorized after long hours of work.  But the reader might not.  And that makes me wonder if there isn't a better way to represent the case (in general, not just in this one example)?

Warfley

  • Hero Member
  • *****
  • Posts: 1469
Re: Proposal: Record Composition
« Reply #16 on: September 18, 2023, 07:36:14 pm »
On another note: have you considered the field and record alignment options that the compiler offers ? (I would like to test myself but unfortunately my agenda is a bit crowded atm). (*)

fwiw I especially like the anonymous embedding as that is really a lacking feature.

(*) By that initially I meant the actual layout in memory. The language construct themselves can be added if not (properly) supported right now.
On a technical level this just adds a (hidden if unnamed) field to the record of that type you composite. So if you compsite another record the record field will be aligned as per alignment rules of the parent record ($PACKRECORDS, packed or bitpacked), while the elements of the child record are internally aligned according to the internal record packing:
Code: Pascal  [Select][+][-]
  1. {$PACKRECORDS C}
  2. TTest = record // Packed according to PACKRECORDS C
  3.   ...
  4.   using packed record // non aligned because of the "packed" keyword
  5.     ...
  6.   end;
  7.   ...
  8. end;

So from that perspective it does not change anything about the packing rules, it's just syntactic sugar that rather than writing x.child.foo you can just write x.foo.

You make your case very well.  But strictly as a matter or curiosity, when you do LD A -> (BC), does A go into B, or C, or perhaps both, or perhaps one or the other depending on whether the "BigEndian" switch is on or off?  And if A goes into B, is C left alone, or set to zero?

The programmer knows the answers having the manual ready to hand and probably memorized after long hours of work.  But the reader might not.  And that makes me wonder if there isn't a better way to represent the case (in general, not just in this one example)?
Don't get me started on endianess for the emulator, in the Gameboy Manual it is very confusing on this, and without code examples I probably wouldn't have figured out myself.
But basically yes, this is just some syntactic sugar around variant records, so endianess and all that other stuff effects the definition of the types. You probably need something like this:
Code: Pascal  [Select][+][-]
  1. TAFRecord = record
  2. case Boolean of
  3. True: (AF: Word);
  4. {$IfDef LittleEndian}
  5. False: (A, F: Byte);
  6. {$Else}
  7. False: (F, A: Byte);
  8. {$EndIf}
  9. end;
  10.  
  11. ...
  12. TCPURegs = record
  13.   uses TAFRecord;
  14.   uses TBCRecord;
  15.   ...
  16. end;

But this is the sort of stuff that you get always in contact with when doing low level programming. I think there isn't a good solution for that problem, basically you will always have to write things twice if you are going to handle different endianess. Personally, as I usually only write software for modern x86_64 CPUs, I just don't care and always assume little endian. When I'm feeling extra secure I may add something like:
Code: Pascal  [Select][+][-]
  1. {$IfNDef LittleEndial}
  2. {$Error Currently only works on Little Endian architectures}
  3. {$EndIf}

Zoran

  • Hero Member
  • *****
  • Posts: 1804
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Proposal: Record Composition
« Reply #17 on: September 18, 2023, 08:53:46 pm »
This is a good addition, Warfly!

See the type declaration about line 30 in my implementation of Zilog 80:
Code: Pascal  [Select][+][-]
  1. type
  2.  
  3.   TRec16 = packed record
  4.     case Integer of
  5.       0: // unsigned word (16-bit unsigned int)
  6.         (U16bit: Word);
  7.       1: // pair of unsigned bytes
  8.       {$ifdef endian_little}
  9.         (UByteLo, UByteHi: Byte);
  10.       {$else}
  11.         (UByteHi, UByteLo: Byte);
  12.       {$endif}
  13.   end;
  14.  

Had your proposed functionality been in language syntax when I started the emulator, I would have rather written it like this:

Code: Pascal  [Select][+][-]
  1. type
  2.  
  3.   TRec16 = packed record
  4.     case Integer of
  5.       0: // unsigned word (16-bit unsigned int)
  6.         (U16bit: Word);
  7.       1: // pair of unsigned bytes
  8.        ( uses SysUtils.WordRec );
  9.   end;
  10.  

Because we have WordRec type declared in SysUtils:
Code: Pascal  [Select][+][-]
  1.    WordRec = packed record
  2. {$ifdef FPC_LITTLE_ENDIAN}
  3.      Lo,Hi : Byte;
  4. {$else FPC_LITTLE_ENDIAN}
  5.      Hi,Lo : Byte;
  6. {$endif FPC_LITTLE_ENDIAN}
  7.    end;
  8.  

Btw, for the purpose of your Nintendo emulator, you can adjust this unit. It has some peculiarities of ZX Spectrum (memory contention for example), built in processor code for speed, though.
But yes, I know that all the fun would go away if you don't write it yourself... :D
Still, you might want to take a look anyway. 8)

Fibonacci

  • Full Member
  • ***
  • Posts: 219
  • #PDK
Re: Proposal: Record Composition
« Reply #18 on: September 25, 2023, 11:08:09 am »
Any progress? Its a great feature, please finish it and make a PR

If FPC devs reject this feature lets make FPC+ :D With additional features. Record Composition, Inline Variables, maybe multiline strings (heredoc) :D Im currently using modified compiler with 4 custom modeswitches, 2 of them I could contribute to FPC+.

Warfley

  • Hero Member
  • *****
  • Posts: 1469
Re: Proposal: Record Composition
« Reply #19 on: September 25, 2023, 01:05:57 pm »
From my point of view this is finished so far, I have around 60 tests or so, and I don't know what to test further. It seems to be pretty stable so far. I created an MR https://gitlab.com/freepascal.org/fpc/source/-/merge_requests/498

Note that this feature is actually just some prequesite for a bigger feature I'm building (well the internals that enable this feature at least, not the syntax feature using "uses" itself, this was just for testing purposes and because I think it may be useful), so I'll leave it at that for now

Fibonacci

  • Full Member
  • ***
  • Posts: 219
  • #PDK
Re: Proposal: Record Composition
« Reply #20 on: September 25, 2023, 02:10:53 pm »
Great! Everyone on this forum who thinks this feature is useful should leave a thumbs up for this MR on GitLab.

Fibonacci

  • Full Member
  • ***
  • Posts: 219
  • #PDK
Re: Proposal: Record Composition
« Reply #21 on: September 25, 2023, 03:03:04 pm »
How much effort would it take to change the "uses" keyword to something new, custom made?
« Last Edit: September 25, 2023, 03:06:31 pm by Fibonacci »

Warfley

  • Hero Member
  • *****
  • Posts: 1469
Re: Proposal: Record Composition
« Reply #22 on: September 25, 2023, 03:32:14 pm »
Would need to be added to the scanner, which I think is generated with flex, so it shouldn't be that hard. That said, from what I know, due to backwards compatibility the fpc team is heistant to introduce new keywords, because those words would then be "burned" from any other use. So if you introduce something like "compose" than any program that has a variable called "compose" would probably break.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5283
  • Compiler Developer
Re: Proposal: Record Composition
« Reply #23 on: September 28, 2023, 10:09:08 pm »
Would need to be added to the scanner, which I think is generated with flex, so it shouldn't be that hard.

It is hand crafted, not generated.

 

TinyPortal © 2005-2018