Recent

Author Topic: Boolean type  (Read 6577 times)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11137
  • Debugger - SynEdit - and more
    • wiki
Re: Boolean type
« Reply #30 on: April 14, 2025, 03:41:53 pm »
All the asm is correct as long as the user does not break the content of the variable.

Without the user violating the contract, an initialised boolean var can only have ordinal 0 or 1. And then all the test are correct. If testing for 0 fails, then it must be 1, there is nothing else that it can be.

As soon as the user broke that contract, the tests are no longer valid. But that is correct behaviour. If you break the contract, then it stops being boolean, and you can't do bool operations on it (at least not expect them to work).


It is the same as
Code: Pascal  [Select][+][-]
  1. TStringList(1).Count
That does not work.

However (if it compiles)
Code: Pascal  [Select][+][-]
  1. TStringList(random(high(ptruint))).Count
might return some number as count (sometimes).

Even if it is not a list with any items in it....

But, that is breaking the contract, so you can't complain about whatever happens.


There is a different contract though
Code: Pascal  [Select][+][-]
  1. var o: TObject;
  2. begin
  3.   o := TObject(1);
  4.   writeln(ptruint(o)); // should write 1

Of course datasizes must be taken into account.

And similar for LongBool and boolean32 or 64 or .... whatever they all are called. Even for just "boolean", if you know the size it will have in a given context (as it's size is known to vary, depending on the context in which it is declared).

« Last Edit: April 14, 2025, 03:44:06 pm by Martin_fr »

440bx

  • Hero Member
  • *****
  • Posts: 5267
Re: Boolean type
« Reply #31 on: April 14, 2025, 04:12:13 pm »
Without the user violating the contract, an initialised boolean var can only have ordinal 0 or 1.
Some people say that Pascal is a strongly typed language.  I believe it is rather reasonable to expect a strongly typed language to enforce what values can be assigned to a variable, particularly when the value _obviously_ violates the data type.

For instance, no amount of typecasting can assign a string of 16 characters to an integer, simply because not only the types don't match but also because their sizes are different. 

The fact is, a boolean is a single bit and the compiler FAILS to _treat_ it as such.  That's why it allows INVALID typecasts and, as a result of that, it ends up creating the mess it has made.

The compiler should NOT accept a typecast such as "boolean(2)" because the numeral 2 does NOT fit in 1 bit.  The TRUE size of a boolean prevents that but, FPC is oblivious to that, which is why it makes a mess.  In addition to that, the code it generates to test for logical values is more often wrong than right because it makes the completely INVALID assumption that only 1 bit is set in spite of the fact that it accepts casts such as boolean(15) which set multiple bits.  IOW, the compiler makes assumptions it allows the programmer to violate (some strong typing there!)

And to put a cherry on top of that mess, the documentation states that a boolean in FPC is zero or 1.  Yes, that and the Pope is a Victoria Secret model.

When someone points out those bugs, the magic words "undefined territory" are dusted off.  I wonder what's undefined... a boolean is a single bit and any value greater than 1 does not fit in a single bit.  What's is undefined there ?

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11137
  • Debugger - SynEdit - and more
    • wiki
Re: Boolean type
« Reply #32 on: April 14, 2025, 05:06:46 pm »
Some people say that Pascal is a strongly typed language.

Well, the exact meaning (or absence of meaning) of this is an entirely different discussion. In this context, all we need to know, that typecast are possible, and that typecast data breaks any contract for the value relating to type...  => That is just how it is. (good, bad, ugly, ... whatever)

Quote
  I believe it is rather reasonable to expect a strongly typed language to enforce what values can be assigned to a variable, particularly when the value _obviously_ violates the data type.
And there we go.

You, define that "typecasting" is not reasonable, even though it is a language feature. You then - after ignoring how typecasting works - complain that boolean does not work, if used after typecasting.

Because you ignore how typecasting works, you ignore that boolean (like any other type) is not even expected to work "type specific" after a typecast was made. As it is not expected (i.e. as the behaviour is declared "undefined") your expectation is wrong.

And to reiterate: "undefined" may have the same outcome as any of the defined possibilities. It may, or may not, and that may alter depending on anything, any change, any whatever.

As I said, you mix across several feature boundaries, in such a way that the result of your "mixing" becomes wrong, even *if* individual parts are/were not.



As for the size fitting and type casts => that is a different discussion. That is about type casting and types that have context dependent sizes.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12186
  • FPC developer.
Re: Boolean type
« Reply #33 on: April 20, 2025, 01:02:21 pm »
Without the user violating the contract, an initialised boolean var can only have ordinal 0 or 1.
Some people say that Pascal is a strongly typed language. 

But typecasts (and some other things, Borland derived pascal unions are not very safe) mostly circumvent that.

A strong typed language is not necessarily the same as "safe" language.


440bx

  • Hero Member
  • *****
  • Posts: 5267
Re: Boolean type
« Reply #34 on: April 20, 2025, 01:44:25 pm »
The problem is that FPC (and likely Delphi) fail to enforce the fact that a boolean is a single bit type.

The fact that the single bit is in a byte/word/dword/qword container is irrelevant.  It's that way to  make addressing convenient (can't directly address a single bit) but, the compiler should _never_ accept values other than 0 or 1 because they simply don't fit in one bit and there is no typecast that can change that.

