Recent

Author Topic: {$if SizeOf(byte) = 1} works but {$if SizeOf(TMyOrdinalType) = 1} doesn't  (Read 10717 times)

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
This compiles and works well:
Code: Pascal  [Select][+][-]
  1.   {$MACRO ON}
  2.   {$if SizeOf(byte) = 1}
  3.     WriteLn('SizeOf(byte) = ', SizeOf(byte));
  4.   {$endif}
  5.  

however this does not compile:
Code: Pascal  [Select][+][-]
  1.   {$MACRO ON}
  2.   {$define TMyOrdinalType := byte}
  3.   {$if SizeOf(TMyOrdinalType) = 1}
  4.     WriteLn('SizeOf(TMyOrdinalType) = ', SizeOf(TMyOrdinalType));
  5.   {$endif}
  6.  
and produces this compilation error:
Quote
Identifier not found "TMyOrdinalType"

Is there some workaround?

Btw: Tested on trunk 32-bit FPC on Win10 x64.
« Last Edit: July 16, 2021, 12:12:59 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

MarkMLl

  • Hero Member
  • *****
  • Posts: 6646
Presumably that also means that a macro doesn't expand inside a $note etc.

Paging a compiler developer to tell us that the workaround is not to use macros.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
workaround is not to use macros.
I have found a workaround to use one $define / $undef pair for each ordinal type size, but that code is ugly and duplicates more then needed so I am hoping for something more elegant.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

Kays

  • Hero Member
  • *****
  • Posts: 569
  • Whasup!?
    • KaiBurghardt.de
however this does not compile:
I don’t understand why you aren’t writing a simple type alias:
Code: Pascal  [Select][+][-]
  1. type
  2.         TMyOrdinalType = Byte;
Yours Sincerely
Kai Burghardt

alpine

  • Hero Member
  • *****
  • Posts: 1032
workaround is not to use macros.
I have found a workaround to use one $define / $undef pair for each ordinal type size, but that code is ugly and duplicates more then needed so I am hoping for something more elegant.
May I ask you why is that?
Because from your sample it smells like C preprocessor meta-programming which is everything but elegant.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
I don’t understand why you aren’t writing a simple type alias:
Code: Pascal  [Select][+][-]
  1. type
  2.         TMyOrdinalType = Byte;

because I would like to avoid to query type size at runtime and query at compilation time instead, something like this:
Code: Pascal  [Select][+][-]
  1. function TORDINALHELPER.HighestBitPos: cardinal;
  2. begin
  3.   {$if     SizeOf(TORDINALTYPE) = 1}
  4.     Result := BsrByte(byte(Self));
  5.   {$elseif SizeOf(TORDINALTYPE) = 2}
  6.     Result := BsrWord(word(Self));
  7.   {$elseif SizeOf(TORDINALTYPE) = 4}
  8.     Result := BsrDWord(dword(Self));
  9.   {$else} // SizeOf(TORDINALTYPE) = 8
  10.     Result := BsrQWord(qword(Self));
  11.   {$endif}
  12. end;

For more info about TORDINALHELPER take a look at syshelpo.inc in RTL SysUtils.

workaround is not to use macros.
I have found a workaround to use one $define / $undef pair for each ordinal type size, but that code is ugly and duplicates more then needed so I am hoping for something more elegant.
May I ask you why is that?
Because from your sample it smells like C preprocessor meta-programming which is everything but elegant.
I have also said my self that it's not elegant and that's the reason why I would like to avoid it. Unfortunately {$if SizeOf(TMyOrdinalType) = 1} doesn't work although according to $IF docs I expected it to work. I discuss this case here to find out if I should file a bug report, or to find out a more elegant alternative.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11351
  • FPC developer.
Alternatively, make it generic and then use gettypekind ?

Seenkao

  • Hero Member
  • *****
  • Posts: 545
    • New ZenGL.
Code: Pascal  [Select][+][-]
  1. function TORDINALHELPER.HighestBitPos: cardinal;
  2. begin
  3.   {$if     SizeOf(TORDINALTYPE) = 1}
  4.     Result := BsrByte(byte(Self));
  5.   {$elseif SizeOf(TORDINALTYPE) = 2}
  6.     Result := BsrWord(word(Self));
  7.   {$elseif SizeOf(TORDINALTYPE) = 4}
  8.     Result := BsrDWord(dword(Self));
  9.   {$else} // SizeOf(TORDINALTYPE) = 8
  10.     Result := BsrQWord(qword(Self));
  11.   {$endif}
  12. end;
Мне интересно: вы смотрите конечный код (скомпилированный) - что получается на выходе такого кода?!

Google translate:
I'm wondering: you are looking at the final code (compiled) - what is the output of such a code?!
Rus: Стремлюсь к созданию минимальных и достаточно быстрых приложений.

Eng: I strive to create applications that are minimal and reasonably fast.
Working on ZenGL

alpine

  • Hero Member
  • *****
  • Posts: 1032
