Recent

Author Topic: likely bug in FPC v3.2.2 handling of booleans  (Read 8538 times)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12718
  • FPC developer.
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #60 on: January 29, 2025, 12:24:17 pm »
- Not everything is about x86(_64)
- on risc systems loading literals into a register requires extra instructions.
- Even on x86 shorter code often avoids decoding bottlenecks.

And again: the alternative scenarios to have no value to begin with. It only puts unnecessary constraints on the code to save people that recklessly filled booleans with casts.

440bx

  • Hero Member
  • *****
  • Posts: 6155
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #61 on: January 29, 2025, 12:38:32 pm »
save people that recklessly filled booleans with casts.
Isn't Pascal supposed to catch and prevent instances of "reckless" programming ?  It does when casting b8 to an integer and casting the numeral 4 to a boolean is just as incorrect (4 is too large to fit in a bit, which is what a boolean is.)

How about the documentation ?... should the documentation still state that only 0 and 1 are allowed (which is not the case) ? 

CPU architecture and performance should never be allowed to get in the way of correctness (and fortunately they _usually_ aren't.)

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

WooBean

  • Sr. Member
  • ****
  • Posts: 303
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #62 on: January 29, 2025, 01:09:02 pm »
440bx
"Isn't Pascal supposed to catch and prevent instances of "reckless" programming ?"

Do not destroy the last hole to survive at keeping alive old binary protocols when some extra bits are needed now and we cannot modify protocol for some existing participants. No action needed.



Platforms: Win7/64, Linux Mint 22.1 Xia

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12205
  • Debugger - SynEdit - and more
    • wiki
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #63 on: January 29, 2025, 01:20:16 pm »
Did optimization (or speed) become more important than correctness ? 

Correctness based on what definition?

I know you want it to be "mathematical correct" (i.e. following the definition the selected terms have in maths).

But, that is just what you want. That is not what may be defined as correct in terms of the Language, or the specific implementation of the language by the given compiler. (Never mind if you find that acceptable)

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12718
  • FPC developer.
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #64 on: January 29, 2025, 01:22:55 pm »
save people that recklessly filled booleans with casts.
Isn't Pascal supposed to catch and prevent instances of "reckless" programming ?

Yes, to avoid mistakes. But typecasts are the overrides for that safety system, and as such not subject to it.

440bx

  • Hero Member
  • *****
  • Posts: 6155
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #65 on: January 29, 2025, 01:33:06 pm »
That is not what may be defined as correct in terms of the Language, or the specific implementation of the language by the given compiler. (Never mind if you find that acceptable)
No, correct is not  a relative term.  There are a number of incorrect things, among them:

1. the documentation states that TRUE and FALSE are the only values that can be assigned to the boolean type, that's INCORRECT (and it has nothing to do with the fact that I find it unacceptable, it's INCORRECT whether I or anyone else finds it acceptable or unacceptable.)

2. assigning a value greater than 1 to a boolean is INCORRECT.  A boolean is an object that has only two states, therefore it cannot represent a fifth state (the numeral 4 - which is fifth from zero included.)

3. if the compiler considers a value TRUE when it is in an 8/16/32/64 bit structure then that TRUE bit must also be TRUE when represented as a single bit (a bitpacked array element.)  IOW, it cannot suffer a Kafkan mutation when stored in a single bit.

None of the above, have anything to do with what I personally consider correct or otherwise.  As you pointed out, it's either math or logic.



save people that recklessly filled booleans with casts.
Isn't Pascal supposed to catch and prevent instances of "reckless" programming ?

Yes, to avoid mistakes. But typecasts are the overrides for that safety system, and as such not subject to it.

The compiler rejects invalid typecasts.  It should reject those since they are as invalid as "integer(b8) := 4;" 

Accepting those typecast is, by itself, a bug (which has additional undesirable consequences.)

« Last Edit: January 29, 2025, 01:38:34 pm by 440bx »
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12205
  • Debugger - SynEdit - and more
    • wiki
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #66 on: January 29, 2025, 01:47:34 pm »
That is not what may be defined as correct in terms of the Language, or the specific implementation of the language by the given compiler. (Never mind if you find that acceptable)
No, correct is not  a relative term. 

True. Its absolutely defined by the documentation (the FPC Pascal documentation). Or rather the "would be", if it would be error free.

I am not arguing if the doc can be improved. It is fine for me, but maybe could be better. I don't agree with all of your issues with the doc, but that is a different topic.

I was arguing that the implemented behaviour (the one we discussed: or / setneb) is correct.
- I believe the documentation is indented to specify that to be expected. (again, not arguing if it is best written to convey this)
- I believe the documentation has the right to define this. (I.e. if someone creates a Pascal dialect, and that is what fpc is, then they define the rules)