Typecasting a value greater than 1 into a boolean is simply an invalid typecast, because there is a size mismatch. 

Failure to treat a boolean as what it really is, is what causes all these conveniently named "undefined territory" cases.  The territory is very well defined: a boolean is 1 and only 1 bit. 

The other problem is that allowing the typecast invalidates what the documentation states, that a boolean is either 0 or 1 (that's what it should be), since the compiler allows typecasting values other than 0 and 1 into a boolean, the documentation is _incorrect_: the values of a boolean are _not_ restricted to zero and 1.

The part I really like is that expressions that are all TRUE aren't necessarily logically equal to each other.  TRUE <> TRUE... fits nicely in the "writable constants" bin.

Sadly, it won't be fixed.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12186
  • FPC developer.
Re: Boolean type
« Reply #35 on: April 20, 2025, 03:21:22 pm »
The problem is that FPC (and likely Delphi) fail to enforce the fact that a boolean is a single bit type.

That would be only needless cycles to check that, since only legal constructs can violate that. (with the exception of an union record).

440bx

  • Hero Member
  • *****
  • Posts: 5267
Re: Boolean type
« Reply #36 on: April 20, 2025, 03:35:03 pm »
The problem is that FPC (and likely Delphi) fail to enforce the fact that a boolean is a single bit type.

That would be only needless cycles to check that, since only legal constructs can violate that. (with the exception of an union record).
No cycles are needed. 

The compiler should simply refuse casts such as boolean(5)  which is done at compile time.

At runtime, the compiler should use correct code instead of the incorrect code it's using now.  The correct code is to and with 1 to determine the value of the bit instead of doing a test al, al or test ax, ax which tests an entire nibble or byte, which is blatantly incorrect since that tests a complete nibble or byte (or word, dword, etc, as if it were a BOOL instead of a boolean.)

FPC is generating the same code for a boolean as it does for a BOOL and that is wrong.

It wouldn't cost a single additional clock cycle to do it right and, as a bonus, it would make the documentation right too.

Currently, there is no boolean type in FPC, there is only BOOL.  Boolean is just a different name (a synonym) for something that behaves the same way.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11137
  • Debugger - SynEdit - and more
    • wiki
Re: Boolean type
« Reply #37 on: April 20, 2025, 04:16:48 pm »
The problem is that FPC (and likely Delphi) fail to enforce the fact that a boolean is a single bit type.

The means of storage and/or representation are absolutely not relevant at all.

Boolean logic (when and where applied) needs 2 states. True or false. The correctness of the logic works, it works even if you store the states as strings, so long as there are only 2 possible strings that can ever occur. [1]

The representation/storage is an implementation detail. It does not matter do the user. It does not matter for the program to run correctly.

In fact, programs written in Pascal (and other languages) work 100% correct (in terms of boolean logic), never mind how the store the 2 states. And more so, they also work correct if that storage/representation changes (e.g. packed vs non packed).

If you were right, and if representation mattered, then correct boolean algebra on a piece of paper would be impossible. Because, even if the person writing it down would use 0 and 1, each 0 or 1 that they write looks slightly different. A hand written 0 (or 1) is a form that approximates a certain shape. And "approximates" makes it clear: it varies. There is more than a single form that represents 0, and more than a single form that represent 1.

And just because on a computer you can use a single bit, does not mean you have to. The underlaying implementation just has to be aware of how it stored the value. And then correctly recognise the stored value. And it does exactly that..
The fact that you use ways to break the contract and it then breaks, does not mean that it is wrong. It means your usage example is wrong.



[1] "can ever occur" => within the defined parameters of usage. (On a piece of paper I can also write down "my guess: true". And that also breaks it...
« Last Edit: April 20, 2025, 04:19:36 pm by Martin_fr »

ASerge

  • Hero Member
  • *****
  • Posts: 2408
Re: Boolean type
« Reply #38 on: April 20, 2025, 07:12:22 pm »
The compiler should simply refuse casts such as boolean(5)  which is done at compile time.
Hands off type casting. This is a convenient tool. If the programmer doesn't know what it is and doesn't know how to apply it, don't let him touch it. If he knows, but uses it with an error, it's his fault, not the compiler's. Personally, I'm already annoyed when the compiler issues a warning when casting between Pointer and PtrUInt.
Specifically for the Boolean type, castings are almost always unnecessary. Instead of a Boolean(variable) specify a expression (Variable <> 0).

jamie

  • Hero Member
  • *****
  • Posts: 6888
Re: Boolean type
« Reply #39 on: April 20, 2025, 07:30:25 pm »
I can't believe the flack going back and forth here. It would look like a few are running a campaign to put the compiler back to the stone ages.

  And yes, Delphi allows this, and it seems the dev's of Delphi understand more of what's going on than this few here.
  Subscription to Delphi is high but that is the bullet that has to be taken.

Good luck.
Jamie

The only true wisdom is knowing you know nothing

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12186
  • FPC developer.
Re: Boolean type
« Reply #40 on: April 20, 2025, 08:39:12 pm »
The problem is that FPC (and likely Delphi) fail to enforce the fact that a boolean is a single bit type.

That would be only needless cycles to check that, since only legal constructs can violate that. (with the exception of an union record).
No cycles are needed. 

The compiler should simply refuse casts such as boolean(5)  which is done at compile time.

Even if I'd agree that that something like that would be desirable(and I don't), that only would fix the case where the compiler can statically verify that the value of the typecast is out of bounds. Inconsistent.

440bx

  • Hero Member
  • *****
  • Posts: 5267
Re: Boolean type
« Reply #41 on: April 20, 2025, 09:41:38 pm »
This is really amazing.

The compiler already detects all kinds of invalid typecasts.  it simply FAILS to detect that typecasting a value greater than 1 to a boolean is INVALID.  Read it again, slowly please: typecasting any value other than 0 and 1 to boolean is INVALID.   It's not rocket scientce, it's that simple.

In addition to that, look at the code the compiler generates for a boolean: it is WRONG.  The compiler is testing for nibbles, bytes, words, etc instead of testing a single bit as it should. 

There are 3 problems: 1. the compiler allows an invalid typecast.  2. the compiler generates code that is wrong for testing the value of a boolean.  3. the documentation states what it SHOULD be, NOT what it IS.

FACT: FPC does NOT implement the boolean type, it implements the BOOL type.

The thing it calls boolean is flawed which is why there are times when, using booleans, there are cases where TRUE <> TRUE.  Another writable constants "breakthrough".

Anyway... let's agree to disagree.   I won't be fixed anymore than FPC is going to implement static variables.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11137
  • Debugger - SynEdit - and more
    • wiki
Re: Boolean type
« Reply #42 on: April 20, 2025, 10:37:35 pm »
This is really amazing.
How you keep trying to make up a fault that does not exist. At least not in the faintest fashion of how you portrait it?

Quote
Read it again, slowly please: typecasting any value other than 0 and 1 to boolean is INVALID.   It's not rocket scientce, it's that simple.
It is invalid, if and only if you want the value to be valid boolean data.

The language allows storing arbitrary data (with size limits) in any type. TStringList(1) is not giving you a stringlist. But you can store the data 1 in a variable of that type. Yes, its an abuse. But it's an allowed abuse. It's part of the language. (again: good, bad, ugly, beautiful, whatever...)

So yes, the compiler should allow you to store arbitrary data (within size limits) in a variable of type boolean. Even if it means the data is not valid for the type, and the variable no longer functions as if it was of the type. That is the price to pay. And it is by design.

Quote
In addition to that, look at the code the compiler generates for a boolean: it is WRONG.  The compiler is testing for nibbles, bytes, words, etc instead of testing a single bit as it should. 
Read my section on "representation" very very very slowly. I had discussions with you before, I know you are way above average, and ** if you want ** you can easily comprehend it.

The tests in the generated asm are correct. And I explained that in great detail before. Another good bit of explanation for a slow read...


About representation: You made at some time the point that true and false should ( or maybe you even said "must") be represented by zero and one.

Given that, then there are plenty of documents, books, papers, ... that (according to you) wrongly use True/False or T/F or even translation there of.
And how do we represent those two numbers? #$30 and #$31 ? Short-strings with the text one/zero?

Or is there an official all binding definition that say boolean value must be represented by a single point in an electrical circuit that has a specific current for each of the two states? How was boolean ever done on paper?




440bx

  • Hero Member
  • *****
  • Posts: 5267
Re: Boolean type
« Reply #43 on: April 21, 2025, 12:10:10 am »
Quote
Read it again, slowly please: typecasting any value other than 0 and 1 to boolean is INVALID.   It's not rocket scientce, it's that simple.
It is invalid, if and only if you want the value to be valid boolean data.
That's right, it's invalid.   If it's invalid then why does the compiler allow it ??  there are plenty of examples of invalid typecasts the compiler does NOT allow, why does it allow that invalid typecast ?   It couldn't possibly be because it's a bug ... could it ?

no value greater than 1 fits in a boolean and the compiler should know and enforce this _obvious fact_.   but... no, it's the programmer's fault the compiler allows typecasting the space shuttle into a ham and cheese sandwich.  Bad, bad programmer!


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

nanobit

  • Full Member
  • ***
  • Posts: 173
Re: Boolean type
« Reply #44 on: April 21, 2025, 12:26:08 am »
If it's invalid then why does the compiler allow it ??

A long thread, and boolean(100) is in reference.
boolean( ordinal_expression), the so-called value typecast,
is safe (producing valid value) only when the lowest byte of the expression result is $00 or $01.
The topic is broader: byte() and all other ordinal types.
« Last Edit: April 21, 2025, 12:30:30 am by nanobit »

 

TinyPortal © 2005-2018