Recent

Author Topic: How to force the not operator to return a byte  (Read 9863 times)

y.ivanov

  • Full Member
  • ***
  • Posts: 185
Re: How to force the not operator to return a byte
« Reply #60 on: May 16, 2021, 06:10:57 pm »
*snip*
What types are you talking about for ordinary constants? Show how " to solve it with types", I don't afraid to say that I do not know that.
My point was that, the Sizeof() for example when used on expression, must evaluate the type of the expression, not the expression itself. Then substituting with the terminals (e.g. 128 for a, 64 for b) into the expression (byte(not (a or b)), and given the rules for expansion, we should be able to determine at which step the sign-extension takes place and to put a proper typecast to prevent it. But it turns out it was just a speculation.   

@molly
+1 for your detailed explanation
« Last Edit: May 16, 2021, 06:14:26 pm by y.ivanov »

tetrastes

  • Full Member
  • ***
  • Posts: 119
Re: How to force the not operator to return a byte
« Reply #61 on: May 16, 2021, 06:26:13 pm »
Code: [Select]
Remark: The compiler decides on the type of an integer constant
based on the value: An integer constant gets the smallest possible
signed type.
...
constants in range 128..255 are mapped to byte, etc.
...

These two statements contradict each other, am I wrong?
I fail to see how these two statements could contradict. If you still think the same after reading this post then please feel free to elaborate to make me better understand.
An integer constant gets the smallest possible SIGNED type.
...
constants in range 128..255 are mapped to BYTE

Byte is unsigned type, so according to first statement constants in range 128..255 must be mapped to SmallInt.
But English is not my native language, and maybe I don't undestand something... 

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: How to force the not operator to return a byte
« Reply #62 on: May 16, 2021, 07:08:30 pm »
Ah, thank you for the elaboration tetrates.

Now I am able to understand why you might think that.

If you look at the original text: https://freepascal.org/docs-html/ref/refsu4.html#x26-250003.1.1

The statement at the remark-part is a generic statement on how the compiler works. Immediately after that statement the original documentation elaborates on how that is done by the compiler by telling:

Quote
The first match in table (3.3) is used.
By using the table you are able to determine the order of precedence.

fwiw: I left out the actual table in my code because I have beter things to do other than copying a html-table into source-code  :D

First the compiler tries to match shortint, then byte, then smallint, etc, and as shown in the table.

The number/value 64 first match is that of a shortint.
the number/value 128 does not fit in a shortint and the next candidate in the table is a byte.
the same applies the number/value 192.

The resulting answer/value turning into a 64 bit integer is the exception, which is also explained by the documentation (note that the 64-bit is mentioned in the documentation, but that might differ because the documentation can be different for other platforms and therefor not always return a 64-bit integer. e.g. that could also be a 32-bit integer on 32 bit cpu, or perhaps an even smaller integer depending on the platform).

Does the above explanation compute better for you ?

Quote
y.ivanov wrote:
@molly
+1 for your detailed explanation
Thank you for the +1 but I can't really take the credit for that as others have (more or less) stated the same.

The only thing I did is make it a bit more easier to understand by creating an example that is as simple as possible to understand and that matches the documentation.

In case the example and explanation was able to help the reader better understand of what is actually happening then I'm glad I was able to help out (a little).

Practise shows that it is far more difficult to be able to disprove what is written in the documentation , and then nag about that :P

tetrastes

  • Full Member
  • ***
  • Posts: 119
Re: How to force the not operator to return a byte
« Reply #63 on: May 16, 2021, 07:23:34 pm »
@molly
Thank you for explanations, I understand all. But I still think that the first statement must be "An integer constant gets the smallest possible INTEGER type".

lucamar

  • Hero Member
  • *****
  • Posts: 4135
Re: How to force the not operator to return a byte
« Reply #64 on: May 16, 2021, 07:54:38 pm »
Thank you for explanations, I understand all. But I still think that the first statement must be "An integer constant gets the smallest possible INTEGER type".

Context is everything here ;)

The original wording is because it's a quotation from the documentation and it refers to the table of integer types, so "smallest possible signed type" in this case has to be taken to mean "smallest possible signed type from those in the table above [of predefined integer types]".
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

y.ivanov

  • Full Member
  • ***
  • Posts: 185
