Lazarus

Programming => General => Topic started by: LemonParty on April 13, 2025, 07:04:14 pm

Title: Boolean type
Post by: LemonParty on April 13, 2025, 07:04:14 pm
Hello.

I am interesting if Boolean type represented as $1(for True) on all platforms or it may be platforms where True value may be some nonzero value like $FF.
Title: Re: Boolean type
Post by: jamie on April 13, 2025, 07:58:10 pm
True is always any value other than 0

Many APIs in windows use a return value as both a value to indicate something and also as a true or false at the same time.

Code: Pascal  [Select][+][-]
  1.  If lastValue then do_something with LastValue;
  2.  

 There if  LastValue isn't 0 then it's true but as you can see it also is used for value returns, too.

 Finding the value of 1 in code for a true is most of the time just a convenience to make the toggling logic easier for the compiler to make code more efficient code in complex bool code, it really has no designation.


Jamie
Title: Re: Boolean type
Post by: Martin_fr on April 13, 2025, 08:52:16 pm
True is always any value other than 0

NO !

Or, well it depends what we are talking about.

"Boolean" as defined by Pascal is an enumeration. The ordinal value of False and True are 0 and 1.

Casting any other value to boolean (e.g.  Boolean(9) ) is not allowed, and results in undefined behaviour. It may sometimes behave as True and sometime as False. (If you try it, and don't get that, then you did not try hard enough)


In "boolean" expressions numbers don't have a "boolean" value.   If 1 then ...; does not work.

But FPC has several boolean types.

There are Bytebool, WordBool, ... and they can cast/store any int value (within their range) and for them 0 is false, all else is true.
https://www.freepascal.org/docs-html/current/ref/refsu4.html
Title: Re: Boolean type
Post by: jamie on April 13, 2025, 09:03:18 pm
I have to disagree with you the has has allways been that way zero is always false anything else is always true no matter what language you deal with and that's the one argument that I'm not going to back down on.

 In math its the same way.

Various values for true can be used for true except for 0.
Compiler logic uses the 1 as a more code efficient way to deal with complex bool operations.

 When directly assigning a 1 value has really nothlng to do with the language, it just makes it more code sence.
  You can pass any value as a bool to a function for true and it will accept it because onlu 0 is the important value in all language and math fir false.

 Have a good day, this is the last ill address this.
Jamie
Title: Re: Boolean type
Post by: 440bx on April 13, 2025, 09:30:04 pm
The documentation about the "boolean' types say one thing but, the behavior is a different thing.

In theory, only the BOOL types will consider any non zero value to be true while, the "boolean" types (e.g, Boolean16) will only consider a value of 1 to be true.  The reality is, as far as truth value the "boolean" types behave exactly the same way as the BOOL types.

That said, the compiler generates code that is inconsistent with the rules stated in the documentation.  For instance, it tests AX to determine if a _boolean_ is true or false.  That's incorrect, that's only valid for "BOOL" types.  For "boolean" types, the correct test is ANDing with 1.

Suggestion: treat the "boolean" types as being _functionally_ the same as the "BOOL" types. 
Title: Re: Boolean type
Post by: Martin_fr on April 13, 2025, 09:42:22 pm
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. var
  4.   a, b: Integer;
  5. begin
  6.   a := 1;
  7.   b := 2 + random(5); // prevent constant eval
  8.  
  9.   if (b>a) = Boolean(b) then
  10.     write('yes')
  11.   else
  12.     write('no');
  13.   readln;
  14. end.
  15.  

Prints "no" for me.

"b" is between 2 and 7 (so not zero). According to your statement, then that would be true.

b is also greater than a.

So the "if" has "True = True". Yet it goes into the "else" branch.



Mind that results may vary (random), depending on compiler version, compiler settings (optimization), even target arch, ....
Title: Re: Boolean type
Post by: 440bx on April 13, 2025, 10:04:05 pm
That almost sounds good but, there is a problem with it... here is your code with a couple of lines added to it:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. var
  4.   a, b: Integer;
  5. begin
  6.   a := 1;
  7.   b := 2 + random(5); // prevent constant eval
  8.  
  9.   if (b>a) = Boolean(b) then
  10.     write('yes')
  11.   else
  12.     write('no');
  13.  
  14.  
  15.   if boolean(b) then
  16.     write('yes')
  17.   else
  18.     write('no');
  19.  
  20.   readln;
  21. end.
  22.  
Lo and behold, boolean(b) is TRUE.  What your original code proves is that there are cases in FPC where two expressions that evaluate to TRUE are NOT _logically_ equal (even though they are both TRUE).  IOW, there are cases in FPC where TRUE <> TRUE (and according to some, somehow that's not a bug... it's just "undefined behavior"... there are some occasions where FPC takes "undefined behavior" to new heights.)

The code generated by the compiler is WRONG and that is the reason the first test yields false.  The code generated by the compiler to test for boolean(b) is also wrong, it uses "test al, al" therefore any non zero value in al will yield true which is incorrect since it violates the definition of boolean, both the mathematical one and the documented one.

This whole thing was already discussed ad nauseam in the thread
https://forum.lazarus.freepascal.org/index.php/topic,70004.0.html
and that thread made it very obvious that those FPC bugs are here to stay.  Logical and mathematical correctness isn't something that is going to get in FPC's way.

Wanna be safe ? ... consider any "boolean" type as behaving the same as BOOL.  There is NO true boolean type in FPC (and likely Delphi... but, since I don't use it, I don't care.)

Getting a true boolean type in FPC is programmer's responsibility.  The compiler will not help enforce the characteristics of a genuine/true boolean type.

Title: Re: Boolean type
Post by: Martin_fr on April 13, 2025, 10:35:07 pm
Lo and behold, boolean(b) is TRUE.  What your original code proves is that there are cases in FPC where two expressions that evaluate to TRUE are NOT _logically_ equal (even though they are both TRUE).  IOW, there are cases in FPC where TRUE <> TRUE (and according to some, somehow that's not a bug... it's just "undefined behavior"...

You are right, it's undefined behaviour. But you are wrong. "boolean(b)" is not true, nor is it false. It is undefined. Hence the behaviour is undefined too.

Of course if you look at this from a low level machine code point of view, and if you apply none-Pascal or generalized meanings of True/False, then the statement might be more than what you said.

But since this is about Pascal, and probably specifically fpc style, applying other conventions seems a bit out of scope?
Title: Re: Boolean type
Post by: 440bx on April 13, 2025, 10:53:51 pm
But since this is about Pascal, and probably specifically fpc style, applying other conventions seems a bit out of scope?
It's about what is logically and mathematically correct.

FPC's documentation states that when it comes to the boolean type only the value 1 is considered TRUE but, that is not true.  FPC considers values other than 1 to be TRUE and that can be seen in the code it generates.  For a boolean type it is _incorrect_ to generate a test al, al to determine the truth value of the boolean type.  The _correct_ instruction is to and the register with 1.

No matter how anyone wishes to slice it.  FPC does _not_ handle booleans as it states in the documentation that it does and, generates code that is invalid to manage a boolean type.  It generates code for the C BOOL type, that's what it does in all cases, that's why it uses test al, al (which is incorrect for boolean types.)

Title: Re: Boolean type
Post by: Martin_fr on April 13, 2025, 11:15:34 pm
But since this is about Pascal, and probably specifically fpc style, applying other conventions seems a bit out of scope?
It's about what is logically and mathematically correct.
Speaking about a numerical value for "true", are you sure that in maths (i.e. boolean algebra) there is a numerical value to the logical states?

I could have sworn that is a by product of information technology.... (And this topic started about numerical values...).

Quote
FPC's documentation states that when it comes to the boolean type only the value 1 is considered TRUE but, that is not true.  FPC considers values other than 1 to be TRUE

Does it, or does it consider them undefined?

Because the result can by chance be identical. An undefined value is allowed to behave like "true", that does not break the contract.

I know, you refer to the machine code, that does not explicitly perform the check for "1". But it performs a check that will always based on the following ordinary values of a bool behave for
- 0 as false
- 1 as true
- other as either (where "either" can is some case be a fixed choice, but is not guaranteed to be fixed)

Also:
I am neither going to reread the linked thread for any word picking in it, nor analyse the documentation for any potential English wording that could be twisted to more than one meaning.

It may be or not be that the documentation could be improved.
But, I can (I have the ability, and the good will) read it as (with regards to boolean / ignore bytebool)
0 is the ordinary value of false
1 is the ord val of true
any other ord value is not defined, and considered undefined.

And example asm code like testing "tst rax" or "or rax, rax" followed by only on of "be" or "bz" => is totally in line with that. It does not break the undefined state.
Title: Re: Boolean type
Post by: 440bx on April 14, 2025, 01:16:06 am
Speaking about a numerical value for "true", are you sure that in maths (i.e. boolean algebra) there is a numerical value to the logical states?
boolean is two states.  Those can be ON and OFF or in a gate, low voltage and high voltage, if you assign a numeric value to those states then you get 0 and 1.  It's been convention, for centuries I believe, to assign zero to false and 1 to true (unless I'm mistaken George Boole is responsible for that one.)

I could have sworn that is a by product of information technology.... (And this topic started about numerical values...).
Again, unless I am mistaken Boole started that thing.

Does it, or does it consider them undefined?
The documentation is crystal clear.  for all boolean types (not BOOL types) 1 is TRUE and 0 is FALSE.  It's right there in black and white.  That's what the documentation states, that's very far from what FPC enforces and considers as TRUE which for FPC is any value other than zero.

The problem is that FPC generates code that does NOT enforce the documented rule for boolean types (0 = FALSE, 1 and only 1 = TRUE).   There is no true boolean type in FPC.  There is only a BOOL type easily demonstrated by the code it generates: it does NOT generate code to test that the value of a boolean is 1, it generates code to test that the value is non-zero.  Consequence: there are only BOOL types in FPC.

The truly sad part is that, that bug cannot easily be corrected without breaking existing code.  There is plenty of code out there that depends on boolean being true for values that are simply non-zero.  The only way not to break that code is to make the correct behavior be depending on a new mode (e.g, USETRUEBOOLEAN) which, it doesn't look like the FPC developers are willing to entertain.

But, maybe FPC should consider assigning 42 to TRUE and 32 to FALSE.  Why would anyone be "stuck" on 0 and 1 ??? no reason for that ;)


