Recent

Author Topic: Boolean type  (Read 6644 times)

jamie

  • Hero Member
  • *****
  • Posts: 6889
Re: Boolean type
« Reply #45 on: April 21, 2025, 12:50:52 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.
Now you are just trying to twist it around to a different narrative. That isn't what the docs states that you pointed to.

The value 100 does not result to a 1, because it's an event number so that means the first bit isn't set so the value of 100 is still true.
I didn't see any "$" Infront of that statement?

Boolean(1) would be that, but it does not matter because the compiler does the proper actions of testing for 0.

Bool values come in any value for the true state, it does not have to be $01. it's whatever size of the Boolean type dictates the max range of the
True value, other than 0 which is always false.

 The TRUE type in the compiler for byte size bools mainly the "Boolean" is $01 when you are directly assigning a Boolean from the TRUE.
 
 Other values could be -1 for true when assigned directly in code depending on the size of the bool type, it's still TRUE regardless.

 Although I haven't been using FPC much lately and hanging in the Delphi code, I hate to see those with an agenda to butcher the compiler get their way.

 Maybe they pay for Delphi too and are aggravated with the cost and can't stand for others to enjoy something without the cost.


The only true wisdom is knowing you know nothing

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11164
  • Debugger - SynEdit - and more
    • wiki
Re: Boolean type
« Reply #46 on: April 21, 2025, 01:30:51 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 ?? 
"if you want the value ..."

Not all users may care about that. And if the user does not care about it, then it becomes a valid option.

There are even valid cases of de-referring nil (on platform with protected zero page)...

Quote
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 ?
Because it can be valid, depending on the situation, and expectation.


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

And again, you twist your description ever so slight....

Depending on how a boolean variable is declared, value greater than 1 can fit into them. If they do its a valid typecast.
A typed value and its storage are 2 different things.

If you had said "no value greater than 1 [or other than 0 or 1] is a valid boolean value" => then that is correct (in context of the boolean type discussed here).

But that does not mean that storage needs to be limited to that. (Already explained to abundance / please re-read)

You can say, its a waste of storage. But then the alternative is to pay with more execution time. Both give you the same valid results. And with bitpacked you can even chose how you want to pay.



If you want a language that does not allow such stuff => well that is fine. But Pascal already allows it. And people use it. So changing it is unlikely.

But even if it would be changed in future, as of today it is a feature, and not a bug.

You may judge it as a bad design... Your opinion. ... Well depends what the design is indented for.

440bx

  • Hero Member
  • *****
  • Posts: 5294
Re: Boolean type
« Reply #47 on: April 21, 2025, 03:50:37 am »
Because it can be valid, depending on the situation, and expectation.
really ?  how about you provide at least one example where typecasting the value 18 to boolean would be valid and, what would the result mean ? (if anything at all)

Just to make sure, typecast to a boolean NOT a BOOL.  Thank you! :)

If you want a language that does not allow such stuff => well that is fine. But Pascal already allows it.
I had no idea that Pascal allows putting a value, such as 18, in a single bit but, I did know that FPC tries (unsuccessfully, of course!)  I had heard of "fat bits" but I don't think their purpose was to accommodate values greater than 1.
(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 #48 on: April 21, 2025, 06:04:21 am »

A long thread, and boolean(100) is in reference.
boolean( ordinal_expression), the so-called value typecast,

Refining my own statement:
boolean(100) is boolean( assignment_incompatible_ordinal_expression), producing invalid boolean.
By contrast, boolean( someLongbool) would be assignment-compatible and converted to 0/1.
Assignment-compatible expressions normally don't need typecasting,
but typecasting can help to select certain overloaded functions.
« Last Edit: April 21, 2025, 07:35:46 am by nanobit »

Thaddy

  • Hero Member
  • *****
  • Posts: 16945
  • Ceterum censeo Trump esse delendam
Re: Boolean type
« Reply #49 on: April 21, 2025, 06:47:25 am »
That is: try to use a value where the first bit is cleared e.g. given $0 is false $1 should be true, right? (that is the definition)
Alas, $2 is also right......and does not have that bit set, etc.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11164
  • Debugger - SynEdit - and more
    • wiki
Re: Boolean type
« Reply #50 on: April 21, 2025, 10:14:22 am »
Because it can be valid, depending on the situation, and expectation.
really ?  how about you provide at least one example where typecasting the value 18 to boolean would be valid and, what would the result mean ? (if anything at all)

I said typecasting "data". Storing it in a variable that happened to be of type boolean. I did not say 18 would become boolean.

The variable holds arbitrary data after the typecaset. Just like TStringlist(1).

Would you agree, that TStringlist(1) does not make 1 a TStringList? If yes, then why do you expect Boolean(18) to make 18 boolean?


Quote
Just to make sure, typecast to a boolean NOT a BOOL.  Thank you! :)
Neither.

