Recent

Author Topic: [SOLVED] how to declare a Set constants synonym ?  (Read 865 times)

440bx

  • Hero Member
  • *****
  • Posts: 2015
[SOLVED] how to declare a Set constants synonym ?
« on: April 10, 2020, 11:41:47 am »
Hello,

This question is easier to explain with an example.  Consider the following code:
Code: Pascal  [Select][+][-]
  1. {$WRITEABLECONST OFF}
  2.  
  3. program TestSetConstants;
  4.  
  5. type
  6.   TCOLORS     = (red, green, blue, othercolors);
  7.  
  8.   TCOLORS_SET = set of TCOLORS;
  9.  
  10. var
  11.   RGB            : TCOLORS_SET = [red, green, blue];
  12.  
  13.   PRIMARY_COLORS : TCOLORS_SET absolute RGB;
  14.  
  15. begin
  16. end.
  17.  
The variable PRIMARY_COLORS is just a synonym for the variable RGB.

I would like to accomplish the very same thing but with constants instead of variables, can this be done in FPC ? (in C, a simple #define PRIMARY_COLORS = RGB does the trick).  If possible I would like _not_ to use a macro.  I'd like a Pascal-language solution if there is one.

Thank you.

ETA: I need the constants to be typed.  It can be done with untyped constants but I need them typed.
« Last Edit: April 10, 2020, 10:55:08 pm by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2262
  • Compiler Developer
Re: how to declare a Set constants synonym ?
« Reply #1 on: April 10, 2020, 12:10:13 pm »
Two ways:

First, as you have already set writable constants to off you can just as well declare your RGB constant as const:

Code: Pascal  [Select][+][-]
  1. const
  2.   RGB : TCOLORS_SET = [red, green, blue];

Otherwise you can simply declare it as an untyped set constant. An untyped set constant must contain values of the same enum type (the first enum element defines the type of the set constant and others must be compatible to that) and is implicitely assignment compatible to a declared set type of the same type. As an added bonus you can also use it as an initializer for variables, other constants or for default parameters:

Code: Pascal  [Select][+][-]
  1. const
  2.   RGB = [red, green, blue];
  3.  
  4.   PRIMARY_COLORS = RGB;
  5.  
  6. var
  7.   c: TCOLORS_SET = RGB;
  8. begin
  9. end.

440bx

  • Hero Member
  • *****
  • Posts: 2015
Re: how to declare a Set constants synonym ?
« Reply #2 on: April 10, 2020, 05:24:51 pm »
First, as you have already set writable constants to off you can just as well declare your RGB constant as const:
No problem there but, I can't get the definition of PRIMARY_COLORS to work.  I've tried this:
Code: Pascal  [Select][+][-]
  1. {$WRITEABLECONST OFF}
  2.  
  3. program TestSetConstants;
  4.  
  5. type
  6.   TCOLORS     = (red, green, blue, othercolors);
  7.  
  8.   TCOLORS_SET = set of TCOLORS;
  9.  
  10. const
  11.   RGB            : TCOLORS_SET = [red, green, blue];
  12.  
  13.   PRIMARY_COLORS = RGB;
  14.  
  15. begin
  16. end.
  17.  
but the compiler doesn't like line 13 and I believe the reason is that the constant is typed thus, not really a constant (in the sense that it occupies memory in the read only section) and it doesn't think of PRIMARY_COLORS as just a different name referring to the same area in memory.

Two ways:
It would be most convenient to have it as a _typed_ constant.  Can the code snippet shown above be made to compile and work using typed constants ?


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

Zoran

  • Hero Member
  • *****
  • Posts: 1592
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: how to declare a Set constants synonym ?
« Reply #3 on: April 10, 2020, 05:58:17 pm »
See:

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$J-}
  5.  
  6. uses
  7.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  8.   cthreads,
  9.   {$ENDIF}{$ENDIF}
  10.   Classes
  11.   { you can add units after this };
  12.  
  13.  
  14. type
  15.   TClr = (Red, Green, Blue);
  16.   TClrs = set of TClr;
  17.  
  18. const
  19.   RGB: TClrs = [Red, Green];
  20.  
  21. var
  22. // although in var seciton, this is actually typed constant.
  23.   RGB2: TClrs absolute RGB;
  24.  
  25. begin
  26.   RGB2 := [Green]; // compile time error
  27. end.
  28.  

