Recent

Author Topic: class variables in variant record?  (Read 5890 times)

creaothceann

  • Full Member
  • ***
  • Posts: 117
class variables in variant record?
« on: December 13, 2016, 07:48:06 pm »
Test program:

Code: Pascal  [Select][+][-]
  1. program ClassVarRecordTest;  {$MODESWITCH AdvancedRecords}
  2.  
  3.  
  4. type T = record
  5.         class var i : word;
  6.         class var case integer of
  7.                 0:  (abc : word);
  8.                 1:  (xyz : byte);
  9.         end;
  10.  
  11.  
  12. var a, b : T;
  13.  
  14.  
  15. begin
  16. with a do begin  i := 0;  abc := 0;  xyz := 0;  end;  // prevent compiler warnings
  17. with b do begin  i := 0;  abc := 0;  xyz := 0;  end;  // prevent compiler warnings
  18.  
  19. a.i   := 1234;  WriteLn(a.i  , ' ', b.i  );
  20. a.abc := 5678;  WriteLn(a.abc, ' ', b.abc);
  21.  
  22. ReadLn;
  23. end.

Output:

1234 1234
5678 0


The i field in both "variables" a and b being the same shows that class variables are shared; however the variables in the variant part are not.
Is there a way to enable that functionality? (I know this could be simulated with property accessor methods)

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: class variables in variant record?
« Reply #1 on: December 13, 2016, 09:24:38 pm »
It seems a compiler bug. Please report it on Mantis.
I tested with slightly different code and trunk 35112
Code: Pascal  [Select][+][-]
  1. program ClassVarRecordTest;  
  2. {$mode delphi}
  3. type T = record
  4.         class var i : word;
  5.         class var case integer of
  6.                 0:  (abc : word);
  7.                 1:  (xyz : byte);
  8.         end;
  9.  
  10. var a, b : T;
  11. begin
  12.   a:=Default(T);b:=Default(T);
  13.   a.i   := 1234;  WriteLn(a.i  , ' ', b.i  );
  14.   a.abc := 5678;  WriteLn(a.abc, ' ', b.abc);
  15.   ReadLn;
  16. end.

Outputs the same as yours, but it gets worse:
Code: Pascal  [Select][+][-]
  1.   a.abc := 5678;  WriteLn(a.abc:5, b.abc:5, b.xyz:5, a.xyz:5);
Outputs  5678    0    0   46 ??? That's even more "interesting"!  [edit] oops $162e, $2e is 46 of course, so correct.
« Last Edit: December 13, 2016, 10:07:40 pm by Thaddy »
Specialize a type, not a var.

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: class variables in variant record?
« Reply #2 on: December 13, 2016, 09:42:05 pm »
This works:
Code: Pascal  [Select][+][-]
  1. program ClassVarRecordTest;  
  2. {$mode delphi}
  3. type T = record
  4.             i : word;
  5.             case integer of
  6.                 0:  (abc : word);
  7.                 1:  (xyz : byte);
  8.          end;
  9.          
  10.      T2 =record
  11.      class var s:T;
  12.      end;
  13.  
  14. var a, b : T2;
  15. begin
  16.   a:=Default(T2);b:=Default(T2);
  17.   a.s.i   := 1234;  WriteLn(a.s.i:5, b.s.i:5, a.s.xyz:5,b.s.xyz:5  );
  18.   a.s.abc := 5678;  WriteLn(a.s.abc:5, b.s.abc:5, b.s.xyz:5, a.s.xyz:5);
  19.   ReadLn;
  20. end.

Outputs:
Code: [Select]
1234 1234    0    0
5678 5678   46   46
« Last Edit: December 13, 2016, 09:45:39 pm by Thaddy »
Specialize a type, not a var.

creaothceann

  • Full Member
  • ***
  • Posts: 117
Re: class variables in variant record?
« Reply #3 on: December 13, 2016, 10:14:07 pm »
46 is correct, since xyz is only the first 8 bits of the 16-bit variable abc. (5678 = $162E, and $2E = 46)

As for the embedded subrecord... that's what I wanted to avoid ;)

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: class variables in variant record?
« Reply #4 on: December 13, 2016, 10:17:34 pm »
Since it compiles, but doesn't work it is a bug. So report it on the bug tracker.
It should either work, or there should be an error or warning.
(I discovered the $2E myself, shame on me  :-[ , I editted explanation ;) )
Specialize a type, not a var.

creaothceann

  • Full Member
  • ***
  • Posts: 117
Re: class variables in variant record?
« Reply #5 on: December 14, 2016, 11:01:35 pm »
Since it compiles, but doesn't work it is a bug. So report it on the bug tracker.
It should either work, or there should be an error or warning.

Done.

In the mean time I faked additional variables with macros.


