Recent

Author Topic: strange FPC error message  (Read 6592 times)

440bx

  • Hero Member
  • *****
  • Posts: 6530
strange FPC error message
« on: June 07, 2020, 10:17:08 pm »
Hello,

Consider the following test program:
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2.  
  3. program TestBooleanExpression;
  4.  
  5. var
  6.   b : boolean;
  7.  
  8. begin
  9.   b := not 5 and 3;
  10. end.
  11.  
The compiler emits the following errors:
Code: Text  [Select][+][-]
  1. Free Pascal Compiler version 3.0.4 [2017/10/06] for x86_64
  2. Copyright (c) 1993-2017 by Florian Klaempfl and others
  3. Target OS: Win64 for x64
  4. Compiling TestBooleanExpression.lpr
  5. TestBooleanExpression.lpr(9,14) Error: Incompatible types: got "ShortInt" expected "Boolean"
  6. TestBooleanExpression.lpr(9,14) Warning: range check error while evaluating constants (2 must be between 0 and 1)
  7. TestBooleanExpression.lpr(10,4) Fatal: There were 1 errors compiling module, stopping
  8. Fatal: Compilation aborted
The first message about "Incompatible types:..." is as expected.

The second message OTH, is a bit unusual.  2 is the result of not 5 binary anded wtih 3, that part is fine but, it makes no difference whether or not the result is between 0 and 1.   IOW, there is no range check error/warning applicable, the expression would still be wrong even if the range condition had been met (wrong type).
 
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: strange FPC error message
« Reply #1 on: June 07, 2020, 10:27:11 pm »
It compiles and give an outcome of False with a typecast:
Code: Pascal  [Select][+][-]
  1. program TestBooleanExpression;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. var
  6.   b : boolean;
  7.  
  8. begin
  9.   b := not Boolean(5 and 3);
  10.   WriteLn('b=',b);
  11.   ReadLn;
  12. end.

440bx

  • Hero Member
  • *****
  • Posts: 6530
Re: strange FPC error message
« Reply #2 on: June 07, 2020, 10:47:44 pm »
It compiles and give an outcome of False with a typecast:
And what is strange about that is, the value 2 is being assigned to a boolean (which is out of range for a boolean) yet, there is no range warning issued but, there was a range warning issued when the type was wrong. 
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Kays

  • Hero Member
  • *****
  • Posts: 632
  • Whasup!?
    • KaiBurghardt.de
Re: strange FPC error message
« Reply #3 on: June 07, 2020, 11:05:03 pm »
[…]And what is strange about that is, the value 2 is being assigned to a boolean (which is out of range for a boolean) yet, there is no range warning issued but, there was a range warning issued when the type was wrong.
No, it’s not. The compiler will ensure Boolean types’ values are correct. On a x86 target it’ll use the set instruction which “writes” zero or one:
Code: ASM  [Select][+][-]
  1.         call    FPC_INITIALIZEUNITS
  2. ; [6] five := 5;
  3.         movw    $5,U_$P$TESTBOOLEANEXPRESSION_$$_FIVE
  4. ; [7] three := 3;
  5.         movw    $3,U_$P$TESTBOOLEANEXPRESSION_$$_THREE
  6. ; [8] b := not Boolean(five and three);
  7.         movw    U_$P$TESTBOOLEANEXPRESSION_$$_FIVE,%dx
  8.         movw    U_$P$TESTBOOLEANEXPRESSION_$$_THREE,%ax
  9.         andw    %dx,%ax
  10.         testb   %al,%al
  11.         seteb   U_$P$TESTBOOLEANEXPRESSION_$$_B
  12. ; [9] end.
Yours Sincerely
Kai Burghardt

jamie

  • Hero Member
  • *****
  • Posts: 7764
Re: strange FPC error message
« Reply #4 on: June 07, 2020, 11:53:18 pm »
The compiler has short comings.. It's living in a world where it thinks the only value for true is 1

The statement should of been understood by the compiler if the results wasn't 0, just set the Boolean to or what ever value it likes..

The only true wisdom is knowing you know nothing

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12403
  • Debugger - SynEdit - and more
    • wiki