440bx

  • Hero Member
  • *****
  • Posts: 2015
Re: how to declare a Set constants synonym ?
« Reply #4 on: April 10, 2020, 06:09:44 pm »
That did the trick.  Thank you Zoran.  :)

I had tried to "absolute" the constant but the compiler doesn't like "absolute" in constant definitions even if they are typed.  It would be nice if "absolute" could be used to declare typed constant synonyms. (hint, hint PascalDragon) ;)
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2262
  • Compiler Developer
Re: how to declare a Set constants synonym ?
« Reply #5 on: April 11, 2020, 02:40:23 pm »
but the compiler doesn't like line 13 and I believe the reason is that the constant is typed thus, not really a constant (in the sense that it occupies memory in the read only section) and it doesn't think of PRIMARY_COLORS as just a different name referring to the same area in memory.

Correct, you cannot initialize an untyped constant using a typed constant.

Two ways:
It would be most convenient to have it as a _typed_ constant.  Can the code snippet shown above be made to compile and work using typed constants ?

I still don't know why it would be more convenient. An untyped constant has the advantage that the compiler can directly insert it into the code while a typed constant is always loaded like a variable is.

I had tried to "absolute" the constant but the compiler doesn't like "absolute" in constant definitions even if they are typed.  It would be nice if "absolute" could be used to declare typed constant synonyms. (hint, hint PascalDragon) ;)

absolute is simply not allowed for constants.

440bx

  • Hero Member
  • *****
  • Posts: 2015
Re: how to declare a Set constants synonym ?
« Reply #6 on: April 11, 2020, 07:40:34 pm »
I still don't know why it would be more convenient. An untyped constant has the advantage that the compiler can directly insert it into the code while a typed constant is always loaded like a variable is.
Maybe stating "convenient" wasn't the right word.  If the set is typed the compiler generates smaller and more efficient code than it does for an untyped set constant, as shown in the following test program:
Code: Pascal  [Select][+][-]
  1. {$WRITEABLECONST OFF}
  2.  
  3. program TestSetConstants;
  4.  
  5. type
  6.   TCOLORS         = (a1, b1, c1, d1, e1, f1, g1, i1, j1, k1, l1, m1,
  7.                      a2, b2, c2, d2, e2, f2, g2, i2, j2, k2, l2, m2,
  8.                      a3, b3, c3, d3, e3, f3, g3, i3, j3, k3, l3, m3,
  9.                      a4, b4, c4, d4, e4, f4, g4, i4, j4, k4, l4, m4,
  10.                      a5, b5, c5, d5, e5, f5, g5, i5, j5, k5, l5, m5,
  11.                      a6, b6, c6, d6, e6, f6, g6, i6, j6, k6, l6, m6);
  12.  
  13.  
  14.   TCOLORS_SET = set of TCOLORS;
  15.  
  16. const
  17.   RGB            : TCOLORS_SET = [a1, b4, c6];
  18.  
  19. type
  20.   TCASES         = (a11, b11, c11, d11, e11, f11, g11, i11, j11, k11, l11, m11,
  21.                     a12, b12, c12, d12, e12, f12, g12, i12, j12, k12, l12, m12,
  22.                     a13, b13, c13, d13, e13, f13, g13, i13, j13, k13, l13, m13,
  23.                     a14, b14, c14, d14, e14, f14, g14, i14, j14, k14, l14, m14,
  24.                     a15, b15, c15, d15, e15, f15, g15, i15, j15, k15, l15, m15,
  25.                     a16, b16, c16, d16, e16, f16, g16, i16, j16, k16, l16, m16);
  26.  
  27. const
  28.   SET2           = [a11, b14, c16];
  29.  
  30. var
  31.   PRIMARY_COLORS : TCOLORS_SET absolute RGB;
  32.  
  33. var
  34.   typed   : TCOLORS;
  35.  
  36.   untyped : TCASES;
  37.  
  38. begin
  39.   if typed in RGB then ;
  40.  
  41.   if untyped in SET2 then ;
  42. end.
  43.  