ASerge

  • Hero Member
  • *****
  • Posts: 2477
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #67 on: January 29, 2025, 09:56:34 pm »
The compiler rejects invalid typecasts.  It should reject those since they are as invalid as "integer(b8) := 4;"
Not! Typecast is a useful tool. Each time the sizes match, the compiler must allow typecast.
If someone intentionally misuses it, that's not a reason to reject it.

440bx

  • Hero Member
  • *****
  • Posts: 6155
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #68 on: January 29, 2025, 10:26:50 pm »
The compiler rejects invalid typecasts.  It should reject those since they are as invalid as "integer(b8) := 4;"
Not! Typecast is a useful tool. Each time the sizes match, the compiler must allow typecast.
If someone intentionally misuses it, that's not a reason to reject it.
The size of a boolean is NOT 8 nor 16 nor 32 nor 64 bits, it is 1 bit, again: 1 _bit_.

Therefore any attempt of storing a value greater than 1 in 1 bit is invalid.  The cast is invalid.  "byte(b8) := 4;" is as invalid as "integer(b8) := 4;", the reason: a boolean is 1 and only 1 bit, not 8, not 16, not 32, not 64.  Therefore in both cases the cast is invalid due to a size mismatch.

The reason booleans are stored in integers is because of addressability but that does not change the fact that a boolean is a single bit.  The cast is invalid and the compiler _should_ not allow it.  Additionally, the documentation says that only zero and one are valid for boolean.

Bug 1: the compiler allowed an invalid typecast.
Bug 2: after making a mess as a result of Bug 1, it made a another mess when assigning false to a bit that was being assigned a value it erroneously claimed was true.