Re: strange FPC error message
« Reply #5 on: June 08, 2020, 01:15:42 am »
The compiler has short comings.. It's living in a world where it thinks the only value for true is 1
Or rather you give it the wrong instruction.

Boolean is an enum with two values.
If you bitpack an array/record then 8 Boolean vars should fit into 1 byte (not tested, if fpc actually will do it)

You can use
LongBool that gives you a boolean that can take the 32bit range (or wordbool, or bytebool)

jamie

  • Hero Member
  • *****
  • Posts: 7764
Re: strange FPC error message
« Reply #6 on: June 08, 2020, 01:45:06 am »
But those don't work correctly either in all cases where the code expects a value of 1 for a Boolean results..
  cases where it is expected to fit in a byte size return..

 Oh well, no worries. Much more to ponder over...
The only true wisdom is knowing you know nothing

440bx

  • Hero Member
  • *****
  • Posts: 6530
Re: strange FPC error message
« Reply #7 on: June 08, 2020, 05:43:00 am »
No, it’s not. The compiler will ensure Boolean types’ values are correct.
In spite of the assembly code you posted, the results contradict your statement.  Run this sample program (32bit or 64bit... your choice... no difference):
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2.  
  3. program TestBooleanExpression;
  4.  
  5. var
  6.   b : boolean;
  7.   c : boolean;
  8.  
  9. begin
  10.   c := boolean(5);
  11.   b := boolean(not 5 and 3);
  12.  
  13.   writeln;
  14.  
  15.   writeln('b = ', ord(b));
  16.   writeln('b = ', b);
  17.  
  18.   writeln('c = ', ord(c));
  19.   writeln('c = ', c);
  20.  
  21.   writeln;
  22.   write('b = c ? : ');
  23.  
  24.   // it doesn't do a logical comparison (likely because Delphi doesn't either)
  25.  
  26.   if b = c then writeln('equal') else writeln('not equal (logic in wonderland)');
  27. end.                            
if the values of b and c were correct (that is, in the range of a boolean) then true would equal true (as some "unreasonable" people like George Boole would expect)  Another Borland-ism to make Pascal behave like C.

ETA
Corrected typo: changed "b" to "c" in the first writeln of the second set of writeln(s)
« Last Edit: June 08, 2020, 01:46:55 pm by 440bx »
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 19267
  • Glad to be alive.
Re: strange FPC error message
« Reply #8 on: June 08, 2020, 09:10:38 am »
The second message is undetermined because the first is an error.
objects are fine constructs. You can even initialize them with constructors.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12403
  • Debugger - SynEdit - and more
    • wiki
Re: strange FPC error message
« Reply #9 on: June 08, 2020, 01:16:19 pm »
if the values of b and c were correct (that is, in the range of a boolean) then true would equal true (as some "unreasonable" people like George Boole would expect)  Another Borland-ism to make Pascal behave like C.

It only is unexpected if you ignore the type.

For any enum "SomeWeekday := TWeekday(999);" you can forcefully assign an out of range value.
That is known to be undocumented behaviour. If the enum is stored packed it will behave differently, because the value may not even fit into the underlying storage.
If you compare values for which the behaviour is unexpected, well.....

Boolean is enum(False,True).

Run your code again, but use "longbool" (for the var, and the typecast).
And it will say that they are "equal". (I did test that)

It does exactly what you ask it to do.

440bx

  • Hero Member
  • *****
  • Posts: 6530
Re: strange FPC error message
« Reply #10 on: June 08, 2020, 01:39:45 pm »
It only is unexpected if you ignore the type.
On the contrary.  A boolean is supposed to have only two possible values (0 and 1), therefore the compiler should not claim that a boolean with a value that is neither zero (0) nor one (1) is true or false, it is something (a donald trump !?) but, neither true nor false.

Boolean is enum(False,True).
yes, it is and, it would nice if the compiler knew that too.  :D

Run your code again, but use "longbool" (for the var, and the typecast).
And it will say that they are "equal". (I did test that)

It does exactly what you ask it to do.
But, longbool is a different data type with different semantics than boolean.  A longbool is true for any non zero value, that is not the definition of boolean.

