### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### 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
« 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 constantbased on the value: An integer constant gets the smallest possiblesigned 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

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
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

#### 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 !!!)
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.

#### 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 »