Code: Pascal  [Select][+][-]
  1. type int = integer;
  2.  
  3. type u8  = byte;
  4. type u16 = word;
  5.  
  6.  
  7. // version 1 -------------------------------------------------------------------
  8.  
  9.  
  10. type T_CPU_Registers = record
  11.         case int of
  12.                 0:  (AX     : u16);  // accumulator
  13.                 1:  (AL, AH : u8 );  // accumulator low byte, high byte
  14.         end;
  15.  
  16.  
  17. type CPU = record
  18.         class var Regs : T_CPU_Registers;
  19.         // ...
  20.         end;
  21.  
  22.  
  23. // This works, but now I have to type "Regs" everytime I access the registers,
  24. // which will be *a lot*.
  25.  
  26.  
  27. // version 2 -------------------------------------------------------------------
  28.  
  29.  
  30. type T_CPU = record
  31.         // ...
  32.         class var case int of
  33.                 0:  (AX     : u16);  // accumulator
  34.                 1:  (AL, AH : u8 );  // accumulator low byte, high byte
  35.         end;
  36.  
  37.  
  38. // This doesn't work - the variables are not class variables, i.e. they are
  39. // specific to their variable of type T_CPU. This is not optimal because any
  40. // functions declared in the record now need a "Self" pointer to access the
  41. // variable they're supposed to work with, and any functions in the record
  42. // declared as "static" (which in my case are all of them) cannot access the
  43. // variables.
  44.  
  45.  
  46. // version 3 -------------------------------------------------------------------
  47.  
  48.  
  49. type T_CPU = record
  50.         class var AX : u16;  // accumulator
  51.         // ...
  52.         end;
  53.  
  54.  
  55. type u8_2 = array[0..1] of u8;
  56.  
  57. {$MACRO ON}
  58. {$DEFINE  AL  :=  u8_2(AX)[0]  }  // accumulator low  byte
  59. {$DEFINE  AH  :=  u8_2(AX)[1]  }  // accumulator high byte
  60.  
  61.  
  62. // This works - but it's a pure text replacement so I have to be careful about
  63. // writing AL and AH elsewhere, and it's a little bit slower to compile.
  64.  

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: class variables in variant record?
« Reply #6 on: December 15, 2016, 08:49:24 am »
Note that if you are under windows HiByte and LoByte are already defined. For some reason they are not defined for other platforms.
[edit]
I filed a bug report, then of course it became clear that there is already hi() and Lo() It has been so for a long time.Hi and Lo being half the size of the input.
Hi(word) becomes the high byte, High(integer) etc.... It is all there, Just forgot about it.
« Last Edit: December 15, 2016, 11:53:06 am by Thaddy »
Specialize a type, not a var.

creaothceann

  • Full Member
  • ***
  • Posts: 117
Re: class variables in variant record?
« Reply #7 on: December 15, 2016, 06:50:42 pm »
I knew about Hi and Lo. I can also use casts (for the lower part) or array accesses, which is what I did with the macros.

But always writing Hi and Lo gets old really fast. Everybody who knows ASM knows the registers, so just defining them like that in the declaration part would be ideal.

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: class variables in variant record?
« Reply #8 on: December 15, 2016, 08:43:50 pm »
Everybody who knows ASM knows the registers, so just defining them like that in the declaration part would be ideal.
Which is the purpose of hi/lo. They are advanced instructions and not for average use. In my experience, if you "need" that, you have indeed sufficient low-level knowledge. May be even too much ;)  O:-) 8-)
Specialize a type, not a var.

creaothceann

  • Full Member
  • ***
  • Posts: 117
Re: class variables in variant record?
« Reply #9 on: December 16, 2016, 02:22:08 am »
Which is the purpose of hi/lo.
Can't write "Hi(x) := y" though, so I went with arrays ;)

In my experience, if you "need" that, you have indeed sufficient low-level knowledge. May be even too much ;)  O:-) 8-)
I don't believe that Pascal users should always use the highest-level programming techniques, and should use another language if they need low level stuff. :P That's one of the reasons Pascal is not regarded as a "high-performance language".

(I could probably learn x86/x64 ASM for that if I really needed it, but then it'd be less portable than it already is)

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: class variables in variant record?
« Reply #10 on: December 16, 2016, 08:53:26 am »
That's one of the reasons Pascal is not regarded as a "high-performance language".
That's utter nonsense. In principle Pascal is just as performant as C. Simply depends on the evolution of the compiler, which is still getting better.
The language structures are similar. There are many C compilers that are outperformed by FPC on many platforms.

If you consider C as a high performance generic language, you should also consider Pascal a high performance generic language.
It was possible to compare e.g. the GNU C compiler vs the GNU pascal compiler and they basically rendered  the same code speed given the same GNU family version (ca 2005). These shared the same code generator. And that is really comparing like for like. The Delphi compiler generates often faster code than the equivalent C++ compiler by Embarcadero over the versions I used. But these are two different compilers, although from the same stable.
That may also be an indication. Note that FPC only generates optimal code when you really twiddle and fiddle all the options. Can be as much as 200% faster than the default.

« Last Edit: December 16, 2016, 11:40:41 am by Thaddy »
Specialize a type, not a var.

 

TinyPortal © 2005-2018