What a mess! (but it's an optimized mess... it's fast... that's really important)

Out of curiosity: should the documentation be corrected to let programmers know that values other than zero and one can be assigned to a boolean ?   if you consider that cast valid then you must answer "yes" to that question.  OTH, if the cast is invalid then the documentation is correct as it currently stands (which it is) and it is the compiler that should comply with the documentation (casting is not an excuse... can't cast a string to a boolean... can't cast the Saturn V rocket into a Toyota Yaris... can't cast the numeral 4 into a single bit.)

The real problem is: Delphi accepts "b8 := boolean(4);" which is obviously incorrect but, FPC will use that as the reason to allow it and also allow "ord(b8) := 4;"

Another "writable constant"... that's what happens when a language is abandoned, i.e. there isn't a group of qualified language designers creating and updating standards for it.  oh well... the bug is alive, long live the bug!

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Fred vS

  • Hero Member
  • *****
  • Posts: 3833
    • StrumPract is the musicians best friend
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #69 on: January 29, 2025, 11:52:57 pm »
Bug 1: the compiler allowed an invalid typecast.

But how else to do it, the smallest type size being byte/char (8 bits)?
Pascal does not provide a native one-bit type (which should be used for booleans).
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12205
  • Debugger - SynEdit - and more
    • wiki
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #70 on: January 30, 2025, 12:15:40 am »
But how else to do it, the smallest type size being byte/char (8 bits)?
Pascal does not provide a native one-bit type (which should be used for booleans).

He tries to fit the definition of boolean in FreePascal into (over? around?) the Mathematical concept. Of course that wont work, because Math does (afaik) not describe how to store a boolean value in different media.

Just like Unicode needs the Unicode transfer encoding, a computer program needs defined storage for a boolean.

Of course one could (and we can argue about "one should") chose the smallest available container. But this isn't about maths at that point. So if desired technically it is possible to choose storage/encoding in bigger containers.
In other word, choosing other storage than a single bit is possible. (And one might think of it as good or bad, but that does not change that it can be done).

So Boolean32 chooses to store in a 4byte container. And all 32 bits are part of the value (yes total overkill, don't need them, but still doing it)
It chooses to encode
False = 00000000000000000000000000000000
True = 00000000000000000000000000000001
Any other value is not valid.

If we change the storage we have to change the encoding. In A boolean8 it will be 00000000 and 00000001.

-----------------
And then yes, one could argue the compiler should check the full value each time it accesses such media.

That might be an idea for a "bool range check" option.

Otherwise the code is based on that it only needs to work if values are within the valid encodings. And with that given, we can reduce any code to a check that can distinguish the valid encoded values, and not care about anything else.


Mind this "only deal with valid" is true for many other values too. Enums have the same rules. Other values may also have valid vs invalid. The hidden pointer in ansistring must be nil, or point to accessible mem with a specific data layout.... But there are no plausibility checks when accessing it.
« Last Edit: January 30, 2025, 12:23:13 am by Martin_fr »

440bx

  • Hero Member
  • *****
  • Posts: 6155
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #71 on: January 30, 2025, 12:34:52 am »
Bug 1: the compiler allowed an invalid typecast.

But how else to do it, the smallest type size being byte/char (8 bits)?
Pascal does not provide a native one-bit type (which should be used for booleans).
True, the smallest _addressable_ size is byte.   In the case of boolean, the type size and the storage size can differ (they don't in the case of a bitpacked array of boolean).   When dealing with booleans the compiler should use the type size _not_ the storage size.  The storage size affects addressability but never affects the fact that a boolean is a single bit.  The compiler should make that distinction.

All that said, since Delphi accepts the invalid typecast, it is rather unlikely that this bug will be corrected (because Delphi compatibility is more "important" than correctness.)

It's also interesting that the majority of posters, including myself, consider the cast to be invalid but, there is no mention that the compiler should not allow the invalid cast.  IOW, the compiler accepts something it should not accept but, if and when a programmer uses that invalid construction, it's not the compiler's fault, it's the programmer's.  ain't that great ?  Talk about the guilty party pointing the finger at someone else and saying "he did it !"



@Martin,

You're right that math does not say how a boolean should be stored BUT, it does say that it has only two states and, in a computer that's a bit.  No way around it.  boolean = 2 states = 1 bit.

It doesn't matter how it is stored, the number of states is the same: 2 and only 2. Therefore, by definition, a boolean occupies a single bit.

Due to addressability reasons, that single bit is usually part of a byte or word or dword or qword but, no matter the container, it is and will always be a single bit. 



The bottom line is simple: no matter how many bits there are in the container, only 1 bit is significant, the rest are not and they are not part of the type therefore the compiler should NOT allow their being manipulated because they are not used to represent the type's value.

It is incorrect and meaningless for the compiler to allow the non-significant bits to be manipulated and, if for convenience or compatibility with Delphi, it decides to allow it then those bits should always be ignored because they are not part of the data type, just "tolerated" guests in the container to enable simple addressability.




FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12205
  • Debugger - SynEdit - and more
    • wiki
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #72 on: January 30, 2025, 12:42:33 am »
And what if it was stored with a "checksum" => choosing multiple bits that must have a pattern, so that if any one bit rotted then it would be detected?

I guess you would not say that hardware with error correction bits is unable to store boolean values?

I know, we don't use the encoded value as a such a pattern. Fpc doesn't check the validity. But that isn't the point of my above statement. I am simple saying there are reasons that could warrant storage with multiple bits - all equally significant.

So it is not some given that it must be a single bit.

And if it is not a given, then it may be a multi bit encoding - even for no good reason at all. (or at least, no reason you seem to see as good)

440bx

  • Hero Member
  • *****
  • Posts: 6155
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #73 on: January 30, 2025, 01:27:21 am »
And what if it was stored with a "checksum" => choosing multiple bits that must have a pattern, so that if any one bit rotted then it would be detected?
Obviously a checksum applies only to a sequence of bits.  Each bit in that sequence is still one of two possible states, no way around that and the checksum is a separate entity.  Parity and ECC implement detection and limited recovery in the case of ECC but, the bits are still just bits, 1s and 0s, checksum, ecc or any other checking mechanism.

IOW, a checksum changes absolutely nothing.  Bits are still two states and a boolean is still a single bit.  It doesn't matter if there is one boolean or 1 million of them, they are all 1 bit.  The presence of additional bits to ensure correctness changes nothing.

Do you consider the documentation statement:
Quote
Free Pascal supports the Boolean type, with its two predefined possible values True and False.
These are the only two values that can be assigned to a Boolean type.
to be true or false ?

It sounds boolean(4) to me but, I strongly believe the compiler should fully enforce it without exception.



FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Fred vS

  • Hero Member
  • *****
  • Posts: 3833
    • StrumPract is the musicians best friend
Re: likely bug in FPC v3.2.2 handling of booleans
« Reply #74 on: January 30, 2025, 01:29:36 am »
And what if it was stored with a "checksum" => choosing multiple bits that must have a pattern, so that if any one bit rotted then it would be detected?

Ha, ok, it is (maybe) why it exists type boolean32.  :-\
But how would you do to create a "checksum" (very nice idea to check if the value has all the right).

With this example:

Code: Pascal  [Select][+][-]
  1. var
  2. abol : boolean32;
  3. ...
  4. begin
  5. abol := boolean32(123456789);  // the integer > 0 that will set abol as "true"
  6. writeln(word(abol));

the result is 52501, so what is the relation with 123456789?
(It is more for the game, not sure it would be useful for something)
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

 

TinyPortal © 2005-2018