*snip*
workaround is not to use macros.
I have found a workaround to use one $define / $undef pair for each ordinal type size, but that code is ugly and duplicates more then needed so I am hoping for something more elegant.
May I ask you why is that?
Because from your sample it smells like C preprocessor meta-programming which is everything but elegant.
I have also said my self that it's not elegant and that's the reason why I would like to avoid it. Unfortunately {$if SizeOf(TMyOrdinalType) = 1} doesn't work although according to $IF docs I expected it to work. I discuss this case here to find out if I should file a bug report, or to find out a more elegant alternative.
I see. It looks to me as a perfect case for using template specialization (as marcov noted).
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
Alternatively, make it generic and then use gettypekind ?
Looking at TTypeKind I do not see how can ordinal types with SysUtils helpers (boolean type are not interesting) be identified as 1, 2 4 or 8 bytes (for example byte and shortint can not be identified as 1 byte types, and word and smallint as 2 byte types).

I'm wondering: you are looking at the final code (compiled) - what is the output of such a code?!
No. According to documentation {$if SizeOf(TORDINALTYPE) = 1} should be compilable but it's not. That's why I 'm looking at alternatives.
Ето нет конечный код. Kомпилированние не можно.
« Last Edit: July 16, 2021, 01:43:43 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11351
  • FPC developer.
No. According to documentation {$if SizeOf(TORDINALTYPE) = 1} should be compilable but it can not be compiled. That's why I 'm looking at alternatives.
Ето нет конечный код. Kомпилированние не можно.

It should be if defined as type alias, but you are turning it into a macro. Doing it runtime with sizeof(T)  CASE block might also help, and hope it is optimized away in final code. (because the sizeof(T) becomes a constant and the other case options will never happen)

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
No. According to documentation {$if SizeOf(TORDINALTYPE) = 1} should be compilable but it can not be compiled. That's why I 'm looking at alternatives.
Ето нет конечный код. Kомпилированние не можно.

It should be if defined as type alias, but you are turning it into a macro. Doing it runtime with sizeof(T)  CASE block might also help, and hope it is optimized away in final code. (because the sizeof(T) becomes a constant and the other case options will never happen)
As said, I am trying to avoid runtime SizeOf() and case block check. The example I've shown is not probably going to end up in a loop, but I have examples where even slightest delay matters a lot so I am trying to optimize for performance as much as it's reasonable and stays cross platform.

Looking at the documentation https://www.freepascal.org/docs-html/prog/progsu29.html I was expecting {$if SizeOf(TORDINALTYPE) = 1} to compile. If I am reading it correctly, then I should either file a documentation bug report to make documentation more clear, or a feature bug report where $IF is not behaving as it should. Help?
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

alpine

  • Hero Member
  • *****
  • Posts: 1032
Considering your first example:
*snip*
however this does not compile:
Code: Pascal  [Select][+][-]
  1.   {$MACRO ON}
  2.   {$define TMyOrdinalType := byte}
  3.   {$if SizeOf(TMyOrdinalType) = 1}
  4.     WriteLn('SizeOf(TMyOrdinalType) = ', SizeOf(TMyOrdinalType));
  5.   {$endif}
  6.  
and produces this compilation error:
Quote
Identifier not found "TMyOrdinalType"

Is there some workaround?

The simple fix for this could be:
Code: Pascal  [Select][+][-]
  1.   {$MACRO ON}
  2.   {$define TMyOrdinalType := byte}
  3. type
  4.   TMyOrdinalType_ = type TMyOrdinalType;
  5.  
  6.   {$if SizeOf(TMyOrdinalType_) = 1}
  7.     WriteLn('SizeOf(TMyOrdinalType) = ', SizeOf(TMyOrdinalType));
  8.   {$endif}
  9.  
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

avra

  • Hero Member
  • *****
  • Posts: 2514
    • Additional info
It really works, so I guess I should probably file a feature bug report. Thanks a lot!  :D :) :D

This code compiles and outputs 2 lines as it should:
Code: Pascal  [Select][+][-]
  1. type
  2.   TMyOrdinalType = type word;
  3.  
  4.   {$MACRO ON}
  5.  
  6.   {$if SizeOf(byte) = 1}
  7.     WriteLn('SizeOf(byte) = ', SizeOf(byte));
  8.   {$endif}
  9.  
  10.   {$if SizeOf(TMyOrdinalType) = 2}
  11.     WriteLn('SizeOf(TMyOrdinalType) = ', SizeOf(TMyOrdinalType));
  12.   {$endif}
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

alpine

  • Hero Member
  • *****
  • Posts: 1032
It really works, so I guess I should probably file a feature bug report. Thanks a lot!  :D :) :D
I'm not sure it is a bug. IMHO I'd prefer not to have a macro expansion within a conditional directive. I even wonder why {$DEFINE :=} was introduced at first place, we have const, type  ... In C that was the only way to define (literal) constants.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

 

TinyPortal © 2005-2018