For that program, the compiler generates the following:
Code: ASM  [Select][+][-]
  1. TestSetConstants.lpr:38           begin
  2. 00401420 55                       push   %ebp
  3. 00401421 89e5                     mov    %esp,%ebp
  4. 00401423 e8d8280000               call   0x403d00 <fpc_initializeunits>
  5.  
  6.                                   ; code when set is typed
  7.  
  8. TestSetConstants.lpr:39           if typed in RGB then ;
  9. 00401428 a100c04000               mov    0x40c000,%eax
  10. 0040142D 0fa30500b04000           bt     %eax,0x40b000
  11.  
  12.                                   ; code when set is untyped
  13.  
  14. TestSetConstants.lpr:41           if untyped in SET2 then ;
  15. 00401434 a110c04000               mov    0x40c010,%eax
  16. 00401439 85c0                     test   %eax,%eax
  17. 0040143B 7408                     je     0x401445 <main+37>
  18. 0040143D 83f825                   cmp    $0x25,%eax
  19. 00401440 7403                     je     0x401445 <main+37>
  20. 00401442 83f83e                   cmp    $0x3e,%eax
  21. TestSetConstants.lpr:42           end.
  22.  
The code generated is smaller and faster when the set is typed because there is a set in memory whose bits can be tested whereas the set does not exist when untyped.  The difference between the two cases is even more pronounced when optimizations are turned on.


absolute is simply not allowed for constants.
Which makes sense but, we both know that a typed constant isn't a compiler constant, it's a memory reference in a read only section.  I admit that using "absolute" on a constant would look strange but, the same thing applies to declaring a variable "absolute"d on top of a constant which works because the "constant" is a constant in memory not a compile time constant.

Maybe FPC should support something along the lines of "static const <identifier definition>" and "static <identifier definition>".  That's just a thought, not a suggestion but, it would certainly be a lot cleaner and descriptive than the contradictory "writeable constants" Borland injected into Pascal.


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

PascalDragon

  • Hero Member
  • *****
  • Posts: 2262
  • Compiler Developer
Re: how to declare a Set constants synonym ?
« Reply #7 on: April 11, 2020, 10:10:37 pm »
I still don't know why it would be more convenient. An untyped constant has the advantage that the compiler can directly insert it into the code while a typed constant is always loaded like a variable is.
Maybe stating "convenient" wasn't the right word.  If the set is typed the compiler generates smaller and more efficient code than it does for an untyped set constant, as shown in the following test program:
Code: Pascal  [Select][+][-]
  1. {$WRITEABLECONST OFF}
  2.  
  3. program TestSetConstants;
  4.  
  5. type
  6.   TCOLORS         = (a1, b1, c1, d1, e1, f1, g1, i1, j1, k1, l1, m1,
  7.                      a2, b2, c2, d2, e2, f2, g2, i2, j2, k2, l2, m2,
  8.                      a3, b3, c3, d3, e3, f3, g3, i3, j3, k3, l3, m3,
  9.                      a4, b4, c4, d4, e4, f4, g4, i4, j4, k4, l4, m4,
  10.                      a5, b5, c5, d5, e5, f5, g5, i5, j5, k5, l5, m5,
  11.                      a6, b6, c6, d6, e6, f6, g6, i6, j6, k6, l6, m6);
  12.  
  13.  
  14.   TCOLORS_SET = set of TCOLORS;
  15.  
  16. const
  17.   RGB            : TCOLORS_SET = [a1, b4, c6];
  18.  
  19. type
  20.   TCASES         = (a11, b11, c11, d11, e11, f11, g11, i11, j11, k11, l11, m11,
  21.                     a12, b12, c12, d12, e12, f12, g12, i12, j12, k12, l12, m12,
  22.                     a13, b13, c13, d13, e13, f13, g13, i13, j13, k13, l13, m13,
  23.                     a14, b14, c14, d14, e14, f14, g14, i14, j14, k14, l14, m14,
  24.                     a15, b15, c15, d15, e15, f15, g15, i15, j15, k15, l15, m15,
  25.                     a16, b16, c16, d16, e16, f16, g16, i16, j16, k16, l16, m16);
  26.  
  27. const
  28.   SET2           = [a11, b14, c16];
  29.  
  30. var
  31.   PRIMARY_COLORS : TCOLORS_SET absolute RGB;
  32.  
  33. var
  34.   typed   : TCOLORS;
  35.  
  36.   untyped : TCASES;
  37.  
  38. begin
  39.   if typed in RGB then ;
  40.  
  41.   if untyped in SET2 then ;
  42. end.
  43.  