Title: Re: Boolean type
Post by: Thaddy on April 14, 2025, 07:38:00 am
So:
Code: Pascal  [Select][+][-]
  1. type
  2.   MyBool = (nothing,something);
The problem being that many compilers define false/true as 0/1, but then they start optimizing this strictness away, like fairly recent C++ and all llvm based compilers.
At least fpc tries to prevent this "optimization" where true is not false
Title: Re: Boolean type
Post by: Khrys on April 14, 2025, 07:43:54 am
Like @440bx said, this topic has already been discussed to death (https://forum.lazarus.freepascal.org/index.php/topic,70004.0.html).

No matter whether you believe the documentation to be wrong or the programmer using non-1 integers for  True  to be at fault,
saying that  Integer(ABool)  will always be 1 is simply bad advice that shouldn't be relied upon in practice.

Code like this (which I've been tempted to write before!) is just waiting to blow up in your face, especially when e.g. you innocently try passing it  Boolean(Res)  where  Res  is the  bool  return value of an external C function:

Code: Pascal  [Select][+][-]
  1. function CountTrue(A, B, C, D: Boolean): Integer;
  2. begin
  3.   Result := Integer(A) + Integer(B) + Integer(C) + Integer(D); // May return any integer up to 1020
  4. end;
Title: Re: Boolean type
Post by: Thaddy on April 14, 2025, 08:49:33 am
I believe I gave a similar example in a previous discussion and also filed a bug report.
Especially with interfacing in other languages it can blow up indeed, but not only that: e.g. llvm based compilers only blow up with at least -O3.
I demonstrated that with a simple C lib that assumed the docs were correct for the compiler, i.e 0 and 1. Blew up when optimized.
Must be somewhere here on the forum.
Title: Re: Boolean type
Post by: Martin_fr on April 14, 2025, 10:29:43 am
Speaking about a numerical value for "true", are you sure that in maths (i.e. boolean algebra) there is a numerical value to the logical states?
boolean is two states.  Those can be ON and OFF or in a gate, low voltage and high voltage, if you assign a numeric value to those states then you get 0 and 1.  It's been convention, for centuries I believe, to assign zero to false and 1 to true (unless I'm mistaken George Boole is responsible for that one.)

Ok, I didn't know. But even if, as you said its 2 tokens.

For all else, they are 2 tokens for  - as you wrote - 2 states.

Unfortunately you simple ignored about half of the previous statement.

If the token is not readable (never mind why that can happen, or if the choices that allow it to happen aren't choices that make you happy), then something must happen. It could be a crash, an exception, or an undefined behaviour. The latter was chosen. Maybe not your preferred choice, none the less a valid one.

You keep doing a mix of ignoring and misrepresenting it. Your choice. Valid choice as well, but not a choice on which I will waste my time.
Title: Re: Boolean type
Post by: 440bx on April 14, 2025, 10:41:55 am
You keep doing a mix of ignoring and misrepresenting it. Your choice. Valid choice as well, but not a choice on which I will waste my time.
I don't think I"m ignoring or misrepresenting anything. 

By definition Boolean is 2 states.  If we accept the traditional convention of 0 and 1 to denote those 2 states and 0 to represent FALSE and 1 to represent TRUE then FPC does NOT implement booleans.  What it implements is C's bastardized BOOL type but, it definitely does NOT implement boolean and that is readily seen in the code it generates.  No boolean implementation can use test al, al or test ax, ax to determine if the value is 1 since those tests determine 0 and non-zero.  They do not test for the value 1 which is what boolean requires and also what the documentation specifies.

It would be kind of nice if the compiler behaved as the documentation states it does (which it simply does not in the case of boolean.)

There is no way around it.  FPC does NOT behave as documented and does NOT treat the boolean type as documented.  If it did, the code it would generate for them would be quite different from the code it's generating today.


Title: Re: Boolean type
Post by: Martin_fr on April 14, 2025, 11:05:01 am
You keep doing a mix of ignoring and misrepresenting it. Your choice. Valid choice as well, but not a choice on which I will waste my time.
I don't think I"m ignoring or misrepresenting anything. 

By definition Boolean is 2 states. 

Even when G.Boole did it (presumingly on paper, but it does not matter what media), there was a chance of unclear representation. And if he (or any human) encountered such a case they needed to deal with it (and if they did not recognise it, then the result was unpredictable).

More so, someone could have written a 2 in an bool equation on paper. That would have invalidated the expression of course (just as it does now, when you do Boolean(2)). So we follow the exact same rules. Once invalidated the result is undefined. (because undefined was chosen over an exception).

I do understand that you believe that now we have the chance to chose a representation (single bit) that can not be mis-read. But that choice has not been made. And G.Boole himself used representations that did not enforce others to stick to those 2 tokens. In all of time, others were able to write tokens (on paper) that were invalid.

So, all it is, is that the possibility to break the rule (of only using the 2 valid tokens) is still available to the user.

Quote
By definition Boolean is 2 states. 
And so does it have in FPC.

All else is user error.

The only thing that I can see as a point (in all of your statements) is that user error is not prevented. Though if that is what you try to say, then you do that in a really obscured and definitely misleading way.

Title: Re: Boolean type
Post by: Thaddy on April 14, 2025, 11:40:39 am
1. Boolean implementations as opposed to definitions are not two states but infinity - 1 since optimizations lead to loss ofthe two state accuracy.
Optimizers seem to accept the only solid value of the two theoretical states is false. But that implies that true is infinity, since infinity - 1 is also infinite.
2. Compilers should not play such dangerous games with optimizers.
I repeat my proof from two years ago:
Code: C  [Select][+][-]
  1. #include <stdio.h>
  2. #include <stdbool.h> /* optional in GNU 12 and higher */
  3. void mycfunc(_Bool arg){
  4.         printf("number: %d\n",arg?1:2);
  5. }
Compile with and without optimization and shiver....
Same goes if you build it with clang.
Both compilers only adhere to the two state 0 and 1 without optimizations.
Both compilers document Bool is 0 and 1...
Go figure....
Title: Re: Boolean type
Post by: 440bx on April 14, 2025, 11:52:27 am
And so does it have in FPC.
NO, that's the fallacy.  The fact that FPC uses instructions such as test al, al and test ax, ax to determine the truth value _proves_ that what FPC is implementing is NOT a true, 2 state only, 0 and 1, boolean type.  It is implementing C's BOOL thing which is 0 = FALSE any other value = TRUE (that's 255 additional states) which is in direct contradiction to the documentation.

FPC does not implement a true boolean type.  It implements C BOOL type which is similar but also very different.  Since there are times it is forced to treat boolean as a real boolean, e.g, when bitpacking, then it falls over itself as was shown in the tread I previously linked to.

There is no undefined behavior, what there is, is well defined, completely incorrect implementation.   

It's not hard to implement the real boolean type, a simple "and reg, 1" does it.
Title: Re: Boolean type
Post by: Thaddy on April 14, 2025, 12:20:26 pm
@440bx
You are right but it depends on optimization and you are focussing on just one cpu family.
My above test library is a better way to prove your point for external libs.
I believe that trunk does not optimize true/false anymore for Boolean,but it does for BOOL, same as C _Bool.
Title: Re: Boolean type
Post by: Martin_fr on April 14, 2025, 12:33:18 pm
And so does it have in FPC.
NO, that's the fallacy. 

Yes, it does
And I explained how/why.
Title: Re: Boolean type
Post by: 440bx on April 14, 2025, 01:35:05 pm
Yes, it does
And I explained how/why.
Martin, you cannot argue this. 

The compiler generates code that tests entire bytes/words/dwords/etc depending on the size of the boolean.  THAT proves beyond any possible argument that FPC is NOT treating a boolean as a two state entity.  The treatment it gets is: 0 = FALSE and 1 through 255 (or high(type)) = TRUE.  That doesn't remotely resemble two unique ways of representing TRUE and FALSE.

FPC has 1 state for FALSE and umpteen states for TRUE and the way it treats them is erratic which is why the whole thing falls apart when mixing them with bitpacked booleans and also why there are cases in FPC where TRUE <> TRUE (refer back to the example I gave based on your code.)  If FPC implemented the boolean type correctly TRUE would always equal TRUE.

result: there are no true booleans in FPC.  Only C's BOOL.

The FPC documentation states how a boolean _should_ be, definitely not the way it is in FPC.
Title: Re: Boolean type
Post by: Martin_fr on April 14, 2025, 01:39:34 pm
Yes, it does
And I explained how/why.
Martin, you cannot argue this. 

Agreed. I can only state the facts. I did.

You misrepresent them. (You represent various facts, but mix/cross different contexts leading to an incorrect result)
Title: Re: Boolean type
Post by: Khrys on April 14, 2025, 02:12:46 pm
Explicit casts from integer to boolean like  Boolean(2)  should at the very least generate a warning, or better yet actually enforce FPC's purported principle that  Integer(True) = 1  by inserting extra code for such casts.

In my opinion, the mere presence of undefined behavior isn't the problem here, but the fact that it can be triggered so easily without warning - it's a footgun with a silencer attached.
Title: Re: Boolean type
Post by: LemonParty on April 14, 2025, 02:21:30 pm
Thank you for answers.
My desire was to determine if I can write code like this:
Code: Pascal  [Select][+][-]
  1. function Pick(B: Boolean): Integer;
  2. const
  3.   Resp: array[Boolean]of Integer = ($13, $42);
  4. begin
  5.   Result:= Resp[B];
  6. end;
  7.  
Title: Re: Boolean type
Post by: cdbc on April 14, 2025, 02:23:09 pm
Hi
You can!
Regards Benny
Title: Re: Boolean type
Post by: Martin_fr on April 14, 2025, 02:34:14 pm
Thank you for answers.
My desire was to determine if I can write code like this:
Code: Pascal  [Select][+][-]
  1. function Pick(B: Boolean): Integer;
  2. const
  3.   Resp: array[Boolean]of Integer = ($13, $42);
  4. begin
  5.   Result:= Resp[B];
  6. end;
  7.  


Ok, so the answers where completely off....


You could try an operator overload. Something like
Code: Pascal  [Select][+][-]
  1. Operator := (val: integer): Boolean;

You need to check the exact details (and if FPC will accept it at all)
Title: Re: Boolean type
Post by: 440bx on April 14, 2025, 03:15:01 pm
Agreed. I can only state the facts. I did.
Here is a FACT: in FPC two expressions that are TRUE are considered to be unequal, IOW, TRUE <> TRUE.  THAT is a FACT in FPC.  There is NO undefined territory in the whole universe that can justify that.

I didn't misrepresent anything.  I stated the facts and if you need to see them again, look at the two lines I added to your code.  That proves what I've stated.  Also, the FACT that FPC uses test al, al and test AX, AX proves it is considering any non zero value as TRUE.  Those are FACTS and I do not understand how you can possibly attempt to argue them. 

Look at the assembly code.  It's right there.
Title: Re: Boolean type
Post by: 440bx on April 14, 2025, 03:31:43 pm
Thank you for answers.
My desire was to determine if I can write code like this:
Code: Pascal  [Select][+][-]
  1. function Pick(B: Boolean): Integer;
  2. const
  3.   Resp: array[Boolean]of Integer = ($13, $42);
  4. begin
  5.   Result:= Resp[B];
  6. end;
  7.  
It should work but, I still would be careful with writing something like that because the value of B is NOT guaranteed to be in the set [0, 1].  It can be any value ranging from zero to 255.  That said, if your code can guarantee that the value of B will be 0 or 1 then there is no problem, just don't expect the compiler to guarantee B to be zero or 1, it does not.

Title: Re: Boolean type
Post by: Martin_fr on April 14, 2025, 03:33:48 pm
Agreed. I can only state the facts. I did.
Here is a FACT: in FPC two expressions that are TRUE are considered to be unequal,

There aren't true (as far as any example that I have been shown). They are undefined. As soon as you use typecast (except for the ordinal 0 ad 1), you no longer have "boolean".
Title: Re: Boolean type
Post by: Martin_fr 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).

Title: Re: Boolean type
Post by: 440bx 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 ?

Title: Re: Boolean type
Post by: Martin_fr 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.
Title: Re: Boolean type
Post by: marcov 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.

Title: Re: Boolean type
Post by: 440bx 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.
Title: Re: Boolean type
Post by: marcov 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).
Title: Re: Boolean type
Post by: 440bx 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.

Title: Re: Boolean type
Post by: Martin_fr 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...
Title: Re: Boolean type
Post by: ASerge 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).
Title: Re: Boolean type
Post by: jamie 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