A BOOL should still work with AND/OR/... but as you yourself pointed out Boolean(18) does not.

TStringlist(1) also does not work if you try to use it as Stringlist (e.g. try to invoke count)

Quote
If you want a language that does not allow such stuff => well that is fine. But Pascal already allows it.
I had no idea that Pascal allows putting a value, such as 18, in a single bit but, I did know that FPC tries (unsuccessfully, of course!)  I had heard of "fat bits" but I don't think their purpose was to accommodate values greater than 1.

EDIT: answer for if you talk about bitpacked....

Clever, you picked one of the few references of typecasting that I made without adding "limited by size". If you read my overall posts then you will notice that point.


« Last Edit: April 21, 2025, 10:38:05 am by Martin_fr »

440bx

  • Hero Member
  • *****
  • Posts: 5294
Re: Boolean type
« Reply #51 on: April 21, 2025, 10:44:16 am »
I said typecasting "data". Storing it in a variable that happened to be of type boolean. I did not say 18 would become boolean.

The variable holds arbitrary data after the typecaset. Just like TStringlist(1).

Would you agree, that TStringlist(1) does not make 1 a TStringList? If yes, then why do you expect Boolean(18) to make 18 boolean?
The point is that it is totally nonsensical and wrong to allow typecasting a value greater than 1 to a boolean.  It is simply wrong for the compiler to allow that.  There are plenty of invalid typecasts that FPC disallows, it should also disallow that one because it is invalid.

After that, FPC should be corrected to generate correct code for testing boolean values.  instructions such as "test al, al", "test ax, ax", etc are  appropriate to test for BOOL values but totally wrong when it comes to testing boolean values because it is taking into consideration a whole lot of bits that are NOT part of the representation of a boolean.

It's like if someone coded "if DwordVariable = 0 then..." and the compiler generated "test rax, rax" to figure out if the value is zero, that's completely wrong because rax is 64 bits and a DwordVariable is only 32 bits therefore the compiler is taking into account 32 additional bits that are not representative of the variable's value.  It's exactly the same thing with a boolean.  A boolean is a single bit and testing more than 1 one to determine the value of a boolean variable is WRONG, no two ways about it.  It's as wrong as testing rax to determine the value of a 32 bit variable.

As I stated before, this isn't rocket science.  Actually, rather trivial stuff.

