----- Original Message ----- From: "Frank Heckenbach" ih8mj@fjf.gnu.de To: gpc@gnu.de Sent: Thursday, April 06, 2006 18:25 Subject: Re: Out of range values in
Bart van den Broek wrote:
If I (as an inactive observer) may comment / make a suggestion; when a constant of ByteBoole, WordBoole or LongBoole is evaluated, presumably at compile time, convert it to a value of type Boolean. As a consequence: type VeryTrue = ByteBool (10) .. ByteBool (42); means type VeryTrue = True..True; Also, in the test program fjf1102, (Ord (a) = 1) and (Ord (b) = 1) and
(Ord
(c) = 1) holds, and more specifically Ord( ByteBool(42) ) = 1.
Interesting idea, but if done only for constants (as I understand your suggestion), it would also lead to strange effects:
program foo;
var n: Integer = 42;
begin WriteLn (ByteBool (n) = ByteBool (42)) { => False } end.
Since the Borland Delphi 3 Object Pascal Language Guide mentions: "....Whenever a ByteBool, WordBool or LongBool value is used in a context where a Boolean value is expected, the compiler will automatically generate code that converts any nonzero value to the value True." If i interpret the expression ByteBool(n) = ByteBool(42) as "a context where a Boolean value is expected" then it is equivalent to (ByteBool(n) <> 0) = (ByteBool(42) <> 0), or (ByteBool(n) <> 0) = True, and foo would print True.
I don't think so (BTW, what does Delphi do?). The context here is `=' Since ByteBool is an ordinal type, and `=' allows the same ordinal type (among others) on both sides, ByteBool is valid. I.e., it's a context where Boolean is allowed, but not required. Contexts that require Boolean include the conditions in if, while, until, or assignments to Boolean variables, or Boolean value parameters.
Besides, it probably wouldn't be 100% Delphi compatible, as Delphi documentation (as quoted by Adriaan) states that Ord of "True" of such types can be any value <> 0.
Well, 1 is such a value <> 0, so how do u think it is incompatible?
OK, but if it were always 1, then they'd probably say so, and not write:
: Boolean ByteBool, WordBool, LongBool : Ord( True) = 1 Ord( True) = any non-zero value
I dont have Delphi available right now, but i vaguely remember Delphi does the following: ByteBool(True) = $FF WordBool(True) = $FFFF LongBool(True) = $FFFFFF If so (will check later) then this means my suggestion is different and maybe incompatible.
I don't either, but someone who does might want to check this (and the behaviour of my program above under Delphi). If really ByteBool(True) = $FF (I assume you mean Ord (ByteBool (True)) = $FF, or can you compare ByteBool and integers in Delphi?) that would complicate things, as normally (in BP and GPC) value type casts preserve ordinal values ...
Frank
-- Frank Heckenbach, frank@g-n-u.de, http://fjf.gnu.de/, 7977168E GPC To-Do list, latest features, fixed bugs: http://www.gnu-pascal.de/todo.html GPC download signing key: ACB3 79B2 7EB2 B7A7 EFDE D101 CD02 4C9D 0FE0 E5E8
Indeed I meant Ord(ByteBool(True)) = $FF and so on.
When I run this program in Delphi v7.1 (7.0 + patch)
program Project1;
{$APPTYPE CONSOLE}
procedure RunTest; var n : Integer; m : Integer; begin n := 42; m := 43; Writeln(ByteBool(n) = ByteBool(m)); Writeln(ByteBool(n) = ByteBool(42)); Writeln(ByteBool(n) = True); Writeln(Ord(ByteBool(True)));
Writeln(WordBool(n) = WordBool(m)); Writeln(WordBool(n) = WordBool(42)); Writeln(WordBool(n) = True); Writeln(Ord(WordBool(True)));
Writeln(LongBool(n) = LongBool(m)); Writeln(LongBool(n) = LongBool(42)); Writeln(LongBool(n) = True); Writeln(Ord(LongBool(True)));
Writeln(Pred(Boolean(False))); Writeln(Pred(ByteBool(False))); Writeln(Pred(WordBool(False))); Writeln(Pred(LongBool(False))); end;
begin RunTest; end.
I get this output (ignore extra empty lines i put in):
TRUE TRUE TRUE 255
TRUE TRUE TRUE 65535
TRUE TRUE TRUE -1
<gibberish> <gibberish> TRUE TRUE
Note the signedness of the Ord(LongBool(True)), probably due to the fact that Ord function is 32 bits integer.
I guess being completely compatible here is not simple.
Bart
On 6 Apr 2006 at 20:15, Bart van den Broek wrote:
[...]
When I run this program in Delphi v7.1 (7.0 + patch)
program Project1;
{$APPTYPE CONSOLE}
procedure RunTest; var n : Integer; m : Integer; begin n := 42; m := 43; Writeln(ByteBool(n) = ByteBool(m)); Writeln(ByteBool(n) = ByteBool(42)); Writeln(ByteBool(n) = True); Writeln(Ord(ByteBool(True)));
Writeln(WordBool(n) = WordBool(m)); Writeln(WordBool(n) = WordBool(42)); Writeln(WordBool(n) = True); Writeln(Ord(WordBool(True)));
Writeln(LongBool(n) = LongBool(m)); Writeln(LongBool(n) = LongBool(42)); Writeln(LongBool(n) = True); Writeln(Ord(LongBool(True)));
Writeln(Pred(Boolean(False))); Writeln(Pred(ByteBool(False))); Writeln(Pred(WordBool(False))); Writeln(Pred(LongBool(False))); end;
begin RunTest; end.
[...]
1. Delphi 3.0 and Delphi 4.0: TRUE FALSE TRUE 255 ----------------------- TRUE FALSE TRUE 65535 ----------------------- TRUE FALSE TRUE -1 ----------------------- TRUE TRUE TRUE TRUE
Delphi 7: TRUE TRUE TRUE 255 ----------------------- TRUE TRUE TRUE 65535 ----------------------- TRUE TRUE TRUE -1 ----------------------- Runtime error 216 at 00402BC4 (program GPFs here)
FPC (2.0.0): TRUE TRUE TRUE 1 ----------------------- TRUE TRUE TRUE 1 ----------------------- FALSE TRUE TRUE 1 ----------------------- TRUE TRUE TRUE TRUE
But gives "Warning: range check error while evaluating constants" on these two lines at compile time: Writeln(Pred(WordBool(False))); Writeln(Pred(LongBool(False)));
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Bart van den Broek wrote:
Indeed I meant Ord(ByteBool(True)) = $FF and so on.
When I run this program in Delphi v7.1 (7.0 + patch)
program Project1;
{$APPTYPE CONSOLE}
procedure RunTest; var n : Integer; m : Integer; begin n := 42; m := 43; Writeln(ByteBool(n) = ByteBool(m)); Writeln(ByteBool(n) = ByteBool(42)); Writeln(ByteBool(n) = True); Writeln(Ord(ByteBool(True)));
Writeln(WordBool(n) = WordBool(m)); Writeln(WordBool(n) = WordBool(42)); Writeln(WordBool(n) = True); Writeln(Ord(WordBool(True)));
Writeln(LongBool(n) = LongBool(m)); Writeln(LongBool(n) = LongBool(42)); Writeln(LongBool(n) = True); Writeln(Ord(LongBool(True)));
Writeln(Pred(Boolean(False))); Writeln(Pred(ByteBool(False))); Writeln(Pred(WordBool(False))); Writeln(Pred(LongBool(False))); end;
begin RunTest; end.
I get this output (ignore extra empty lines i put in):
TRUE TRUE TRUE 255
TRUE TRUE TRUE 65535
TRUE TRUE TRUE -1
<gibberish> <gibberish> TRUE TRUE
Note the signedness of the Ord(LongBool(True)), probably due to the fact that Ord function is 32 bits integer.
BTW, is it really the Ord function in general? Does Ord applied to an unsigned 32 bit integer convert it to signed? If not (as I hope ;-), it seems to be not a property of the Ord function, but of the LongBool type (perhaps from times when Delphi didn't support unsigned 32 bit).
I guess being completely compatible here is not simple.
I really think so -- also considering The Chief's tests. Does anyone know if the different behaviour between Delphi 3/4 and 7 is documented? Otherwise we might just say Delphi's behaviour is not precisely defined in the first place ...
BTW, FPC's behaviour is also interesting, m and n are considered equal in ByteBool and WordBool, but not in LongBool.
Considering C compatibility, most C functions that expect a Boolean argument in an integer will probably accept any non-zero value as true, though the documented value is often (IMHO) 1, often via a #define TRUE 1 or such, rarely 0xff, 0xffff, 0xffffffff, -1 or such. This would suggest making Ord (FooBool (True)) always 1 (in accordance with FPC, and with general BP type-cast rules, but in contrast to Delphi).
Seeing these questions, I'd rather get rid of such types at all, if we didn't need them for Delphi compatibility ... :-(
Frank