Just for the record, I don't hold FPC responsible for that boolean nonsense.  It comes from Delphi.  Another Borland-ism.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12403
  • Debugger - SynEdit - and more
    • wiki
Re: strange FPC error message
« Reply #11 on: June 08, 2020, 02:25:57 pm »
It only is unexpected if you ignore the type.
On the contrary.  A boolean is supposed to have only two possible values (0 and 1), therefore the compiler should not claim that a boolean with a value that is neither zero (0) nor one (1) is true or false, it is something (a donald trump !?) but, neither true nor false.
It is the same as TWeekDay(999).

What is supposed to happen with  TWeekDay(999)?
There was a huge discussion, about that when certain "case of" optimization came into play. (a case "else" does not catch 999, if all defined values are already explicitly mentioned)

A "longbool" has 4million possible values. And 2 defined meanings for them.

A boolean as you said has only 2 possible values. (and 2 meanings for them).

How to bring your 2 statements together?
- There are only 2 possible value for boolean (true and false)
- 1, 3, 5 or whatever are all boolean values
That is a direct contradiction.

You clearly expect the behaviour of longbool. So use that.

Pascal offers you both worlds.
- boolean with only 0 or 1 and all else undefined
- longbool with true = not zero

What is the problem with that?

Maybe you would prefer, if Pascal did not allow type-casts (as they are not type safe)

Quote
Boolean is enum(False,True).
yes, it is and, it would nice if the compiler knew that too.  :D
Where and when does it not?

Isn't your complain about the compiler behaving exactly to that knowledge when it compares the 2 values?

It does indeed ignore that, when you typecast boolean(n). (n outside range).
Again: typecasts are not typecast. So indeed, typecasts mean that the compiler ignores the knowledge it has about the data type.

I do not know if/were the documentation for that is, but it has been pointed out plenty of times: typecasts can break the type system.
Typecasts allow to produce invalid data, and invalid data has no defined behaviour.
5 is not a boolean value (its an integer). Typecasting it, does not necessarily  result in valid boolean data.

 
Quote
Run your code again, but use "longbool" (for the var, and the typecast).
And it will say that they are "equal". (I did test that)

It does exactly what you ask it to do.
But, longbool is a different data type with different semantics than boolean.  A longbool is true for any nolean.
But isn't that exactly what you were asking for?

That is the result you expect in your final compare.



Just to show how undefined the behaviour is
Code: Pascal  [Select][+][-]
  1.     {$APPTYPE CONSOLE}
  2.  
  3.     program TestBooleanExpression;
  4.  
  5.     var
  6.     x: bitpacked record
  7.       b : boolean;
  8.       c : boolean;
  9.       c1 : boolean;
  10.       c2 : boolean;
  11.       c3 : boolean;
  12.       c4 : boolean;
  13.       end ;
  14.  
  15.     begin
  16.       x.c := boolean(5);
  17.       x.b := boolean(7);  // <<< changed this
  18.  
  19.       writeln;
  20.  
  21.       writeln('x.b = ', ord(x.b));
  22.       writeln('x.b = ', x.b);
  23.  
  24.       writeln('x.c = ', ord(x.c));
  25.       writeln('x.c = ', x.c);
  26.  
  27.       writeln;
  28.       write('x.b = x.c ? : ');
  29.  
  30.       // it doesn't do a logical comparison (likely because Delphi doesn't either)
  31.  
  32.       if x.b = x.c then writeln('equal') else writeln('not equal (logic in wonderland)');
  33.     end.
  34.  

with bitpacked
Code: Text  [Select][+][-]
  1. x.b = 1
  2. x.b = True
  3. x.c = 1
  4. x.c = TRUE
  5.  
  6. x.b = x.c ? : equal

without bitpacked
Code: Text  [Select][+][-]
  1. x.b = 7
  2. x.b = TRUE
  3. x.c = 5
  4. x.c = TRUE
  5.  
  6. x.b = x.c ? : not equal (logic in wonderland)

As you can see the behaviour changes, for the same code. With the same type "boolean". Only because bitpacked changed the underlying storage.