For that program, the compiler generates the following:
Code: ASM  [Select][+][-]
  1. TestSetConstants.lpr:38           begin
  2. 00401420 55                       push   %ebp
  3. 00401421 89e5                     mov    %esp,%ebp
  4. 00401423 e8d8280000               call   0x403d00 <fpc_initializeunits>
  5.  
  6.                                   ; code when set is typed
  7.  
  8. TestSetConstants.lpr:39           if typed in RGB then ;
  9. 00401428 a100c04000               mov    0x40c000,%eax
  10. 0040142D 0fa30500b04000           bt     %eax,0x40b000
  11.  
  12.                                   ; code when set is untyped
  13.  
  14. TestSetConstants.lpr:41           if untyped in SET2 then ;
  15. 00401434 a110c04000               mov    0x40c010,%eax
  16. 00401439 85c0                     test   %eax,%eax
  17. 0040143B 7408                     je     0x401445 <main+37>
  18. 0040143D 83f825                   cmp    $0x25,%eax
  19. 00401440 7403                     je     0x401445 <main+37>
  20. 00401442 83f83e                   cmp    $0x3e,%eax
  21. TestSetConstants.lpr:42           end.
  22.  
The code generated is smaller and faster when the set is typed because there is a set in memory whose bits can be tested whereas the set does not exist when untyped.  The difference between the two cases is even more pronounced when optimizations are turned on.

Gotta admit that I'm a bit surprised and had expected better there. Probably there should be a simplification pass added to operations on untyped set constants. :-X

Maybe FPC should support something along the lines of "static const <identifier definition>" and "static <identifier definition>".  That's just a thought, not a suggestion but, it would certainly be a lot cleaner and descriptive than the contradictory "writeable constants" Borland injected into Pascal.

There is no need to add more syntax to the language for something that exists, even if it's counterintuitive.

440bx

  • Hero Member
  • *****
  • Posts: 2015
Re: how to declare a Set constants synonym ?
« Reply #8 on: April 11, 2020, 11:07:50 pm »
Gotta admit that I'm a bit surprised and had expected better there. Probably there should be a simplification pass added to operations on untyped set constants. :-X
Just FYI, if test had been something like "if <identifier> in [a, b, k, y, z] then <statement>" the code the compiler generates is even less efficient speedwise and the number of instructions needed to determine inclusion in the set increases with the number of elements.  Essentially, it acts as a case statement.

There is no need to add more syntax to the language for something that exists, even if it's counterintuitive.
I see your point and, I don't wish to argue it but, the whole thing about "writeable constants" comes across as amateurish.  I don't like C but, I have to say, their implementation is definitely more professional and sensible.  I just believe that things of that kind give the impression that some clueless noobie designed the language.  I agree on the point you made about syntax but, I also believe the syntax should be sensible and, that it would be a good thing for FPC to provide the sensible alternative, it would reflect well on the compiler.