(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: 11164
  • Debugger - SynEdit - and more
    • wiki
Re: Boolean type
« Reply #52 on: April 21, 2025, 11:15:20 am »
As I stated before, this isn't rocket science.  Actually, rather trivial stuff.

I agree on it is simple. Except, the way you misrepresent it.


I have no problem if you don't like it, or if you ask for a change in the language definition (though I am strongly opposing such a change).
I have an issue that you twist the truth.

In case of asm generated for boolean tests. The are correct. Show me a case (where you do not break the contract) where they do return the wrong result.

If you do break the contract (e.g. by typecasting / similar / otherwise) then the data is no longer boolean (I think we established that). It may be stored in a variable typed as boolean, but the data is not. And the logic is then supposed to not work.
So therefore if you break the contract... The generated asm is by design not indented to work. And it does just that.

But if you keep to the contract it works.

The contract for a non-bitpacked 32bit sized boolean variable is, that it can contain 2 states. Those states are represented as %00000000000000000000000000000000 and %00000000000000000000000000000001. And only as those two.
And if that contract is hold up, then the asm is correct. If it is not the one state, then it must be the other state. There is no other option within the contract.

And yes, you could store the value with less storage. But for boolean logic to work the representation can be defined in any way. It just has to be defined for 2 states. And it is defined for 2 states.
On Paper I can choose: 0/1 T/F True/False Wahr/Falsch +/- .... So long that any other reader of that paper knows what I used.

440bx

  • Hero Member
  • *****
  • Posts: 5294
Re: Boolean type
« Reply #53 on: April 21, 2025, 12:28:33 pm »
In case of asm generated for boolean tests. The are correct. Show me a case (where you do not break the contract) where they do return the wrong result.
There is no "contract" that a programmer has to tip-toe around to accommodate incorrect code.  "test al, al", "test ax, ax", etc are appropriate for BOOL and completely wrong for boolean.  No programmer has to carry the burden of accommodating wrong code.  There is no contract that says, the compiler generates incorrect code and you have to program to avoid it.  Also, a boolean is 1 bit (2 states) that's mathematical and no "contract" can change that, the same way that no "contract" can stuff a value greater than 1 into 1 bit.

FPC cut corners and treats boolean as if it is the same as BOOL and, of course, that doesn't always work (for obvious reasons.)  No one has to accommodate that corner cutting stuff, the compiler should do it correctly then, everything would work as it should (and, BTW, then it would also work as documented which would be a nice "bonus".)

There is a contract we can make: we can agree to disagree because, FPC current behavior with booleans is wrong and unacceptable but, it is obvious that we won't agree.
(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: 11164
  • Debugger - SynEdit - and more
    • wiki
Re: Boolean type
« Reply #54 on: April 21, 2025, 12:39:59 pm »
There is no "contract" that a programmer has to tip-toe around to accommodate incorrect code. 

Well I disagree. I say there is a contract, and it becomes visible when using typecasts.

I don't see it as tip toeing, but hey personal perception can't be argued. I know what I do when I typecast, so its an easy walk in the park for me.

And well, if you don't use typecast (or similar) then you can't break the contract, so you don't need to care about it (it is all taken care of for you).
So, don't use typecasts (or any similar means), and you got what you want. Just don't complain if others want to dance that dance.

And yes, I know the problem is you may have to interact with code by others. You don't have that choice. If you need your own Pascal build on your preferred definitions => fork it.

TRon

  • Hero Member
  • *****
  • Posts: 4369
Re: Boolean type
« Reply #55 on: April 21, 2025, 12:44:12 pm »
Once upon a time there was a young lad. He wanted to write his own compiler, based on an existing compiler. He opted to make his compiler source-compatible to the existing compiler.

iow beating a dead (and the wrong) horse. several times over and over again. sailing bridges crossing burning ships or something like that.

Today is tomorrow's yesterday.

Zoran

  • Hero Member
  • *****
  • Posts: 1948
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Boolean type
« Reply #56 on: April 21, 2025, 04:17:02 pm »
It's not hard to implement the real boolean type, a simple "and reg, 1" does it.

Why do you claim that?
I wonder where in the fpc documentation you found grounds for the expectation that the value of bit 0 should represent the boolean value. And I cannot understand on what grounds you claim a particular variant of implementing boolean to be "real boolean", and any other not.
So, in this post, when I say Boolean, I shall mean one-byte Boolean type as documented in fpc of course, not something you call "real boolean".

The compiler behaves as documented and expected with a Boolean variable, when it contains 0 or 1.
If the variable contains something else, the boolean operations on it might not behave as you expect, but then you actually should not expect anything for certain, as nothing is documented.

But then it is important to see if it is possible that a boolean variable contain anything but 0 or 1, unless the unsafe operations were used on this variable.
I think no, it is not possible. And if the unsafe operations were used, then the programmer is responsible to make sure the variable contains 0 or 1 and nothing else, before performing boolean operations on it.

So let's see how we can get anything but 0 or 1 in a boolean variable.
1. When using the variable declared locally which was not initialised prior to the usage.
2. When using explicit casting - that is when in your code you are using Boolean(SomethingWhichIsNotBoolean).
3. When using "absolute" directive when declaring two or more vars, one of which is boolean.
4. When declaring a Boolean variable inside a record with case (called union in C), so that this variable shares the same memory space with another variable of some other type.
5. Using unsafe routines such as System.move (or fillchar) to write to your Boolean variable

Do you know of some other situation?

Then, let's see:
1.
- The compiler does not implicitly initialise local variables. It is documented and the memory which your variable occupies can contain anything. Were the variable initialised explicitly, it would contain nothing else but 0 or 1.

2.
- When explicit casting is involved, the compiler must not do any checking, that's the point of explicit casting. Explicit casting must not adjust bits in a variable, that's the one and only thing we can rely on.

3 and 4.
- Here the Boolean variable shares the same memory with another variable, the compiler does not give any guarantees, it's up to you to take care what the variable contains when using it.

5.
System.move is not safe. That is what it is for, its power lies in having no checks by the compiler. Hence the responsibility is again on the programmer.

When a boolean variable contain 0 or 1, then the behaviour is defined.

In all these cases given above the compiler must not perform any checking, so the variable can contain any of 256 possible bit patterns.
Then if you want to perform boolean operations on such a variable directly, you cannot blame the compiler when you get unexpected results, actually there are no unexpected results, anything can be expected.

For instance, if a boolean variable contains the value 2, then what you should ask yourself first is whether you used some unsafe operation on it. Then no expectations are justified, it's your responsibility to handle it according to your needs. For example in one of these three ways:
Code: Pascal  [Select][+][-]
  1. var
  2.   B: Boolean;
  3. begin
  4. // ...
  5.    if Byte(B) <> 0 then // you want to treat any non-zero as true
  6.       DoSomething;
  7. // ...
  8.    if Byte(B) and 1 <> 0 then // you want bit 0 set or reset to represent true and false respectively
  9.       DoSomething;
  10. // ...
  11.    if Byte(B) and 4 = 0 then // you want bit 3 unset to represent true, and bit 3 set to represent false
  12.       DoSomething;
  13. // ...
  14. end;
  15.  

And many more possibilities. All equally valid.
Swan, ZX Spectrum emulator https://github.com/zoran-vucenovic/swan

440bx

  • Hero Member
  • *****
  • Posts: 5294
Re: Boolean type
« Reply #57 on: April 21, 2025, 06:50:32 pm »
It's not hard to implement the real boolean type, a simple "and reg, 1" does it.

Why do you claim that?
because it actually is that simple.

I wonder where in the fpc documentation you found grounds for the expectation that the value of bit 0 should represent the boolean value.
The documentation does not state which bit should be used (and it shouldn't) but, the most sensible choice is bit 0.  That said, if FPC wanted to pick bit 3 or any other bit for that matter, it can be my guest.  The only thing that matters is that ONLY A SINGLE BIT be used to represent a boolean, not 2, not 3, not 8, not 16, not 32, not 64 because a boolean is a single bit. 

That said, STRICTLY for addressing purposes, compilers will "package" whatever bit they choose into a byte, word, dword or whatever other container.  That makes no difference, it's just there to make the bit easily addressable.  Nothing else (at least in a correct implementation.)

And I cannot understand on what grounds you claim a particular variant of implementing boolean to be "real boolean", and any other not.
So, in this post, when I say Boolean, I shall mean one-byte Boolean type as documented in fpc of course, not something you call "real boolean".
The container which can be a byte, a word, a dword or a qword, is totally irrelevant.  The only thing that matters is a single bit, one the compiler chose to represent the boolean value.

Here is a very simple explanation that I believe most should be able to understand: You can put a grain of sand in a 9 cubic meter container.  The container is NOT the grain of sand and neither is the grain of sand, the container.  Neither is equal to the other.  Same thing with a boolean, put the bit in whatever container you want, the only thing that makes the boolean is whatever bit has been chosen to represent it.  The container, in the case of a computer is simply to make that one bit directly addressable.

FPC does NOT implement booleans, it implements C's BOOL.  When it comes to the boolean type, it only works as long as it is considered a BOOL and NOT a boolean.   That's the reason why when using booleans, FPC can end up in situations where TRUE <> TRUE but, when the compiler does that atrocity, it's "undefined territory" (but, of course, it is!) just like when a drunk drives into a tree, it's the tree that got in the way (obviously!.)

I'm tired of explaining the obvious.

If FPC lovers want to defend FPC no matter what, that's fine with me.  I'm done!  I won't explain the obvious again to people who refuse to understand.

You are all absolutely right! enjoy!

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

simone

  • Hero Member
  • *****
  • Posts: 665
Re: Boolean type
« Reply #58 on: April 21, 2025, 09:06:47 pm »
As often happens, I am part of the minority that agrees with 440bx. In a nutshell, the reason for my position lies in some inconsistent behaviors of fpc with boolean type, such as the following:


Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$mode ObjFpc}
  3. var
  4.   B1, B2 : boolean;
  5. begin
  6.   B1:=Boolean(1);
  7.   B2:=Boolean(2);
  8.   writeln(B1);        //print TRUE
  9.   writeln(B2);        //print TRUE
  10.   writeln(B1 and B2); //print TRUE
  11.   writeln(B1=B2);     //print FALSE!!!
  12.   readln;
  13. end.
« Last Edit: April 21, 2025, 09:08:36 pm by simone »
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

dseligo

  • Hero Member
  • *****
  • Posts: 1507
Re: Boolean type
« Reply #59 on: April 21, 2025, 09:12:07 pm »
As often happens, I am part of the minority that agrees with 440bx. In a nutshell, the reason for my position lies in some inconsistent behaviors of fpc with boolean type, such as the following:


Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$mode ObjFpc}
  3. var
  4.   B1, B2 : boolean;
  5.  
  6. begin
  7.   B1:=Boolean(1);
  8.   B2:=Boolean(2);
  9.   writeln(B1);        //print TRUE
  10.   writeln(B2);        //print TRUE
  11.   writeln(B1 and B2); //print TRUE
  12.   writeln(B1=B2);     //print FALSE!!!
  13.   readln;
  14. end.

Problem is in line 8. Don't use casting if you don't know what you are doing. Correct line 8 and compiler will work as it should.

Do you also use uninitialized variables? It is similar as you did here. Programmer's error. Compiler will protect you to some limit.

 

TinyPortal © 2005-2018