Re: How to force the not operator to return a byte
« Reply #65 on: May 16, 2021, 08:11:21 pm »
Here are the snippets from the compiler source:
Code: Pascal  [Select][+][-]
  1. // from pexpr.pas
  2. ...
  3.             _INTCONST :
  4.                begin
  5.                  {Try first wether the value fits in an int64.}
  6.                  val(pattern,ic,code);
  7.                  if code=0 then
  8.                    begin
  9.                       consume(_INTCONST);
  10.                       int_to_type(ic,hdef);
  11.                       p1:=cordconstnode.create(ic,hdef,true);
  12.                    end
  13.                  else
  14.                    begin
  15.                      { try qword next }
  16.                       ...
  17.                  if code<>0 then
  18.                    begin
  19.                      { finally float }
  20.                       ...
  21.  
  22. // from defutil.pas
  23.   ...
  24.     procedure int_to_type(const v:TConstExprInt;var def:tdef);
  25.       begin
  26.         range_to_type(v,v,def);
  27.       end;
  28. ...
  29.     procedure range_to_type(const l,h:TConstExprInt;var def:tdef);
  30.       begin
  31.         { prefer signed over unsigned }
  32.         if (l>=int64(-128)) and (h<=127) then
  33.          def:=s8inttype
  34.         else if (l>=0) and (h<=255) then
  35.          def:=u8inttype
  36.         else if (l>=int64(-32768)) and (h<=32767) then
  37.          def:=s16inttype
  38.         else if (l>=0) and (h<=65535) then
  39.          def:=u16inttype
  40.         else if (l>=int64(low(longint))) and (h<=high(longint)) then
  41.          def:=s32inttype
  42.         else if (l>=low(cardinal)) and (h<=high(cardinal)) then
  43.          def:=u32inttype
  44.         else if (l>=low(int64)) and (h<=high(int64)) then
  45.          def:=s64inttype
  46.         else
  47.          def:=u64inttype;
  48.       end;
  49. ...

I believe the code of procedure range_to_type says it all. No more contradictions.  :D

Roland57

  • Full Member
  • ***
  • Posts: 187
Re: How to force the not operator to return a byte
« Reply #66 on: May 16, 2021, 09:07:51 pm »
Thank you all for the very informative discussion.  :)

winni

  • Hero Member
  • *****
  • Posts: 2478
Re: How to force the not operator to return a byte
« Reply #67 on: May 16, 2021, 09:17:30 pm »


To be, Or Not (to be )

Hamlet, Shakespeare



engkin

  • Hero Member
  • *****
  • Posts: 2853
Re: How to force the not operator to return a byte
« Reply #68 on: May 16, 2021, 10:54:13 pm »
Here is the source code for NOT:
Code: Pascal  [Select][+][-]
  1. //nmat
  2. function tnotnode.simplify(forinline : boolean):tnode;
  3. ...
  4. { constant folding }
  5. if (left.nodetype=ordconstn) and
  6.   (left.resultdef.typ=orddef) then
  7.   begin
  8.     v:=tordconstnode(left).value;
  9.     def:=left.resultdef;
  10. ....
  11.     uchar,
  12.     uwidechar,
  13.     u8bit,
  14.     s8bit,
  15.     u16bit,
  16.     s16bit,
  17.     s32bit,
  18.     u32bit,
  19.     s64bit,
  20.     u64bit:
  21.       begin
  22.         { unsigned, equal or bigger than the native int size? }
  23.         if (torddef(left.resultdef).ordtype in [u64bit,u32bit,u16bit,u8bit,uchar,uwidechar]) and
  24.            (is_nativeord(left.resultdef) or is_oversizedord(left.resultdef)) then
  25.           begin
  26.             { Delphi-compatible: not dword = dword (not word = longint) }
  27.             { Extension: not qword = qword                              }
  28.             v:=qword(not qword(v));
  29.             { will be truncated by the ordconstnode for u32bit }
  30.           end
  31.         else
  32.           begin
  33.             v:=int64(not int64(v));
  34.             def:=get_common_intdef(torddef(left.resultdef),torddef(sinttype),false);
  35.           end;
  36.       end;

So NOT is computed as:
Code: Pascal  [Select][+][-]
  1.             v:=int64(not int64(v));

"will be truncated by the ordconstnode for us32bit"
« Last Edit: May 16, 2021, 10:58:22 pm by engkin »

 

TinyPortal © 2005-2018