« Last Edit: April 12, 2020, 10:46:11 am by 440bx »
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2262
  • Compiler Developer
Re: how to declare a Set constants synonym ?
« Reply #9 on: April 12, 2020, 11:29:41 am »
Gotta admit that I'm a bit surprised and had expected better there. Probably there should be a simplification pass added to operations on untyped set constants. :-X
Just FYI, if test had been something like "if <identifier> in [a, b, k, y, z] then <statement>" the code the compiler generates is even less efficient speedwise and the number of instructions needed to determine inclusion in the set increases with the number of elements.  Essentially, it acts as a case statement.

I so need to fix that. :o

There is no need to add more syntax to the language for something that exists, even if it's counterintuitive.
I see your point and, I don't wish to argue it but, the whole thing about "writeable constants" comes across as amateurish.  I don't like C but, I have to say, their implementation is definitely more professional and sensible.  I just believe that things of that kind give the impression that some clueless noobie designed the language.  I agree on the point you made about syntax but, I also believe the syntax should be sensible and, that it would be a good thing for FPC to provide the sensible alternative, it would reflect well on the compiler.

For Pascal it's simply part of its legacy. The writable constants come from a time where there was no object oriented programming in Pascal and if you wanted to have a “global” variable shared between different calls of a single function, but not visible from outside code you used a local, typed const. Delphi “fixed” this by allowing such typed constants to be made readonly using a directive which they didn't make default due to backwards compatibility. And FPC followed this concept.

And to be perfectly honest with you: I don't care about sensible syntax for this. We have a working syntax. Anything alternative added is just an unnecessary, further complication of the parser. I prefer to extend the parser only for functionality that can't be expressed currently (like anonymous functions).

Thaddy

  • Hero Member
  • *****
  • Posts: 10516
Re: [SOLVED] how to declare a Set constants synonym ?
« Reply #10 on: April 12, 2020, 12:16:28 pm »
Actually, assignable type const was introduced to maintain local state over function/procedure calls. Yes, this was way before OOP extensions.
When used well, it is still a very powerful feature.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2262
  • Compiler Developer
Re: [SOLVED] how to declare a Set constants synonym ?
« Reply #11 on: April 13, 2020, 02:30:33 pm »
Actually, assignable type const was introduced to maintain local state over function/procedure calls. Yes, this was way before OOP extensions.
When used well, it is still a very powerful feature.

Which is what I wrote here:

For Pascal it's simply part of its legacy. The writable constants come from a time where there was no object oriented programming in Pascal and if you wanted to have a “global” variable shared between different calls of a single function, but not visible from outside code you used a local, typed const. Delphi “fixed” this by allowing such typed constants to be made readonly using a directive which they didn't make default due to backwards compatibility. And FPC followed this concept.

Sometimes I wonder whether you're really reading other people's posts... :'(

Zoran

  • Hero Member
  • *****
  • Posts: 1592
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: [SOLVED] how to declare a Set constants synonym ?
« Reply #12 on: April 13, 2020, 02:43:20 pm »
Actually, assignable type const was introduced to maintain local state over function/procedure calls. Yes, this was way before OOP extensions.
When used well, it is still a very powerful feature.

Which is what I wrote here:

For Pascal it's simply part of its legacy. The writable constants come from a time where there was no object oriented programming in Pascal and if you wanted to have a “global” variable shared between different calls of a single function, but not visible from outside code you used a local, typed const. Delphi “fixed” this by allowing such typed constants to be made readonly using a directive which they didn't make default due to backwards compatibility. And FPC followed this concept.

Sometimes I wonder whether you're really reading other people's posts... :'(

PascalDragon, when you are here and it's on topic... What about this bug? I reported it almost two years ago.

 

TinyPortal © 2005-2018