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:
var
B: Boolean;
begin
// ...
if Byte(B) <> 0 then // you want to treat any non-zero as true
DoSomething;
// ...
if Byte(B) and 1 <> 0 then // you want bit 0 set or reset to represent true and false respectively
DoSomething;
// ...
if Byte(B) and 4 = 0 then // you want bit 3 unset to represent true, and bit 3 set to represent false
DoSomething;
// ...
end;
And many more possibilities. All equally valid.