And further more, there is no guarantee, that future fpc version will produce the same result. The result may be different (even without changing the storage), depending on fpc version, optimization, target system, ..... => undefined behaviour.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12403
  • Debugger - SynEdit - and more
    • wiki
Re: strange FPC error message
« Reply #12 on: June 08, 2020, 02:32:52 pm »
Just, adding: If all you say is, the term "boolean" might be misleading, if you do not know its exact definition => then yes, thats might be (implied by the lack of knowing the definition)
If you say the documentation is not up to date, then I have not checked.

But: If you know how boolean is documented (or supposed to be documented), and do not mix up the meaning of boolean in Pascal, with that in other context, then it does exactly what you should expect it to do.

Besides: the trouble does not come from the word being misleading, but from expectations tainted by c or other languages. Because the term boolean does not imply any numeric equivalents for True and False.
It would well be satisfied, if True would be represented by all numeric values with an even number of bits that are 1. And false with an odd number of bits that are one. That definition would work perfectly well. It does not do what C does, but so what?
« Last Edit: June 08, 2020, 02:34:56 pm by Martin_fr »

440bx

  • Hero Member
  • *****
  • Posts: 6530
Re: strange FPC error message
« Reply #13 on: June 08, 2020, 03:07:45 pm »
It is the same as TWeekDay(999).
That flies in the face of strong type checking.  The compiler should not allow a statement like that.

FPC is too cavalier when it comes to enforcing ranges.  Even Delphi, which is definitely on the loose side, is not as loose as FPC.  For instance, Delphi will _not_ allow indexing an array with a constant value that is out of range whereas FPC will (and it shouldn't.)

- 1, 3, 5 or whatever are all boolean values
No, they are not.  The only possible values of a genuine, mathematically and logically correct boolean, is two values.  Numerically and digitally, they can be only zero (0) and (1) because those are the only values that can be stored in one (1) bit.  The problem is that since it is desirable to make boolean variables directly addressable, they are stored in a byte instead of just one bit and, because of that, the definition of boolean has been infected with mathematically incorrect "creative logic" (stemming from C, no surprise there.)


You clearly expect the behaviour of longbool. So use that.
What I'd like, not what I expect since I know that won't happen, is for boolean to be logically correct.  That is, when a boolean variable A is true and another boolean variable B is true then A = B is true as well.

FPC and Delphi, treat boolean types inconsistently.  It they were consistent then it would not be possible for two boolean variables to both be true yet not equal to one another.  In FPC and Delphi boolean is sometimes boolean and sometimes C BOOL.

That's the real problem.  Inconsistency and, the way it's documented is incorrect.  From the link given by @Kays,
Code: Text  [Select][+][-]
  1. Name         Size       Ord(True)
  2. Boolean         1       1
  3. Boolean8        1       1
  4. Boolean16       3       1
  5. Boolean32       4       1
  6. Boolean64       8       1
  7. ByteBool        1       Any nonzero value
  8. WordBool        2       Any nonzero value
  9. LongBool        4       Any nonzero value
  10. QWordBool       8       Any nonzero value
  11.  
The sample program I posted clearly shows that FPC (and Delphi) treat boolean the same as ByteBool, i.e, any non-zero value is true and, when it comes to determining the logical value (true or false) instead of considering any non zero value equal to any other non zero value, IOW, true = true, instead it does a numeric comparison and ends up with true <> true.

On a different note, I seriously doubt Boolean16 is 3 bytes as indicated in that table.  Quite likely (and hopefully) a typo.


But, this is all separate from the point made in the OP which was that, the second message doesn't belong because no matter the range, the types are in conflict.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

lucamar

  • Hero Member
  • *****
  • Posts: 4217
Re: strange FPC error message
« Reply #14 on: June 08, 2020, 03:28:19 pm »
It would well be satisfied, if True would be represented by all numeric values with an even number of bits that are 1. And false with an odd number of bits that are one. That definition would work perfectly well. It does not do what C does, but so what?

That's not quite right, is it? Since, per definition, they have to maintain the relations:
Ord(False) < Ord(True)
Succ(False) = True ==> Pred(True) = False


Or am I wrong?
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.

 

TinyPortal © 2005-2018