Waldek wrote (in private mail, but I hope you don't mind me forwarding it to the list, as it concerns the current discussion about bitsizes):
I have noticed that fjf395[ab].pas expects to be able to compute on out of range values. Both of them fail with 4.1 backend. According to recent discussion on GCC list using out of range values is illegal (if we consider such values legal the type should have bigger bounds).
I would prefer to declare fjf395[ab].pas illegal and remove them from the testsuite. And say that user programs expecting such behaviour should be fixed.
Yes, the test programs are currently wrong as they put ordinal values > 1 in `Boolean attribute (Size = n)' variables. I wrote them at a time when semantics of `Boolean (n)' (as they were called back then) were not very clearly defined ...
The other solution is "double accounting", when we have types with loose bounds for backend use, but we separatly track ranges in the front end.
I'd prefer to avoid this, as it'd surely add quite some effort for probably little gain. In fact, as integer ranges can be freely declared, and we don't (yet) support bitsizes for types other than integers and Booleans, it seems to affect only Booleans with specified bitsize, which is a very special case.
So we have the choice either to leave the range at False {0} .. True {1}, and forbid other values, and change the test programs, or to really declare the range according to the bitsize (e.g. False {0} and 255 values of True for an 8 bit type).
The former would seem more Pascalish. OTOH, such types are probably often used for C interfaces, and what will happen if C routines put values > 1 in them? Probably undefined stuff (e.g., the backend would be free to check only bit 0 or byte 0), so we'd have to declare this invalid, which limits the use of these types.
With the latter, we'd get some strange semantics (such as `Ord (High (...))' of such types not yielding 1) -- or rather, we'd retain them, as some strange semantics are already there:
program Foo;
type t = Boolean attribute (Size = 8);
var a, b: t;
begin a := t (5); b := t (2); WriteLn (a); WriteLn (b); WriteLn (a = b) end.
Says:
True True False
And contrary to Adriaan's previous suggestion we'd actually need a pseudo-schema then, as `Boolean attribute (BitSize = 8)' according to his proposal would yield a 0 .. 1 range.
But still, the latter seems the lesser evil to me ATM, as otherwise these types might not be very useful at all ...
Or can/should we drop them altogether? Are they needed for Delphi compatibility? Or does someone seriously need them (where they can't just be replaced with bitsize-Integers, adding `<> 0' and `Ord' where necessary)?
Frank
Frank Heckenbach wrote:
Waldek wrote (in private mail, but I hope you don't mind me forwarding it to the list, as it concerns the current discussion about bitsizes):
I have noticed that fjf395[ab].pas expects to be able to compute on out of range values. Both of them fail with 4.1 backend. According to recent discussion on GCC list using out of range values is illegal (if we consider such values legal the type should have bigger bounds).
I would prefer to declare fjf395[ab].pas illegal and remove them from the testsuite. And say that user programs expecting such behaviour should be fixed.
Yes, the test programs are currently wrong as they put ordinal values > 1 in `Boolean attribute (Size = n)' variables. I wrote them at a time when semantics of `Boolean (n)' (as they were called back then) were not very clearly defined ...
The other solution is "double accounting", when we have types with loose bounds for backend use, but we separatly track ranges in the front end.
I'd prefer to avoid this, as it'd surely add quite some effort for probably little gain. In fact, as integer ranges can be freely declared, and we don't (yet) support bitsizes for types other than integers and Booleans, it seems to affect only Booleans with specified bitsize, which is a very special case.
So we have the choice either to leave the range at False {0} .. True {1}, and forbid other values, and change the test programs,
In my opinion, the only correct option.
or to really declare the range according to the bitsize (e.g. False {0} and 255 values of True for an 8 bit type).
The former would seem more Pascalish. OTOH, such types are probably often used for C interfaces, and what will happen if C routines put values > 1 in them?
Use an integer or cardinal type instead (for example in the Win32 API, but that API is a mess anyway, dependent on the call you have to check for <> 0 or = 0 or <> 1 or =1).
Regards,
Adriaan van Os
Adriaan van Os wrote:
So we have the choice either to leave the range at False {0} .. True {1}, and forbid other values, and change the test programs,
In my opinion, the only correct option.
Then I doubt whether we need such types at all (unless required for compatibility to Delphi or something).
or to really declare the range according to the bitsize (e.g. False {0} and 255 values of True for an 8 bit type).
The former would seem more Pascalish. OTOH, such types are probably often used for C interfaces, and what will happen if C routines put values > 1 in them?
Use an integer or cardinal type instead (for example in the Win32 API, but that API is a mess anyway, dependent on the call you have to check for <> 0 or = 0 or <> 1 or =1).
I don't know this API. Do you mean there are functions where 0 means False, 1 means True, but 2, 3, ... means False? (Or vice versa?) Ouch!
Frank
On 4-apr-06, at 22:48, Frank Heckenbach wrote:
Adriaan van Os wrote:
So we have the choice either to leave the range at False {0} .. True {1}, and forbid other values, and change the test programs,
In my opinion, the only correct option.
Then I doubt whether we need such types at all (unless required for compatibility to Delphi or something).
or to really declare the range according to the bitsize (e.g. False {0} and 255 values of True for an 8 bit type).
The former would seem more Pascalish. OTOH, such types are probably often used for C interfaces, and what will happen if C routines put values > 1 in them?
Use an integer or cardinal type instead (for example in the Win32 API, but that API is a mess anyway, dependent on the call you have to check for <> 0 or = 0 or <> 1 or =1).
I don't know this API. Do you mean there are functions where 0 means False, 1 means True, but 2, 3, ... means False? (Or vice versa?) Ouch!
Some examples (but I have seem more weird cases)
SystemParametersInfo <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ sysinfo/base/systemparametersinfo.asp> If the function succeeds, the return value is a nonzero value. If the function fails, the return value is zero. To get extended error information, call GetLastError.
SHGetPathFromIDList <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ wceshellui5/html/wce50lrfshgetpathfromidlist.asp> TRUE indicates success. FALSE indicates failure.
DeviceCapabilities <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/ prntspol_21bn.asp> If the function succeeds, the return value depends on the setting of the fwCapability parameter. A return value of zero generally indicates that, while the function completed successfully, there was some type of failure, such as a capability that is not supported. For more details, see the descriptions for the fwCapability values. If the function fails, the return value is -1.
Regards,
Adriaan van Os
Adriaan van Os wrote:
Frank Heckenbach wrote:
Adriaan van Os wrote:
So we have the choice either to leave the range at False {0} .. True {1}, and forbid other values, and change the test programs,
In my opinion, the only correct option.
Then I doubt whether we need such types at all (unless required for compatibility to Delphi or something).
or to really declare the range according to the bitsize (e.g. False {0} and 255 values of True for an 8 bit type).
The former would seem more Pascalish. OTOH, such types are probably often used for C interfaces, and what will happen if C routines put values > 1 in them?
Use an integer or cardinal type instead (for example in the Win32 API, but that API is a mess anyway, dependent on the call you have to check for <> 0 or = 0 or <> 1 or =1).
I don't know this API. Do you mean there are functions where 0 means False, 1 means True, but 2, 3, ... means False? (Or vice versa?) Ouch!
Some examples (but I have seem more weird cases)
SystemParametersInfo <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ sysinfo/base/systemparametersinfo.asp> If the function succeeds, the return value is a nonzero value. If the function fails, the return value is zero. To get extended error information, call GetLastError.
SHGetPathFromIDList <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ wceshellui5/html/wce50lrfshgetpathfromidlist.asp> TRUE indicates success. FALSE indicates failure.
DeviceCapabilities <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/ prntspol_21bn.asp> If the function succeeds, the return value depends on the setting of the fwCapability parameter. A return value of zero generally indicates that, while the function completed successfully, there was some type of failure, such as a capability that is not supported. For more details, see the descriptions for the fwCapability values. If the function fails, the return value is -1.
Hm, now that I have written this down, I start to wonder if "boolean attribute ..." wasn't invented to be compatible with the Win32 API. I had a look at the Borland Delphi 3 Object Pascal Language Guide (page 4-5 to 4-6).
"Boolean types There are four predefined Boolean types: Boolean, ByteBool, WordBool and LongBool. Boolean values are denoted by the predefined constant identifiers False and True. Because Booleans are enumerated types, these relationships hold:
Boolean ByteBool, WordBool, LongBool False < True False<>True Ord( False) = 0 Ord( False) = 0 Ord( True) = 1 Ord( True) = any non-zero value Succ( False) = True Succ( False) = True Pred( False) = True Pred( False) = True "
(I wonder if the last line isn't a printing error meant to say Pred( True) = False)
"Boolean and ByteBool variables occupy one byte, a WordBool variable occupies two bytes (one word) and a LongBool variable occupies four bytes (two words). Boolean is the preferred type and uses the least memory: ByteBool, WordBool and LongBool primarily exist to provide compatibility with other languages and the Windows environment.
A Boolean variable can assume the ordinal values 0 and 1 only, but variables of type ByteBool, WordBool and LongBool can assume other ordinal values. An expression of type ByteBool, WordBool or LongBool is considered False when its ordinal value is zero, and True when its ordinal value is nonzero. 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."
So far the Borland Delphi 3 Object Pascal Language Guide.
Looks like, for compatibility, we have to distinguish clearly between the Pascal Boolean type and C-derived "integer" booleans, for example:
ByteBool = IntBoolOfBitSize (8) WordBool = IntBoolOfBitSize (16) LongBool = IntBoolOfBitSize (32)
again deprecating "boolean attribute ..."
Regards,
Adriaan van Os
Adriaan van Os wrote:
Use an integer or cardinal type instead (for example in the Win32 API, but that API is a mess anyway, dependent on the call you have to check for <> 0 or = 0 or <> 1 or =1).
I don't know this API. Do you mean there are functions where 0 means False, 1 means True, but 2, 3, ... means False? (Or vice versa?) Ouch!
Some examples (but I have seem more weird cases)
SystemParametersInfo <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ sysinfo/base/systemparametersinfo.asp> If the function succeeds, the return value is a nonzero value. If the function fails, the return value is zero. To get extended error information, call GetLastError.
So that's <> 0, fine.
SHGetPathFromIDList <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ wceshellui5/html/wce50lrfshgetpathfromidlist.asp> TRUE indicates success. FALSE indicates failure.
Assuming FALSE = 0 and TRUE = 1 or some other value <> 0, and no other return values are possible, that's also fine with <> 0.
DeviceCapabilities <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/ prntspol_21bn.asp> If the function succeeds, the return value depends on the setting of the fwCapability parameter. A return value of zero generally indicates that, while the function completed successfully, there was some type of failure, such as a capability that is not supported. For more details, see the descriptions for the fwCapability values. If the function fails, the return value is -1.
Is this description complete? -1 is failure, 0 is "generally [...] some type of failure"? Then > 0 is success, or what? Since -1 and 0 "generally" seem to have to be distinguished, that's just not a Boolean (two-valued) result, so one should just use an integer result type.
I'd yet have to see the weirder cases, but so far I see no problem. Perhaps there are perceived problems when not all results are possible.
There's a similar situation with some POSIX routines that return a file descriptor or some other value guaranteed >= 0 when successful and -1 (as documented) on failure. Some C programmers seem to believe they have to test for == -1 for failure. But actually, since values < -1 cannot occur at all according to the documentation, checking < 0 for failure is just as good -- probably even better since getting an "impossible" value < -1 would really be a serious failure (and apart from the fact that < 0 is both shorter to write and often generates easier machine code than == -1).
(I don't mean that these are Boolean results -- clearly not, since values >= 0 must be distinguished --, but that sometimes one sees things more complicated than necessary by reading documentation too literally.)
Hm, now that I have written this down, I start to wonder if "boolean attribute ..." wasn't invented to be compatible with the Win32 API. I had a look at the Borland Delphi 3 Object Pascal Language Guide (page 4-5 to 4-6).
Not particularly the Win32 API, but generally external interfaces, yes. After all, for usage within Pascal code, we don't need specific storage requirements.
"Boolean types There are four predefined Boolean types: Boolean, ByteBool, WordBool and LongBool. Boolean values are denoted by the predefined constant identifiers False and True. Because Booleans are enumerated types, these relationships hold:
Boolean ByteBool, WordBool, LongBool False < True False<>True Ord( False) = 0 Ord( False) = 0 Ord( True) = 1 Ord( True) = any non-zero value Succ( False) = True Succ( False) = True Pred( False) = True Pred( False) = True "
(I wonder if the last line isn't a printing error meant to say Pred( True) = False)
Yes, the last line is strange. The right side would hold for extended Boolean types with negative ordinal values, or with wrap-around without overflow checking (which isn't exactly something I'd make documented behaviour).
OTOH, Pred (True) = False is right for standard Boolean, but not for extended Booleans when calling any non-zero value "True" as they do.
A Boolean variable can assume the ordinal values 0 and 1 only, but variables of type ByteBool, WordBool and LongBool can assume other ordinal values.
I think that's the main point. So for compatibility, it seems we should extend the range of the larger Boolean types. The predefined value "True" would, of course, still yield ordinal 1, but an extended Boolean might function as "true" in conditionals, but have Ord (...) > 1 (or < 0 if we'd allow for "signed" types, but so far I see no need to).
An expression of type ByteBool, WordBool or LongBool is considered False when its ordinal value is zero, and True when its ordinal value is nonzero.
So clearly <> 0, which GPC already does (being derived from C, no surprise).
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."
GPC does this (actually kind of inadvertently -- AFAIR, the respective code was added to avoid type and/or range problems in such conversions, but it does just that). To be sure, I'm adding the following test program:
program fjf1102 (Output);
var a: ByteBool; b: WordBool; c: LongBool; d, e, f: Boolean;
begin a := ByteBool (42); b := WordBool (1000); c := LongBool ($10000); d := a; e := b; f := c; if (Ord (d) = 1) and (Ord (e) = 1) and (Ord (f) = 1) then WriteLn ('OK') else WriteLn ('failed ', Ord (d), Ord (e), Ord (f)) end.
Looks like, for compatibility, we have to distinguish clearly between the Pascal Boolean type and C-derived "integer" booleans, for example:
ByteBool = IntBoolOfBitSize (8) WordBool = IntBoolOfBitSize (16) LongBool = IntBoolOfBitSize (32)
again deprecating "boolean attribute ..."
Yes, seems so.
And now it gets really weird ...
type VeryTrue = ByteBool (10) .. ByteBool (42);
Frank
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.
Motivation: the top definition of VeryTrue deals with the internal representation of Booleans. If the programmer *wants* to deal with this, it is IMHO more clear to use the values 10 and 42 and cast later. Similarly, when a specific value other than 0 or 1 for, say a ByteBool parameter must be passed to an external library function, it is IMHO more clear to use Byte instead.
Bart van den Broek.
From: Frank Heckenbach ih8mj@fjf.gnu.de To: gpc@gnu.de Subject: Re: Out of range values in Date: Thu, 6 Apr 2006 01:14:19 +0200
Adriaan van Os wrote:
Use an integer or cardinal type instead (for example in the Win32
API,
but that API is a mess anyway, dependent on the call you have to
check
for <> 0 or = 0 or <> 1 or =1).
I don't know this API. Do you mean there are functions where 0 means False, 1 means True, but 2, 3, ... means False? (Or vice versa?) Ouch!
Some examples (but I have seem more weird cases)
SystemParametersInfo http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ sysinfo/base/systemparametersinfo.asp If the function succeeds, the return value is a nonzero value. If the function fails, the return value is zero. To get extended error information, call GetLastError.
So that's <> 0, fine.
SHGetPathFromIDList http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ wceshellui5/html/wce50lrfshgetpathfromidlist.asp TRUE indicates success. FALSE indicates failure.
Assuming FALSE = 0 and TRUE = 1 or some other value <> 0, and no other return values are possible, that's also fine with <> 0.
DeviceCapabilities http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/ prntspol_21bn.asp If the function succeeds, the return value depends on the setting of the fwCapability parameter. A return value of zero generally indicates that, while the function completed successfully, there was some type of failure, such as a capability that is not supported. For more details, see the descriptions for the fwCapability values. If the function fails, the return value is -1.
Is this description complete? -1 is failure, 0 is "generally [...] some type of failure"? Then > 0 is success, or what? Since -1 and 0 "generally" seem to have to be distinguished, that's just not a Boolean (two-valued) result, so one should just use an integer result type.
I'd yet have to see the weirder cases, but so far I see no problem. Perhaps there are perceived problems when not all results are possible.
There's a similar situation with some POSIX routines that return a file descriptor or some other value guaranteed >= 0 when successful and -1 (as documented) on failure. Some C programmers seem to believe they have to test for == -1 for failure. But actually, since values < -1 cannot occur at all according to the documentation, checking < 0 for failure is just as good -- probably even better since getting an "impossible" value < -1 would really be a serious failure (and apart from the fact that < 0 is both shorter to write and often generates easier machine code than == -1).
(I don't mean that these are Boolean results -- clearly not, since values >= 0 must be distinguished --, but that sometimes one sees things more complicated than necessary by reading documentation too literally.)
Hm, now that I have written this down, I start to wonder if "boolean attribute ..." wasn't invented to be compatible with the Win32 API. I had a look at the Borland Delphi 3 Object Pascal Language Guide (page 4-5 to 4-6).
Not particularly the Win32 API, but generally external interfaces, yes. After all, for usage within Pascal code, we don't need specific storage requirements.
"Boolean types There are four predefined Boolean types: Boolean, ByteBool, WordBool and LongBool. Boolean values are denoted by the predefined constant identifiers False and True. Because Booleans are enumerated types, these relationships hold:
Boolean ByteBool, WordBool, LongBool False < True False<>True Ord( False) = 0 Ord( False) = 0 Ord( True) = 1 Ord( True) = any non-zero value Succ( False) = True Succ( False) = True Pred( False) = True Pred( False) = True "
(I wonder if the last line isn't a printing error meant to say Pred( True) = False)
Yes, the last line is strange. The right side would hold for extended Boolean types with negative ordinal values, or with wrap-around without overflow checking (which isn't exactly something I'd make documented behaviour).
OTOH, Pred (True) = False is right for standard Boolean, but not for extended Booleans when calling any non-zero value "True" as they do.
A Boolean variable can assume the ordinal values 0 and 1 only, but variables of type ByteBool, WordBool and LongBool can assume other ordinal values.
I think that's the main point. So for compatibility, it seems we should extend the range of the larger Boolean types. The predefined value "True" would, of course, still yield ordinal 1, but an extended Boolean might function as "true" in conditionals, but have Ord (...) > 1 (or < 0 if we'd allow for "signed" types, but so far I see no need to).
An expression of type ByteBool, WordBool or LongBool is considered False when its ordinal value is zero, and True when its ordinal value is nonzero.
So clearly <> 0, which GPC already does (being derived from C, no surprise).
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."
GPC does this (actually kind of inadvertently -- AFAIR, the respective code was added to avoid type and/or range problems in such conversions, but it does just that). To be sure, I'm adding the following test program:
program fjf1102 (Output);
var a: ByteBool; b: WordBool; c: LongBool; d, e, f: Boolean;
begin a := ByteBool (42); b := WordBool (1000); c := LongBool ($10000); d := a; e := b; f := c; if (Ord (d) = 1) and (Ord (e) = 1) and (Ord (f) = 1) then WriteLn ('OK') else WriteLn ('failed ', Ord (d), Ord (e), Ord (f)) end.
Looks like, for compatibility, we have to distinguish clearly between the Pascal Boolean type and C-derived "integer" booleans, for example:
ByteBool = IntBoolOfBitSize (8) WordBool = IntBoolOfBitSize (16) LongBool = IntBoolOfBitSize (32)
again deprecating "boolean attribute ..."
Yes, seems so.
And now it gets really weird ...
type VeryTrue = ByteBool (10) .. ByteBool (42);
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
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.
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.
Motivation: the top definition of VeryTrue deals with the internal representation of Booleans. If the programmer *wants* to deal with this, it is IMHO more clear to use the values 10 and 42 and cast later.
BTW, I didn't mean to advocate the use of types such as my VeryTrue for any purpose, just point out that such declarations are possible ...
Similarly, when a specific value other than 0 or 1 for, say a ByteBool parameter must be passed to an external library function, it is IMHO more clear to use Byte instead.
Ack.
Frank
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.
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? 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 won't dwell on this further and am happy to see what you decide.
Bart.
Frank
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
On 6 Apr 2006 at 17:56, 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.
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? I dont have Delphi available right now, but i vaguely remember Delphi does the following: ByteBool(True) = $FF WordBool(True) = $FFFF LongBool(True) = $FFFFFF
{$apptype console} begin Writeln ( ByteBool (True)); Writeln ( WordBool (True)); Writeln ( LongBool (True)); end.
Gives: TRUE TRUE TRUE on Delphi 3 and Delphi 4. Crashes on Delphi 7.
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Frank Heckenbach wrote:
Is this description complete? -1 is failure, 0 is "generally [...] some type of failure"? Then > 0 is success, or what? Since -1 and 0 "generally" seem to have to be distinguished, that's just not a Boolean (two-valued) result, so one should just use an integer result type.
I'd yet have to see the weirder cases, but so far I see no problem. Perhaps there are perceived problems when not all results are possible.
Probably, the weird cases don't have function result BOOL in the Win32 API, so I think you are right that testing <> 0 is OK after all.
Regards,
Adriaan van Os