Title: Re: Boolean type
Post by: marcov 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.
Title: Re: Boolean type
Post by: 440bx 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.

Title: Re: Boolean type
Post by: Martin_fr 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?



Title: Re: Boolean type
Post by: 440bx 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!


Title: Re: Boolean type
Post by: nanobit 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 (https://www.freepascal.org/docs-html/ref/refse84.html).
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.
Title: Re: Boolean type
Post by: jamie 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 (https://www.freepascal.org/docs-html/ref/refse84.html).
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.


Title: Re: Boolean type
Post by: Martin_fr 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.
Title: Re: Boolean type
Post by: 440bx 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.
Title: Re: Boolean type
Post by: nanobit on April 21, 2025, 06:04:21 am

A long thread, and boolean(100) is in reference (https://www.freepascal.org/docs-html/ref/refse84.html).
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.
Title: Re: Boolean type
Post by: Thaddy 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.
Title: Re: Boolean type
Post by: Martin_fr 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.


Title: Re: Boolean type
Post by: 440bx 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.

Title: Re: Boolean type
Post by: Martin_fr 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.
Title: Re: Boolean type
Post by: 440bx 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.
Title: Re: Boolean type
Post by: Martin_fr 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.
Title: Re: Boolean type
Post by: TRon 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.

Title: Re: Boolean type
Post by: Zoran 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.
Title: Re: Boolean type
Post by: 440bx 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!

Title: Re: Boolean type
Post by: simone 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.
Title: Re: Boolean type
Post by: dseligo 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.
Title: Re: Boolean type
Post by: simone on April 21, 2025, 09:15:37 pm
Why doesn't the compiler emit an invalid cast message error?

Edit: The error is clearly intentional.
Title: Re: Boolean type
Post by: dseligo on April 21, 2025, 09:39:06 pm
Why doesn't the compiler emit an invalid cast message error?

Edit: The error is clearly intentional.

I don't see need for it.

As it says here https://wiki.freepascal.org/Typecast (https://wiki.freepascal.org/Typecast): Typecasting is the concept, allowing to assign values of variables or expressions, that do not match the variable’s data type, virtually overriding Pascal’s strong typing system.

So, you are overriding Pascal’s strong typing system: you are on your own.

It says here https://www.freepascal.org/docs-html/ref/refse85.html (https://www.freepascal.org/docs-html/ref/refse85.html): It is a bad idea to typecast integer types to real types and vice versa.
If you want to, you can make bug report against documentation to say that is also bad idea to typecast integer types to boolean. :)
Title: Re: Boolean type
Post by: Paolo on April 21, 2025, 10:06:46 pm
Quote
I don't see need for it.
+1.

If you force the type, the result is your responsability.
Title: Re: Boolean type
Post by: LV on April 21, 2025, 10:10:18 pm
Why doesn't the compiler emit an invalid cast message error?

Edit: The error is clearly intentional.

The compiler has nothing to do with it. This is a common issue in mathematical logic regarding normalization.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$mode ObjFpc}
  3.  
  4. var
  5.   B1, B2: boolean;
  6.  
  7. begin
  8.   B1 := boolean(1); // True (stored as 1)
  9.   B2 := boolean(2); // True (stored as 2)
  10.  
  11.   writeln(B1);        // Output: TRUE
  12.   writeln(B2);        // Output: TRUE
  13.   writeln(B1 and B2); // Output: TRUE
  14.  
  15.   // Compare by normalizing to 0/1
  16.   writeln( (integer(B1) <> 0) = (integer(B2) <> 0) ); // Output: TRUE
  17.  
  18.   readln;
  19. end.  
  20.  
Title: Re: Boolean type
Post by: marcov on April 21, 2025, 10:18:20 pm

Code: [Select]
  writeln(B1);        // Output: TRUE    CORRECT
  writeln(B2);        // Output: TRUE    IMPLEMENTATION DEFINED
  writeln(B1 and B2); // Output: TRUE IMPLEMENTATION DEFINED
 
  // Compare by normalizing to 0/1
  writeln( (integer(B1) <> 0) = (integer(B2) <> 0) ); // Output: TRUE   CORRECT, but because the typecasts force BOOL, not BOOLEAN semantics

The IMPLEMENTATION DEFINED results are not guaranteed.
Title: Re: Boolean type
Post by: Martin_fr on April 21, 2025, 10:24:16 pm
Code: Pascal  [Select][+][-]
  1.   // Compare by normalizing to 0/1
  2.   writeln( (integer(B1) <> 0) = (integer(B2) <> 0) ); // Output: TRUE
  3.  

That example is truly bad. It might be (part of) why 440bx is so strongly against the ability to use typecasts on boolean. (Albeit, his arguments are still wrong, as they simple aren't true).

If you wanted to use it as boolean, you shouldn't have type casted, but done
Code: Pascal  [Select][+][-]
  1.  B2 := 2 <> 0; // or whatever in the definition of your data defines that 2 should be converted to true.



Type cast you use, if you don't want it to be treated as boolean. (because you give up that option)

Let's say you use some code that has a public field
Code: Pascal  [Select][+][-]
  1. property FooBar: boolean;
You don't need FooBar, but you need storage for something else. And you can't extend the class/record/object.

Then you could (like it is often done with "Tag") store your date (e.g. an integer) in that property
Code: Pascal  [Select][+][-]
  1. MyObj.FooBar := Boolean(MyInt);
And later
Code: Pascal  [Select][+][-]
  1. MyInt := Integer(MyObj.FooBar);

And if you do that, you use it as storage only. While doing so, you would have no reason to treat it as boolean.




Of course there are cases where you typecast and will use it as boolean afterwards.

That is if you have previously done
Code: Pascal  [Select][+][-]
  1. MyObj.Tag := integer(MyValidBool);  // Tag is integer
Then you know Tag must have data that can be cast back to a boolean, and have a value valid for boolean usage. So then you can cast that back later, and use it.

Of course your responsibility that Tag does not get changed in between.
Title: Re: Boolean type
Post by: simone on April 21, 2025, 10:36:48 pm
The purpose of my example, intentionally incorrect and extreme, was to show a concrete paradox that arises from what was clearly explained in previous posts about boolean type implementation of fpc.

In a language with static and strong typing like Object Pascal, silent errors like True=True is False should not happen, in my humble opinion.
Title: Re: Boolean type
Post by: Martin_fr on April 21, 2025, 10:42:47 pm
The purpose of my example, intentionally incorrect and extreme, was to show a concrete paradox that arises from what was clearly explained in previous posts about boolean type implementation of fpc.

In a language with static and strong typing like Object Pascal, silent errors like True=True is False should not happen, in my humble opinion.

But then you would also have to say, that
Code: Pascal  [Select][+][-]
  1. writeln(TStringList(1).Count);
must return some sensible number.

It is clearly typed as a TStringList.

The fact is, that Pascal has a part that is strongly typed.

And Pascal has a part that is not, and that allows to break out of that type-system. Warts and all.
Title: Re: Boolean type
Post by: simone on April 21, 2025, 10:57:16 pm
The fact is, that Pascal has a part that is strongly typed.

And Pascal has a part that is not, and that allows to break out of that type-system. Warts and all.

I had guessed that in the past, but thank you for stating it clearly.

The problem, sometimes, is to figure out where the underlying type system is strong or weak.
Title: Re: Boolean type
Post by: Zoran on April 21, 2025, 11:17:40 pm
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.

No. Having one bit to represent two states and disregard other bits would have been a valid way to represent boolean, had it be chosen. There are other valid ways to store boolean too.
As documented, the chosen way is that the size is one byte (I hope you don't oppose the one byte choice for size, do you?) and that zero in all bits represent false value and 1 in bit 0, together with zeros in all other bits represents true value. All other 254 possible values of the boolean value, that is all values which have any bit other than bit 0 set, are undefined. This choice is perfectly valid.

And when this choice was made, it was so that the relation False < True equals True.
This relation is documented, so it must not be violated, keep that in mind when suggesting to treat any byte with bit 0 set to 1 as True.

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.
No. In fpc Boolean is what fpc documentation says, nothing else. And what you mean by "booleans" there remains unclear.
 - in C, any non-zero value means True. It is not so with Boolean in fpc. Although you might experience the behaviour which appear so, it is not documented and, unlike in C, you must not rely on it.
 - in FPC valid Boolean values are comparable - false < true - you can rely on it. Not so in C.
The types from other languages have nothing to do with how Boolean is defined in FPC. There are types in FPC which are documented to behave like C, but not Boolean.

That's the reason why when using booleans, FPC can end up in situations where TRUE <> TRUE

This situation is not
Code: [Select]
True <> True, it is
Code: [Select]
oneVariableWithUndefinedValue  someRelationOperator  anotherVariableWithUndefinedValueYou can't expect a predictable value from this expression. You get something once, another time something else. Or even worse, you will get the same outcome always, and your user something else.

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

That's how it works, you need to take care yourself to avoid the crash. But you are in control, and as long as you don't overuse alcohol when programming, the tree doesn't get in the way.
Title: Re: Boolean type
Post by: Zoran on April 21, 2025, 11:47:32 pm
The problem, sometimes, is to figure out where the underlying type system is strong or weak.

Pascal has "unsafe" constructs, but they aren't safe only if you don't really know what you are doing - see the five points (2-5) in my post above (https://forum.lazarus.freepascal.org/index.php/topic,70806.msg552751.html#msg552751). These constructs are introduced to allow skipping the strong type system, so they weaken the type system, but they actually give the real strength to this language. The original Pascal, as created fifty years ago didn't have them, that's why it got the "toy language" reputation.
To get the real power, learn to use them well and don't hesitate to use them. When used well and carefully, they are safe.

As I said, you cannot get an undefined value in a boolean variable without using these unsafe constructs. In your examples you use explicit type cast. Fill free to use it whenever you need, but carefully - keep in mind that the type casting exists to allow skipping strong type system. That is what it is for.
Title: Re: Boolean type
Post by: simone on April 21, 2025, 11:59:56 pm
However GnuPascal (1), an old and abandoned, but respectable implementation of Pascal, with my example, generates a compilation error ("constant out of range") when attempting to cast 2 to a boolean, in line #8.

So my expectation of an error message from the compiler is not so unreasonable.

(1): Tried using on line version available from ideone.com
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 12:21:19 am
However GnuPascal, an old and abandoned, but respectable implementation of Pascal, with my example, generates a compilation error ("constant out of range") when attempting to cast 2 to a boolean.

So my expectation of an error message from the compiler is not so unreasonable.

I have never tried GNU Pascal, so I don't know its rules, but I believe that, unlike FPC, it doesn't follow Borland's extensions, but the iso standard object pascal.
Look at the fpc object pascal (at least it is so with the most popular compiler modes) as a dialect of Borland line. This Borland line has its own rules, which fpc inherited from Delphi.

With type casting you are skipping the strong type system. That's it.
Title: Re: Boolean type
Post by: TRon on April 22, 2025, 01:14:28 am
I have never tried GNU Pascal, so I don't know its rules, but I believe that, unlike FPC, it doesn't follow Borland's extensions, but the iso standard object pascal.
Indeed the latter, although ISO pascal also does not explicitly seem to state how it is actually stored in memory. The behaviour though is described for both: true and false are the only two options.

For gnu see https://www.gnu-pascal.org/gpc/Boolean.html
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 01:28:59 am

Indeed the latter, although ISO pascal also does not explicitly seem to state how it is actually stored in memory.

It does, actually (another link in the page you gave): https://www.gnu-pascal.org/gpc/Boolean-_0028Intrinsic_0029.html#Boolean-_0028Intrinsic_0029 (https://www.gnu-pascal.org/gpc/Boolean-_0028Intrinsic_0029.html#Boolean-_0028Intrinsic_0029)
Title: Re: Boolean type
Post by: TRon on April 22, 2025, 01:36:29 am
It does, actually (another link in the page you gave): https://www.gnu-pascal.org/gpc/Boolean-_0028Intrinsic_0029.html#Boolean-_0028Intrinsic_0029 (https://www.gnu-pascal.org/gpc/Boolean-_0028Intrinsic_0029.html#Boolean-_0028Intrinsic_0029)
Well, sort of. It tells us how the compiler handles it/treats them (which differs from tp/fpc). It (at least ISO pascal, I'm  not too familiar with gnu) does not explicitly says anything about how these enumerated values are actually stored in memory. For all we know such boolean actually occupies 64 bits in memory or perhaps even 128 bits. And as long as the compiler treats them in a certain way, it does not matter. It should behave as a black box. This in contrast to the other in gnu pascal defined boolean types.
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 01:45:29 am
That example is truly bad. It might be (part of) why 440bx is so strongly against the ability to use typecasts on boolean. (Albeit, his arguments are still wrong, as they simple aren't true).
The drunk tree got in the way... bad, bad tree!  does that tree have a licence to drive ?...

Why would the compiler refuse an invalid typecast as it does with countless others ?... it's not a bug... good compiler for allowing nonsense.  That's strong typing for you... you want nonsense ?... no problem... it's your lucky day... FPC will allow it... and when it doesn't work... it's your fault...   Wonderful !!  (reminds me of the original implementation of C where undefined identifiers were simply assumed to be integers... why did they get rid of that wonderful feature... it was obviously the programmer's fault that the identifier had not been declared... obviously because it's the programmer who has to declare them!)

Unbelievable! 
Title: Re: Boolean type
Post by: Khrys on April 22, 2025, 08:02:26 am
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.

About that...

Code: Pascal  [Select][+][-]
  1. Double(Some_Integer)
  2. PChar(Some_AnsiString)
  3. WideString(Some_AnsiString)

There is no consistency regarding casts in FPC -  Integer(Some_Double)  is forbidden, but the reverse works just fine; casts between string types in general laugh at this supposed principle.

Would it really kill the compiler to turn this:

Code: ASM  [Select][+][-]
  1. mov eax, edi

...into this:

Code: ASM  [Select][+][-]
  1. test edi, edi
  2. setne al

...when casting to  Boolean? In the compiler's philosphy, casts involving more than just bit pattern reinterpretation seem to be perfectly fine (as demonstrated above). Why not reduce the attack surface of invalid-boolean-bit-pattern UB?
Reiterating what I've said before:

In my opinion, the mere presence of undefined behavior isn't the problem here, but the fact that it can be triggered so easily without warning - it's a footgun with a silencer attached.
Title: Re: Boolean type
Post by: Joanna on April 22, 2025, 08:14:52 am
Is Boolean not an ordinal type? if so how can you type cast it at all? if it is an ordinal type boolean = (false,true)
why doesn't boolean type cast return error of invalid typecast for all numbers besides 0 or 1?
this seem like inconsistent behavior that should be fixed. is there a reason it isn't ?
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 11:20:57 am
There is no consistency regarding casts in FPC -  Integer(Some_Double)  is forbidden,
:o
Uh, It is indeed! Now I'm totally confused! What? Why?
And casting from Integer to Double seems to reintrpret the bits!!! Total mess, I can't believe this! :o

Would it really kill the compiler to turn this:

Code: ASM  [Select][+][-]
  1. mov eax, edi

...into this:

Code: ASM  [Select][+][-]
  1. test edi, edi
  2. setne al

...when casting to  Boolean? In the compiler's philosphy, casts involving more than just bit pattern reinterpretation seem to be perfectly fine (as demonstrated above).

We really don't need this. The behaviour you want can be easily achieved by using "<> 0", there is no need for such casting. We need a reliable unsafe type casting.

But this "cast" from Integer to Double, which is not cast, but reinterpretation is a total mess! Allowing casting to mess with bits is just totally wrong. :o
Can we rely on anything???
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 11:27:54 am
With type casting you are skipping the strong type system. That's it.

Just forget what I said, it seems that I had no idea what I was talking about.
I certainly don't understand the type casting, I got it totally wrong.
 :o
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 11:31:39 am
There are 2 operations by the syntax: SomeType(SomeValue)

- typecasts
- conversion.

E.g. Int64(MyIntVar)
is a conversion. It will sign extend the value from 32 to 64 bit.

It is a bit of a pity that the same syntax does 2 different things.
Title: Re: Boolean type
Post by: nanobit on April 22, 2025, 11:50:20 am
But this "cast" from Integer to Double

The double( int) bug (https://gitlab.com/freepascal.org/fpc/source/-/issues/35886) fix is in newer versions.
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 11:52:35 am
There are 2 operations by the syntax: SomeType(SomeValue)

- typecasts
- conversion.

E.g. Int64(MyIntVar)
is a conversion. It will sign extend the value from 32 to 64 bit.

It is a bit of a pity that the same syntax does 2 different things.

But in your example, although it extends 32-bit to 64-bit, the lower 32 bit value does not change.
Now I tried
Code: [Select]
Double(Int64Variable), which is same size, and the bits were reinterpreted! So, it is not about extending size, it actually changed the bits.

I don't get it. How does the compiler decide when it is a cast, and when it is a conversion? How do we know what to expect from the compiler - cast or conversion?

I haven't known about this conversion until now. I've always thought that we have assignment compatibility from Integer to Double, which serves the purpose quite well. And for assigning Double to Integer there is Trunc().
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 12:07:25 pm
But this "cast" from Integer to Double

The double( int) bug (https://gitlab.com/freepascal.org/fpc/source/-/issues/35886) fix is in newer versions.

Uh, the bug is that in mode Delphi it behaves as cast, and in objfpc it behaves as conversion. But, if I understand well, the "fix" is that now the mode Delphi behaviour is "corrected", so that it no more casts, but converts the value!

Total mess, so we just can't use the "unsafe" cast safely.
Is this conversion behaviour documented anywhere? Not a word about it in https://www.freepascal.org/docs-html/ref/refse85.html#x147-17100012.5 (http://Variable typecast) page.

How can we tell when it is not a cast but a conversion? Why wasn't assignment compatibility of Integer to Double good enough?
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 01:36:48 pm
there doesn't seem to be much sense in FPC's typecasting system.

For instance, in the following:
Code: Pascal  [Select][+][-]
  1.  
  2. const
  3.   ASignature = DWORD('abcd');    { it doesn't accept this }
  4.   ASignature = DWORD('a');       { but it accepts this }
  5.   ABoolean   = boolean('a');     { this is also acceptable, really ??? }
  6.  
  7. var
  8.   ASignatureVar : DWORD;
  9.   ABooleanVar   : boolean;
  10.   ABoolean32Var : boolean32;
  11.  
  12. begin
  13.   ASignatureVar := DWORD('abcd');   { it accepts this. ok for a var but not for a constant ? that makes a lot of sense ;-)  }
  14.  
  15.   ASignatureVar := DWORD('abcde');  { it doesn't accept this, which is good   }
  16.  
  17.   ASignatureVar := DWORD('a');      { it accepts this }
  18.  
  19.   ASignatureVar := DWORD('ab');     { it doesn't accept this, why not ? 'a' is fine but 'ab' isn't ? }
  20.  
  21.   ABooleanVar   := boolean('a');    { typecast a character into a boolean ... NO problem... LOL }
  22.  
  23.   ABoolean32Var := boolean32('abcd');  { another jewel }
  24.  
Time to have some fun:

1. In a constant, you cannot typecast "abcd" into a DWORD but, you can do exactly that cast in a DWORD variable.

2. In a constant, you CAN typecast "a" into a DWORD.  Basically, DWORD is working like "ord"

3. typecasting "abcde" to a DWORD variable is not acceptable (which is good because of the size, i.e, the extra "e")

4. typecasting "a" to a DWORD variable is acceptable (that's questionable because the size isn't right but, seems like DWORD is sort of equal to "ord")

5. typecasting "ab" to a DWORD variable is NOT acceptable.  if it accepts "a" and "abcd" then why doesn't it accept "ab" and "abc" ????  It should zero pad the value just as it did when there was only "a". 

it looks like between "a" and "abcd" all there is, is, "undefined territory". ;)

6. and there is no problem typecasting a character or character string to a boolean.  In FPC, booleans are 0, 1 and "abcd" and any other string that fits (never mind it's a string... that's "perfectly" fine... who could possibly expect a compiler for a strongly typed language to catch such an error ???)  Some strong type checking there!



Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 03:09:48 pm
who could possibly expect a compiler for a strongly typed language to catch such an error ???)  Some strong type checking there!

Strongly typed language? When Pascal was typed that strongly, it rightfully earned the title of a toy language.

What strong type checking? Why would you expect type checking? Apart from not touching the bits in any way, the essential thing with casting is that no type checking should take place.
At least I've thought so until now, when I see that casting an integral value to double seems to behave same as simple assignment, the compiler converts the value, making casting totally useless.

When a programmer uses explicit type casting, he says to the compiler - do not attempt to check anything, I know what I'm doing and why I want to do so.
What else do you think casting can be useful for?
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 03:12:46 pm
When a programmer uses explicit type casting, he says to the compiler - do not attempt to check anything, I know what I'm doing and why I want to do so.
You got that completely wrong.  Typecasting isn't "limitless" and that's quite obvious because there are plenty of typecasts the compiler rejects.  You really have to rethink that.
Title: Re: Boolean type
Post by: Thaddy on April 22, 2025, 03:19:20 pm
Actually he is right. Guaranteed correct casts use is and as.
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 03:21:27 pm
When a programmer uses explicit type casting, he says to the compiler - do not attempt to check anything, I know what I'm doing and why I want to do so.
You got that completely wrong.  Typecasting isn't "limitless" and that's quite obvious because there are plenty of typecasts the compiler rejects.  You really have to rethink that.

Okay, I'm moving away from casting, and I am going to use absolute directive or variant records to workaround casting.
But then, please tell me what can be the purpose of type casting? And why the documentation (https://www.freepascal.org/docs-html/ref/refse85.html#x147-17100012.5) doesn't say anything about that sometimes you can just get conversion instead?
Title: Re: Boolean type
Post by: Thaddy on April 22, 2025, 03:38:08 pm
The auto conversion is indeed a problem and hell when you want to use C style casts. The work-around is using pointer types to what you want to cast.

The best way to show that is trying to translate any and all examples in the famous "bit twiddling hacks" from stanford.
https://graphics.stanford.edu/~seander/bithacks.html
Some of which need adjusting in FPC because of implicit conversions.
This is known to the core compiler team.
I explained quite some decades ago:
“There are more things in heaven and earth, Horatio, than are dreamt of in your philosophy,” but fell on deaf ears. Eventually I used the pointer types to work around it. Although I understood Florian's and Jonas's reasoning regarding the Pascal language.

I used a practical application of this approach in the bit manipulation parts for the type helpers for integer types. That is: the parts I initially wrote.
Title: Re: Boolean type
Post by: Khrys on April 22, 2025, 03:52:52 pm
Has there ever been a time where "cast" exclusively referred to bit pattern reinterpretation? (Genuine question)

In C, the standard way to convert between  int  and  double  is to use casts.
The C++ standard considers cast to be synonymous with explicit conversion. Furthermore,  std::bit_cast  isn't part of the core language; it's a standard library function.

(And by the way, "to cast" originally meant pouring molten metal into a mould, which also changes the metal's shape.)
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 03:57:24 pm
using "absolute" is different than type casting.

"absolute" is used to declare a variable at a specific address.  This allows to place multiple variables of any type at the same address.  That's not typecasting, that's simply variable declaration at a specific address.

The purpose of typecasting is to re-interpret the meaning of some data (without having to declare a variable of some type at some address.)  For instance, the typecast "SomeDword := DWORD('abcd');"  changes the interpretation of 'abcd' from characters to their equivalent bytes.  That typecast works because a DWORD is 4 bytes and 'abcd' is 4 bytes too. 

OTH, FPC's typecasting rules are completely inconsistent (that's putting it _very_ kindly.)  If they were consistent then it would accept "SomeDword := DWORD('ab');" and "SomeDword := DWORD('abc');" because it accepts "SomeDword := DWORD('a');".  If the compiler was consistent  it would do the same padding it does for "DWORD('a') for the other cases but, it is NOT consistent.  Not only that, typecasts that are accepted for variables are not accepted for constants.  IOW, consistently inconsistent.

Also, it is not only wrong but totally ridiculous for FPC to accept "ABoolean32Var := boolean('abcd)';".  Obviously the compiler has no concept whatsoever of what a boolean is.  It sort of manages to implement C's BOOL and tries rather poorly to fit boolean into BOOL.  a BOOL and its variations are not limited to the value 0 and 1, but boolean is (is supposed to be but, obviously not in FPC.)

Maybe there is one thing we could all agree on which is: the type boolean is NOT the same as the type BOOL (at least it isn't supposed to be but, it is in FPC)

That FPC sees boolean to be the same as BOOL is patently obvious because it generates the same code for either which is preposterously wrong for boolean.  There is no boolean type in FPC.
Title: Re: Boolean type
Post by: Thaddy on April 22, 2025, 03:59:29 pm
Has there ever been a time where "cast" exclusively referred to bit pattern reinterpretation? (Genuine question)
Yes, since K&R I know it, but probably much earlier in CS.
Quote
In C, the standard way to convert between  int  and  double  is to use casts.
The C++ standard considers cast to be synonymous with explicit conversion. Furthermore,  std::bit_cast  isn't part of the core language; it's a standard library function.
The C++ approach is quite like the helpers.
Quote
(And by the way, "to cast" originally meant pouring molten metal into a mould, which also changes the metal's shape.)
No, it means shaping the same amount of material into a different shape. It comes from old Norse and means "to throw" but there are much earlier Greek references that describe the same concept. ( Looked that up: Metaphysics (Book VII, section 1033b) , Aristotle of course, should have known that  :'( )
Think a certain amount of clay turned into a brick.
The concept is also known as hylomorphism.
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 04:20:22 pm
OTH, FPC's typecasting rules are completely inconsistent (that's putting it _very_ kindly.)  If they were consistent then it would accept "SomeDword := DWORD('ab');" and "SomeDword := DWORD('abc');" because it accepts "SomeDword := DWORD('a');".  If the compiler was consistent  it would do the same padding it does for "DWORD('a') for the other cases but, it is NOT consistent.  Not only that, typecasts that are accepted for variables are not accepted for constants.  IOW, consistently inconsistent.

Yes there appear to be some inconsistencies. As the example with const section vs code section shows. But that isn't a statement on the concept itself.

As for DWORD('a'): 'a' is of type char (not some string) => that makes it an ordinal value, and afaik (need to double check) that introduces an conversion as part of the overall operation.

Try DWORD('a'+'') and you will see that it fails for a string (long or short $H+/-). Because a string has no ordinal value. And the wrong size in this case.



Yes the fact that you get automatic conversion thrown in there as part of some mix, all with one syntax... that is not always helping. But that is a new topic, way off the original statement.

Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 04:37:52 pm
The auto conversion is indeed a problem and hell when you want to use C style casts.

Is it documented anywhere? When can we expect conversion instead of cast?

The work-around is using pointer types to what you want to cast.

Yes, that would be the first of these three workarounds:
Code: Pascal  [Select][+][-]
  1. // Workaround 1 - using pointer cast
  2. function CastInt64ToDouble_1(const N: Int64): Double; inline;
  3. begin
  4.   PInt64(@Result)^ := N;
  5. end;
  6.  
  7. // Workaround 2 - using move procedure
  8. function CastInt64ToDouble_2(const N: Int64): Double; inline;
  9. begin
  10.   system.Move(N, Result, SizeOf(Result));
  11. end;
  12.  
  13. // Workaround 3 - using absolute directive
  14. function CastInt64ToDouble_3(const N: Int64): Double; inline;
  15. var
  16.   ResultAsInt64: Int64 absolute Result;
  17. begin
  18.   ResultAsInt64 := N;
  19. end;
  20.  

The best way to show that is trying to translate any and all examples in the famous "bit twiddling hacks" from stanford.
https://graphics.stanford.edu/~seander/bithacks.html
Some of which need adjusting in FPC because of implicit conversions.

Thanks! See, I'm using one of their pearls (https://github.com/zoran-vucenovic/swan/blob/main/z80processor.pas#L355) (linked there in the comment). :)

This is known to the core compiler team.
But Delphi compatibility would be the priority... This mess came from Embarcadero, right?
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 04:39:27 pm
Try DWORD('a'+'') and you will see that it fails for a string (long or short $H+/-). Because a string has no ordinal value. And the wrong size in this case.
DWORD('a+') does NOT work but...
DWORD('a+++')  DOES work. 
Last I checked 'a+' and 'a+++' are both strings.  Therefore the fact that one is _not_ accepted and the other one _is_ can't have anything to do with being strings.   Could it be size by any chance ? ...

the fact is, if it accepts DWORD('a') and DWORD('a+++') then it should accept any string that is between 1 and 4 characters because it should do the same padding it is doing when it sees DWORD('a').

if it didn't accept DWORD('a') then and only then it would be justified in accepting only 4 character strings.



Here is a small example of how inconsistent FPC is when it comes to typecasting:
Code: Pascal  [Select][+][-]
  1.   b := boolean('a');  { no warning here, looks like 'a' is between 0 and 1            }
  2.   b := boolean($61);  { no warning here either $61 apparently is also between 0 and 1 }
  3.   b := boolean(512);  { Warning: range check error while evaluating constants (512 must be between 0 and 1) }
  4.  
the character 'a' apparently is between 0 and 1 because no warning is issued about the range.
the number $61 seems to also be between 0 and 1 because no warning is issued about the range.
the number 512 is NOT between 0 and 1 (good that it notices that.)

Maybe typecasting 'a' and $61 to boolean is "undefined territory" while typecasting 512 isn't.  That must be it.  'a' and $61 didn't make it into the contract but 512 fortunately did. That's a relief... at least some things made it.

Good thing there is strong type checking to warn the programmer that any number (or character) above 255 isn't between 0 and 1.   That is so informative and useful.
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 04:50:54 pm
Maybe there is one thing we could all agree on

Never.

which is: the type boolean is NOT the same as the type BOOL (at least it isn't supposed to be but, it is in FPC)

This type is true whenever it is not zero, false only when it equals zero. Type Boolean if FPC is True only when it equals one. It is False only when it equals zero.

This is obviously different.
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 05:03:53 pm
Type Boolean if FPC is True only when it equals one. It is False only when it equals zero.
But, that's not true.

In FPC a boolean that has any value other than 1 is TRUE which is very different than what it's supposed to be and very different than what is documented.

What you stated is what it's supposed to be and, it isn't remotely that way.  That's has been proved in quite a few ways by now.


Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 05:35:19 pm
Try DWORD('a'+'') and you will see that it fails for a string (long or short $H+/-). Because a string has no ordinal value. And the wrong size in this case.
DWORD('a+') does NOT work but...

Your copy differs. It isn't 'a+' => string with 2 chars.

I wrote 'a' +''  => joining with the empty string, to get a STRING with len=1 (rather than a char / which has no length).

You can do: ord('a')
But you can not do: ord('a' + '')
Nor ord('abc')

Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 05:40:42 pm
In FPC a boolean that has any value other than 1 is TRUE

Wrong.
It is true only if it equals 1, false only when it equals zero, all other values are undefined.
If you find anything in fpc sources that doesn't comply with that, please (only then) report.
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 05:51:47 pm
Type Boolean if FPC is True only when it equals one. It is False only when it equals zero.
But, that's not true.

In FPC a boolean that has any value other than 1 is TRUE which is very different than what it's supposed to be and very different than what is documented.

No that is wrong

The ordinal (be that bit, word, integer...) => 0 is false
The ordinal (be that bit, word, integer...) => 1 is true

Everything else does not have a defined boolean state.

Of course if you compile "Boolean(2)" it will return one of the 2 states. But which of those 2 states is not defined. Even if all existing versions with all variations of all compile time settings would return the same state, this isn't guaranteed to persist for the future. It is fluke that it manifest of the one or other state. It is not defined.

If I use pen and paper, then I may write down 0 or 1 (or if agreed with my coworkers True/False) for the 2 states. But the paper still allows me to write 3 or Foo, and then it simply isn't valid anymore. I can not trust what my co-workers will do with those tokens.
Yet paper as storage allows the extra info => that does not invalidate the concept of boolean expressions written on Paper. What makes it "no longer boolean" is if I write down undefined tokens.

Using a bigger storage in a computer still is valid boolean. But If I poke something else (other than the defined states) into that storage, then it isn't boolean anymore.

You said yourself, there is no 3rd state. So if it isn't 0 or 1 then it is the same as "foo" on a piece of paper => not defined. But who knows what my coworker may read of it. They blindly trust me, that whatever I wrote will be correct. So they may see the leading "f" or they may recognise its the shorter of the 2 tokens. The outcome is not defined.

Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 06:11:45 pm
Wrong.

It is true only if it equals 1, false only when it equals zero, all other values are undefined.
You believe that ? ... I got a really good deal for you on a bridge in NY...

It has already been shown that FPC will consider any value other than 0 to be TRUE for a boolean.  That's not undefined territory, that's a FACT.  That's been proved, your wishful thinking doesn't change reality.

You and/or anyone else for that matter, can claim Santa Claus exists but, it doesn't make it that way.



@Martin,

The point remains the same, FPC can't tell a boolean from a dead duck.

It accepts DWORD('a') which it should not.  It should require ord('a') because of the size mismatch but, since it accepts that then it should also accept DWORD('ab') and DWORD('abc') but it doesn't.

The bottom line is this: FPC erroneously considers a boolean as a data type consisting of 8, 16, 32 or 64 bits which is an atrocity.  A boolean is a single bit.   The container is NOT the type.

Plus, it's patently wrong and absurd for the compiler to accept boolean(8) without any complaint whatsoever but complain about boolean(512).  That proves beyond any doubt, reasonable or otherwise, that FPC _incorrectly_ considers a boolean a byte/word/dword/qword sized type, when it is not.   

There is no boolean in FPC.  In FPC the boolean type is "undefined" and _unknown_ "territory".



I love Pascal but, it is no wonder it's on its way to the grave.  Some of it's developers (and some of its users) have no regard whatsoever for logical and mathematical correctness.  writable constants, boolean characters and strings, $61 is between 0 and 1, 0 is a signed numeral... etc, etc,
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 06:21:32 pm
It has already been shown that FPC will consider any value other than 0 to be TRUE for a boolean.  That's not undefined territory, that's a FACT.  That's been proved, your wishful thinking doesn't change reality.

Really? I have not seen that proof.

What I have seen is statements in which undefined was confused with either true or false.

Mind "undefined" is not the same as null in sql. It doesn't have a predictable outcome. But it has an observable outcome. And once I observed, I can repeat if I keep the relevant parameters the same (and in some cases, the relevant parameters may currently not be change able, but that does not change that it is undefined to start with).

And before you say "boolean does only have 2 states, there is no undefined" => undefined here means that boolean no longer applies (even if the type still has that name). undefined means the type specific behaviour has been switched off.  (coincidences may happen, but they are coincidences).
Title: Re: Boolean type
Post by: TRon on April 22, 2025, 06:34:49 pm
Is this conversion behaviour documented anywhere? Not a word about it in https://www.freepascal.org/docs-html/ref/refse85.html#x147-17100012.5 (http://Variable typecast) page.
operator overloading ?

Quote
How can we tell when it is not a cast but a conversion? Why wasn't assignment compatibility of Integer to Double good enough?
Basically you can't unless you know which ones are 'active'.

But Delphi compatibility would be the priority... This mess came from Embarcadero, right?
No matter who or what is responsible the compatibility does it and which renders these kind of discussions completely useless imho. But that compatibility is a joke on itself (sometimes intentional, sometimes by accident).
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 06:51:39 pm
Really? I have not seen that proof.

No problem...

Code: Pascal  [Select][+][-]
  1. program _BooleanType;
  2.   { proof that boolean = bytebool                                             }
  3.  
  4.   { there is NO boolean type in FPC                                           }
  5.  
  6. var
  7.   i          : integer;
  8.  
  9. begin
  10.   { what an amazing coincidence that every value from 1 to 255 prints TRUE,   }
  11.   { surprisingly consistent for something that is supposedly "undefined"      }
  12.  
  13.   for i := low(byte) to high(byte) do
  14.   begin
  15.     { no warning about typecasting an integer into a boolean.  Not even a     }
  16.     { hint about possible loss of range/precision or whatever you want to     }
  17.     { call it.                                                                }
  18.  
  19.     writeln('boolean(', i:3, ') : ', boolean(i):5);
  20.   end;
  21.  
  22.   writeln;
  23.  
  24.   { let's do some more "undefined territory" for fun                          }
  25.  
  26.   for i := low(byte) * 2 to high(byte) * 3 do
  27.   begin
  28.     { no warning about typecasting an integer into a boolean.  Not even a     }
  29.     { hint about possible loss of range/precision or whatever you want to     }
  30.     { it.                                                                     }
  31.  
  32.     writeln('boolean(', i:3, ') : ', boolean(i):5, ' byte(', i:3, ') : ', byte(i));
  33.   end;
  34.  
  35.  
  36.   readln;
  37. end.            
  38.  
but, of course, it's pure coincidence that any value that ends up being a zero byte is considered FALSE while any other value is TRUE.  Amazing how "undefined territory" is so consistent.  Heck!, undefined territory is more consistent than the way FPC handles typecasting.

Any type that implements more than 2 states is NOT, by definition, a boolean type.  It's something else, most likely a C BOOL but most definitely not a boolean.  FPC's boolean is a boolean like the Pope is a Russian astronaut. 
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 07:00:35 pm
Wrong.

It is true only if it equals 1, false only when it equals zero, all other values are undefined.
You believe that ? ... I got a really good deal for you on a bridge in NY...

Hm... I have no reason not to believe that Boolean is implemented according to what is documented. If you can show it is not, please do.
What is documented is - a byte of value 0 is treated as False, byte of value 1 is treated as True. All other 254 values are treated anyhow. So please report if you encounter that the implementation does not follow this specification.

It has already been shown that FPC will consider any value other than 0 to be TRUE for a boolean.  That's not undefined territory, that's a FACT.  That's been proved, your wishful thinking doesn't change reality.

Do you expect that a prng should be engaged to provide random output for undefined values, to persuade you that they are undefined? ;)

If it is implemented somewhere that it treats zero as False, and all other values as 1, it is obviously in line with what's documented - zero is false, one is true, anything else - whatever.
Of course, you must never rely on what you get once for any undefined situation. In next fpc version, or even in current, but for different target, you can get different value in same situation.

You and/or anyone else for that matter, can claim Santa Claus exists but, it doesn't make it that way.


The malicious claims about Santa Claus will get you no good. Expect nothing for next Christmas.
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 07:10:57 pm
Hm... I have no reason not to believe that Boolean is implemented according to what is documented.
Of course not.  Nothing other than the program posted above.

Why settle for facts when you can simply claim whatever you'd like reality to be ?... (sadly, that's becoming too common)

The documentation states that when it comes to boolean, only 1 is TRUE.  That is NOT reality.  Any value other than 0 is considered TRUE and, supposedly that's only the case for BOOL types not boolean.

You need to read the documentation again.
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 07:13:06 pm
Is this conversion behaviour documented anywhere? Not a word about it in https://www.freepascal.org/docs-html/ref/refse85.html#x147-17100012.5 (http://Variable typecast) page.
operator overloading ?


What about operator overloading?
With that, among other things, you get the assignment compatibility, and as expected, the integer value converts to Double when assigning.

So, if you want that, you simply use:
Code: [Select]
DoubleVar := Int64Var;But if you explicitly use type casting:
Code: [Select]
DoubleVar := Double(Int64Var);then you obviously don't expect to get the same as with simple direct assignment.
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 07:22:36 pm
Hm... I have no reason not to believe that Boolean is implemented according to what is documented.
Of course not.  Nothing other than the program posted above.

All I could see from that programme is that you actually expect a prng engaged to get you random values, in order to accept the fact that the value is undefined.  ::)

You need to read the documentation again.

I wonder what new I will see there...
But...
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. Of course, any expression that resolves to a boolean value, can also be assigned to a boolean type.
there seems to be nothing new...
Title: Re: Boolean type
Post by: ASerge on April 22, 2025, 07:24:03 pm
It has already been shown that FPC will consider any value other than 0 to be TRUE for a boolean.
Not always.
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$IFDEF WINDOWS}
  3.   {$APPTYPE CONSOLE}
  4. {$ENDIF}
  5.  
  6. procedure PrintBoolean(V: Boolean);
  7. const
  8.   CNames: array[0..2] of string = ('False', 'True', 'Error');
  9. begin
  10.   Writeln(CNames[Ord(V)]);
  11. end;
  12.  
  13. var
  14.   VBool: Boolean;
  15.   VByte: Byte = 2;
  16. begin
  17.   VBool := Boolean(VByte); // Only bad programmers do that
  18.   PrintBoolean(VBool); // Error
  19.   VBool := VByte <> 0; // The right programmers do this
  20.   PrintBoolean(VBool); // True
  21.   Readln;
  22. end.

About typecast.
Personally, I would prefer that the compiler returns an error when typecast if the size (sizeof) of the type and the value are different. Otherwise, nothing. I explicitly specified the typecast, why else warn about it.

In general, typecast should be avoided, as it violates the strictness of the language.

Bad style            Good style


Boolean(IntVal)IntVal <> 0
Integer(BoolVal)Ord(BoolVal)
Float(IntVal)IntVal + 0.0

Title: Re: Boolean type
Post by: BeniBela on April 22, 2025, 07:25:59 pm
FPC's boolean is a boolean like the Pope is a Russian astronaut.

is that true?

at the moment there is no Pope

for something that does not exist everything is true.  the Pope is a Russian astronaut. and  the Pope is not a Russian astronaut.
Title: Re: Boolean type
Post by: TRon on April 22, 2025, 07:44:06 pm
But if you explicitly use type casting:
Code: [Select]
DoubleVar := Double(Int64Var);then you obviously don't expect to get the same as with simple direct assignment.
Explicit overloading, see also here (https://www.freepascal.org/docs-html/ref/refse104.html#x224-24800015.3).

That global operators on system types are not allowed is an implementation detail (and one for good reason)


for something that does not exist everything is true.  the Pope is a Russian astronaut. and  the Pope is not a Russian astronaut.
a qubit  :)
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 08:05:40 pm
Explicit overloading, see also here (https://www.freepascal.org/docs-html/ref/refse104.html#x224-24800015.3).

Ah, yes, there it is documented:
Quote
When doing an explicit typecast, the compiler will attempt an implicit conversion if an assignment operator is present.

So, the assignment will be used when typecasting.

And then, below:
Quote
However, an Explicit operator can be defined, and then it will be used instead when the compiler encounters a typecast.
I have missed these things.
Not that I like this... but now I know!  ;)

Thanks a lot.
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 08:13:54 pm
Really? I have not seen that proof.

No problem...

Code: Pascal  [Select][+][-]
  1.   { what an amazing coincidence that every value from 1 to 255 prints TRUE,   }
  2.   { surprisingly consistent for something that is supposedly "undefined"      }
  3.  

Why uprising?  Undefined is not necessarily random.

What you demonstrate is undefined behaviour. Even if it is predictable under the given circumstances.
Title: Re: Boolean type
Post by: TRon on April 22, 2025, 08:16:25 pm
I have missed these things.
Glad I could be of help (however slightly)

Quote
Not that I like this... but now I know!  ;)
It is another reason that renders this topic moot. It allows for the user to design its own type behaving exactly the way as user intended. Wish to create a boolean that is stored as text and can be assign as text , f.e. "PLEASEMAKETHISBOOLEANTRUE" the only accepted string to set it to true as possible implementation ? However weird, it is possible to do so.
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 08:50:40 pm


I didn't know the Pope had gone the way of the boolean type in FPC.    May he rest in peace.

Let's review some "creative" code:
Code: Pascal  [Select][+][-]
  1.  
  2. {$MODE OBJFPC}
  3. {$IFDEF WINDOWS}
  4.   {$APPTYPE CONSOLE}
  5. {$ENDIF}
  6.  
  7. procedure PrintBoolean(V: Boolean);
  8. const
  9.   { the correct definition.  if the parameter is a boolean then the index     }
  10.   { should also be a boolean. booleans can only have 2 values, they are 0 and }
  11.   { 1.  That's it.                                                            }
  12.  
  13.   { just like in a byte, the values can only be 0 through 255. cannot put 256 }
  14.   { in a byte.  The same thing applies to a boolean, can't put 2, 3... etc in }
  15.   { a boolean.                                                                }
  16.  
  17.   { you can put it in a BOOL but, a BOOL is NOT a boolean.                    }
  18.  
  19.   CNames: array[boolean] of string = ('False', 'True');
  20.  
  21.   { only bad programmers do that                                              }
  22.   { vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv          }
  23.  
  24.   CNamesOriginal : array[0..2] of string = ('False', 'True', 'Error');
  25.  
  26.   { and why should there be 3 values for a boolean ? a boolean is supposed to }
  27.   { have only 2 values.   What happens if the boolean value is 75 instead of  }
  28.   { 2 as you conveniently chose ?                                             }
  29.  
  30. begin
  31.   { only bad programmers would ord(V) particularly without doing any range    }
  32.   { checking.                                                                 }
  33.  
  34.   Writeln(CNames[V]);
  35. end;
  36.  
  37. var
  38.   VBool: Boolean;
  39.   VByte: Byte = 2;
  40. begin
  41.   { your program proves that FPC isn't considering a boolean variable as being}
  42.   { either TRUE or FALSE. It considers it a byte because it is using the      }
  43.   { value 2 to index in the array and a boolean cannot have the value 2, only }
  44.   { 0 and 1                                                                   }
  45.  
  46.   { there are plenty of ways the value of a boolean variable can be corrupted }
  47.   { it is not only a result of bad programming                                }
  48.  
  49.   VBool := Boolean(VByte);  { the value of VByte could be corrupted for a     }
  50.                             { number of reasons.                              }
  51.  
  52.   { FPC is using a boolean as if it were an byte index.  that's an atrocity   }
  53.   { a boolean isn't a byte.                                                   }
  54.  
  55.   PrintBoolean(VBool);      { fails to print anything                         }
  56.  
  57.   Readln;
  58. end.                      
  59.  

The original code proves that FPC isn't treating the boolean parameter as a boolean but as a byte value.  This is obvious because a boolean can only have the values 0 and 1, therefore it could never index the "error" string.

That program proves (again!) that, as far as FPC is concerned, a boolean is just a byte.  The same code can be used to show that depending on how you code the test, you can make the result to be TRUE or FALSE.  Take your pick.  So much for mathematical correctness.

if FPC had a correct implementation of the boolean type then, the PrintBoolean function would always output something because a bit is either 0 or 1 which would always cause a string from the array to be selected (instead of being "magically" out of range.)

Yet, another proof that FPC does NOT implement the boolean type.

Title: Re: Boolean type
Post by: LV on April 22, 2025, 08:54:39 pm
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode ObjFpc}
  4. {$R+}
  5.  
  6. type
  7.   TZeroOne = 0..1;
  8.  
  9.  
  10. var
  11.   B1, B2, B3, B4: boolean;
  12.  
  13. function boolean_(i: TZeroOne): boolean;
  14. begin
  15.   if i = 0 then result := false
  16.   else result := true;
  17. end;
  18.  
  19. begin
  20.   B1 := boolean_(0);
  21.   B2 := boolean_(1);
  22.   B3 := boolean_(1);
  23.   //B4 := boolean_(2);  // project1.lpr(23,19) Error: range check error
  24.                       // while evaluating constants (2 must be between 0 and 1)
  25.  
  26.   writeln(B1);        // Output: FALSE
  27.   writeln(B2);        // Output: TRUE
  28.   writeln(B3);        // Output: TRUE
  29.   writeln(B1 and B2); // Output: FALSE
  30.   writeln(B2 and B3); // Output: TRUE
  31.  
  32.   writeln( B1 = B2); // Output: FALSE
  33.   writeln( B3 = B2); // Output: TRUE
  34.  
  35.   readln;
  36. end.
  37.  
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 09:09:51 pm
The original code proves that FPC isn't treating the boolean parameter as a boolean but as a byte value.  This is obvious because a boolean can only have the values 0 and 1, therefore it could never index the "error" string.

What exactly do you try to tell....

Boolean vs Byte (or any other storage) is not a conflict.

Using the bit patterns 00000000 and 00000001 in a Byte is merely a matter of representation. Not of how the logic works.

If I put 0 and 1 on a paper, how round does the zero has to be before what I wrote is no longer boolean?

There are 2 states (as you stated more than twice / pun intended). And those 2 states can be represented in a byte (or word or dword or 256bit container or a page of 1024 bytes ....).

And as long as you do use the container with only boolean operation (store either true or false) only those 2 states are there. So that is correct.

And by the very means of boolean logic itself, if the compiler test for one of the 2 states, and it is not that state, then it is the other.
In fact it only needs to test any one part from which it can tell the difference.
If on a paper the terms True/False are used, the all I (as reader) need to do is to check if it starts with a "T". From that I can tell what it is.




If you use typecasts with data that does not match the known representations, then the container is no longer for boolean use (you started using it for something else). And any attempt to use it as if it were boolean will not have a defined outcome.

But if you don't change its usage, then it will behave according to the boolean rules.
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 09:31:55 pm
I have missed these things.
Glad I could be of help (however slightly)

Not so slightly. I've been using this language for decades and it's been a long time since I became too confident, at least with the constructs which I use regularly, and I do use type casting. It's rather strange I haven't had problems.

Quote
Not that I like this... but now I know!  ;)
It is another reason that renders this topic moot. It allows for the user to design its own type behaving exactly the way as user intended. Wish to create a boolean that is stored as text and can be assign as text , f.e. "PLEASEMAKETHISBOOLEANTRUE" the only accepted string to set it to true as possible implementation ? However weird, it is possible to do so.

I know that assignment behaviour can be defined and fine tuned with operator overloading, although I've never been interested in using this feature.

But I totally missed that it affects explicit cast.

I have never been attracted by operator overloading feature, though. To me it has always appeared overrated - having a method with an expressive long name has always looked like a better option than overloading an operator.
Title: Re: Boolean type
Post by: Thaddy on April 22, 2025, 09:45:19 pm
Is it documented anywhere? When can we expect conversion instead of cast?
It is documented on the fp-devel list at least.
The argument focussed on conversion in the sense that Pascal programmers would expect a value vs my dissenting opinion that the bitwise representation should be respected. I was in a minority of one (maybe two). And it was not my "usual" erratics, but firmly founded in theory and with examples.
It is to my knowledge also in the official documentation, but have to look that up: there is a reasoning somewhere that explains that fpc converts instead of leaving it alone.
[edit]
Found it, implicit and partially.
https://www.freepascal.org/docs-html/ref/refse85.html.

(and I am still of the opnion that a bit pattern representing either an integer or float of the same size should NOT be converted. 440bx code example shows the same)

Anyway, either over-casting or pointer magic can save the day.
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 10:19:48 pm
Boolean vs Byte (or any other storage) is not a conflict.
it shouldn't be a conflict but, FPC equates boolean to bytebool, that's a problem and a conflict because a boolean isn't a byte.  A boolean can only host 2 values, a byte can host 256 values, quite a difference.

What is downright atrocious is that FPC accepts a typecast such as boolean(73).  It's atrocious because 73 cannot fit in 1 bit and anything that remotely resembles a compiler knows that and would reject that.

That's just one of the _many_ problems with what FPC _pretends_ is a boolean.  Just taking the code from @ASerge, a boolean cannot index past 1 because it is limited to the values 0 and 1, yet in Serge's code a boolean is used as an index with the value 2.  This is even beyond what they can do at Cirque du Soleil.

It doesn't help that the behavior flies in the face of what the documentation states.  The documentation makes it very clear that a boolean is either zero or 1 and, it's quite obvious that is not the case.  If it were the case Serge's code could not output "error". 

Lastly, there is no amount of typecasting in the universe that can fit the value 72 (or any value greater than 1) in a single bit.  Yet one more proof that what FPC implements is NOT the boolean type but a bytebool (which it pretends is a boolean... obviously, with a lot of help from its friends who defend that atrocity.)

Of course, when all that FPC nonsense is pushed to its limits and falls apart, that's undefined territory.  I have to agree when something says that TRUE <> TRUE, that's definitely undefined territory and, it would have been very nice if it had also been never-discovered territory.  Stuffing values greater than 1 in what is by definition a single bit is not only undefined territory but quite a "breakthrough" (writable constants v2.0).

Anyway... it's rather obvious that we'll never agree just as it is obvious that FPC does not implement the boolean type. 

Title: Re: Boolean type
Post by: TRon on April 22, 2025, 10:27:09 pm
Anyway... it's rather obvious that we'll never agree just as it is obvious that FPC does not implement the boolean type.
fwiw I do not see eye to eye with everything you wrote but do agree that a boolean is just that: a boolean able to contain two different states.

I wonder how electronic engineers think about all of this :)
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 10:27:34 pm

You are repeating yourself. Still wrong. Please "slowly" reread my earlier posts. Thanks.
Title: Re: Boolean type
Post by: Thaddy on April 22, 2025, 10:30:36 pm
The only issue is really the optimization levels and fpc is not the only compiler that optimizes away its own definition. As I proved.
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 10:33:16 pm
You are repeating yourself. Still wrong. Please "slowly" reread my earlier posts. Thanks.
I was hoping that repetition would lead to understanding, unfortunately, it doesn't always work, but, it's worth a try just in case.

They are completely wrong regardless of the speed at which they are read. 

You're very welcome!
Title: Re: Boolean type
Post by: Zoran on April 22, 2025, 10:46:12 pm
Found it, implicit and partially.
https://www.freepascal.org/docs-html/ref/refse85.html.

Thank you, Thaddy.
TRon pointed already to where it is actually documented, you obviously missed our posts (a few posts above (https://forum.lazarus.freepascal.org/index.php/topic,70806.msg552886.html#msg552886)), which is no surprise, this thread became hardly readable.

It's documented under Assignment operators, it appears that when assignment operator is defined, the compiler use it implicitly also with casting. Not only that, but the casting behaviour can be further redefined by overriding explicit operator.
Title: Re: Boolean type
Post by: Thaddy on April 22, 2025, 11:04:26 pm
I wonder how electronic engineers think about all of this :)
That is actually a good comparison to show the zero vs any other value is expected.
Problem is most cs think otherwise: strict low or high.
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 11:09:01 pm
You are repeating yourself. Still wrong. Please "slowly" reread my earlier posts. Thanks.
I was hoping that repetition would lead to understanding, unfortunately, it doesn't always work, but, it's worth a try just in case.

They are completely wrong regardless of the speed at which they are read. 

You're very welcome!

I was hoping if I use your terminology (i.e. "very slow") then that would make it more comprehensible to you.

Well, I admit when I was wrong. My assumption about using "very slow" was wrong. Apologies for that.

But well it happens, and one single mistake of mine in the entire thread, well I can live with that.
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 11:18:33 pm
Well, I admit when I was wrong. My assumption about using "very slow" was wrong. Apologies for that.

But well it happens, and one single mistake of mine in the entire thread, well I can live with that.
You're making progress, you managed to see one of the times you were wrong.  In time you might see the many other ones too.

This is really good news... there is hope! :) 

Too bad there is no hope FPC will implement the boolean type correctly... oh well.  can't have it all I guess.


Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 11:25:38 pm
Too bad there is no hope FPC will implement the boolean type correctly... oh well.  can't have it all I guess.

Correct: "will implement" reference to the future. They can't do it in future, as it already has been done. No mistake (not in fpc, nor of mine in writing this).

But maybe you have a secret different version of FPC? The one that I have behaves.
Title: Re: Boolean type
Post by: 440bx on April 22, 2025, 11:38:02 pm
Correct: "will implement" reference to the future. They can't do it in future, as it already has been done. No mistake (not in fpc, nor of mine in writing this).
You're probably right that they can't do it in the future because if they were able to, they would have done in the past.
Title: Re: Boolean type
Post by: Martin_fr on April 22, 2025, 11:53:24 pm
Correct: "will implement" reference to the future. They can't do it in future, as it already has been done. No mistake (not in fpc, nor of mine in writing this).
You're probably right that they can't do it in the future because if they were able to, they would have done in the past.

Wrong mood. Not "would" but "did". Your welcome.
Title: Re: Boolean type
Post by: 440bx on April 23, 2025, 03:10:19 am
Wrong mood. Not "would" but "did". Your welcome.
You're just as correct as "Your welcome" which should be "You're welcome" but maybe it's just FPC English, like the FPC "boolean" thing. There is a resemblance but, it's still wrong.
TinyPortal © 2005-2018