Testing boolean expressions: ambiguity

Beta Testing discussion on mikroPascal PRO for PIC.
Post Reply
Author
Message
Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Testing boolean expressions: ambiguity

#1 Post by Dany » 05 Aug 2014 12:52

Hi, apparently also in mP (v6.4.0) values which differ from zero are seen as 'true', while in earlier versions only the value '255' was seen as 'true'. I do not know in which version exact things changed.

However: there is an anomaly now in the behaviour when testing actualy against the 'true' value:

Code: Select all

  var_ := 1;
  if var_            <---- expression is true
  if var_ = true     <---- expression is false
I think this 'creepage' towards C behaviour without other adaptations is very dangerous...

The full testcode and the results (pointed to by an arrow):

Code: Select all

program TrueTest;

{ Declarations section }

var var_: boolean;
     var_2: string[5];
     var_3: short;

begin
  { Main program }
  var_ := 1;
  
  if var_ 
  then var_2 := 'true'    // <---- difference with below!
  else var_2 := 'false';
  
  if var_ = true
  then var_2 := 'true'
  else var_2 := 'false';  // <---- difference with above!
  
  
  var_ := true;

  if var_
  then var_2 := 'true'    // <----  no difference with below
  else var_2 := 'false';

  if var_ = true
  then var_2 := 'true'    // <----  no difference with above
  else var_2 := 'false';

  var_3 := -1;
  if Var_3
  then var_2 := 'true'    // <----
  else var_2 := 'false';
  
  var_3 := 0;
  if Var_3
  then var_2 := 'true'
  else var_2 := 'false';  // <----
  
end.
Of course, for mP users which do only give the value 'true' and 'false' to boolean variables, and which do not test non boolean variables as if they were boolean, there is no danger at all. For others... :oops:

Due to this change mP has become a little less "stong typed". :shock:
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Testing boolean expressions: ambiguity

#2 Post by janni » 05 Aug 2014 16:58

Dany wrote:Hi, apparently also in mP (v6.4.0) values which differ from zero are seen as 'true', while in earlier versions only the value '255' was seen as 'true'. I do not know in which version exact things changed.
I'm afraid that it never was that simple and there were always problems with boolean expressions but you're right that there was a change - and quite some time ago.
Due to this change mP has become a little less "stong typed". :shock:
You well know that there's actually no boolean type in mP (and never was). When one declares a boolean variable, it's in fact of byte type. One wouldn't be able to assign value different than TRUE or FALSE to true boolean variable or constant. And then it wouldn't matter how compiler differentiates between TRUE and FALSE, would it? In fact it would also not matter how TRUE and FALSE are defined internally. Note that Pascal definition only states that TRUE and FALSE should be of ordinal type with TRUE following FALSE and that numbers of the truth values denoted by FALSE and TRUE should be the integer values 0 and 1 respectively. (Neither is true in present mP implementation.)

mE does realize that this is a problem and there are appropriate notes in Help - for example, the 'if' conditional description contains a note
The expression must convert to a boolean type; otherwise, the condition is ill-formed.
In other words, expression in 'if' statement has to evaluate to TRUE or FALSE. If it doesn't then the behaviour of 'if' statement is unpredictable (and always was).

As I mentioned, boolean expressions were always a problem in mP (that's why I introduced a bool function in my replacement of System library) and introduction of bit logic (which is not part of Pascal) only increased the number of traps one may fall into if one's not careful.

With boolean variables/constants one has to be sure they are never assigned values other than TRUE or FALSE. One should also never mix bit logic with boolean logic in expressions. This does not mean one cannot use bit variables in boolean expressions - for example, bit_var=1 produces boolean result and may be part of boolean expression. But not bit_var may not lead to boolean value. Once in a while people fall into similar trap with TestBit function forgetting that it produces 0 and 1.

The above rambling has a purpose - in opposition to your reservations, Dany, testing only bit 0 of boolean value or expression result (which would seemingly deepen the C-likeness) would be a remedy to some of present problems. First, it would remove complications introduced with bit logic, second, there never would be cases of not FALSE<>TRUE. Furthermore, though it's not a necessary condition, Pascal definition could be easily followed if TRUE and FALSE were defined as 1 & 0. (It would not introduce problems with backward compatibility - at least for code that used the TRUE and FALSE keywords, not direct internal values, which is a bad practice, anyway.)

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: Testing boolean expressions: ambiguity

#3 Post by Dany » 05 Aug 2014 17:32

Thanks Janni.
All you say is true. :D :D

I have one remark though:
You well know that there's actually no boolean type in mP (and never was). When one declares a boolean variable, it's in fact of byte type.
Of course you are right that the boolean is not an actual type of its own, it is indeed represented by a byte, but then again most actual types are only represented as "a number of bytes". Actually all types are based somehow on the "byte" type, but their behaviour differs from it . But: the "boolean" type is defined and can be used (sadly it behaves in the exactly same way as a byte, they are interchangeable).
In the Pascal standard the "boolean" type is not compatible with any other type (you can not convert e.g. a "boolean" to another type or vice versa, even not with a byte - in Delphi the boolean type is also represented by a byte but one can not use them through another), since Pascal is defined as a very strong typed language.
mP however is rather weak typed, there is even an implicite conversion from boolean to e.g. byte (which is not very difficult to do, since boolean is represened by byte). This also means that indeed booleans and bytes are completely interchangeable (while, according to the Pascal standard) they should not.

Anyway
- I did not know (for some reason) that "if xxx then" was "true" if xxx <> 0 :oops:
- "if xxx then" and "if xxx = true then" will yield different results if (xxx > 0 < 255). :shock:
- having this behaviour, mP leaves more and more the "standard" (becomes weaker typed).

Also (positive note -I think- :? ): this shorter notition is now possible:

Code: Select all

I := 100;
while I do
begin
  ...
  dec(I)
end;
in stead of

Code: Select all

I := 100;
while I > 0 do
begin
  ...
  dec(I)
end;
I do not know if it will save some code, but anyway the source code becomes shorter (C like).
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Testing boolean expressions: ambiguity

#4 Post by janni » 05 Aug 2014 23:07

Dany, you cannot at the same time wish mP to be strong typed and shamelessly exploit the fact that it isn't :lol: .
Dany wrote:Of course you are right that the boolean is not an actual type of its own, it is indeed represented by a byte, but then again most actual types are only represented as "a number of bytes". Actually all types are based somehow on the "byte" type, but their behaviour differs from it .
No, one cannot declare basic multi-byte types as combination of type byte :) . Types definitions should not be mixed with memory organisation. Word and integer both take two bytes in memory, but have different properties. It does not matter whether boolean type consist of a byte or a bit in memory, as long as it has specific properties. As boolean type in mP does not have the necessary properties, it's not a real type. It can function as boolean type, but only if a programmer observes the rules, otherwise it's just a byte type.
Anyway
- I did not know (for some reason) that "if xxx then" was "true" if xxx <> 0 :oops:
It should not matter to a programmer - internally, any method may be applied (can you be sure it's not done the same way in Delphi? Oh, it would not allow you to experiment, would it? :wink: ). mE may change the method any time and properly written programs will behave in the same way. Sure, it would be better if mP would not allow boolean variable to be assigned value different than True or False, but that could be costly in processor resources used.
- "if xxx then" and "if xxx = true then" will yield different results if (xxx > 0 < 255). :shock:
Only if one does not observe the rules and assigns to boolean variable values other than TRUE or FALSE. Note that if a double test was used internally, as you seem to prefer, i.e. FALSE was tested against 0 and TRUE against 255 then intermediate values would also lead to strange results - in fact even more confusing as the same value could lead to opposite results depending on logical expression used.

What I propose, i.e testing only one bit of boolean (or, naturally, bit) variable, would get mP closer to Pascal definition as then ord(bool_var) could simply be interpreted as value of this bit. Already, typecasting bit to byte gives 0 or 1 and reversely, casting larger type to bit results in bit zero deciding on the bit value. This means that there wouldn't be a problem with bit and byte logic compatibility. (And all the smart individuals trying to assign out of range value to boolean variable would have tough life claiming that the value is neither true nor false :lol: .)

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: Testing boolean expressions: ambiguity

#5 Post by Dany » 06 Aug 2014 14:42

Hi Janni,
It can function as boolean type, but only if a programmer observes the rules, otherwise it's just a byte type.
You are right of course. For myself however I try to keep the impression that mP has an actual "boolean" type. :D This means I will never (voluntarely) mix byte with boolean usage myself, and it makes me a little bit sad seeing mE doing it in e.g. its examples.

About your proposal (using 1 for true and 0 for false): there would be a problem with "not" then... -- not(1) results in $fe, which is also "true" when using "if xxx then ...". See testcode below.

Code: Select all

  var_ := 1;
  
  if var_ 
  then var_2 := 'true'    // <---- 
  else var_2 := 'false';

  if not(var_)
  then var_2 := 'true'   // <---- not(var_) is also true !!!
  else var_2 := 'false';
:?: :?: I have a feeling we (and others) discussed these issues also a long time ago. It seems to pop up regurarly :shock: . The golden rule is of course when programming: know what happens under the hood...

I hope mE does not change things any more now (now that I think I know how things work again). :D :D
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Testing boolean expressions: ambiguity

#6 Post by janni » 06 Aug 2014 15:41

Dany wrote:About your proposal (using 1 for true and 0 for false): there would be a problem with "not" then... -- not(1) results in $fe, which is also "true" when using "if xxx then ...".
With present implementation it's obviously true. That's why I'd like it changed. If only bit 0 was tested then there'd be no ambiguity (whether using 0 and 1, or 0 and 255 for TRUE and FALSE).
I have a feeling we (and others) discussed these issues also a long time ago. It seems to pop up regurarly :shock: . The golden rule is of course when programming: know what happens under the hood...
You're right, it pops up now and then whenever somebody falls into one of the traps of bit and boolean logic. That's another argument for changes.

Here are some examples of what does not work now but would work if testing was done on bit 0 of boolean variable (whether explicit or internally formed to evaluate logical expression)

Code: Select all

var i:byte;
    boo:boolean;
    bit1:bit;

begin
  bit1:=1;
  asm nop end;
  boo:=bit1;
  if not boo then             // always evaluates true !
   nop;

  bit1:=1;
  boo:=true;
  asm nop end;
  if not (bit1 and boo) then  // always evaluates true !
   nop;
   
  i:=1;
  PORTB.1:=1;
  asm nop end;
  if not PORTB.i then      // always evaluates true!
   nop;
   
  boo:=bit1 and bit2;     // boo is 0 or 1
  if not boo then         // always evaluates true!
   nop;
I hope mE does not change things any more now (now that I think I know how things work again). :D :D
I hope they will :) .

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: Testing boolean expressions: ambiguity

#7 Post by Dany » 06 Aug 2014 18:28

You're right, it pops up now and then whenever somebody falls into one of the traps of bit and boolean logic. That's another argument for changes.
I would not prefer any more changes, because of unforeseen (and foreseen) new problems. There will always be problems as long as a boolean behaves exactly as a byte, and mE will not change that I suppose.
By the way all ones ($ff for a byte) is a very logical choice for 'true', because not(true) gives false ($0) when applying a bitwise not. $1 as "true" is not so easy to "invert" to its logical counterpart: one can not use the bitwise not to get "false": one gets $FE after inversion. So, I have my doubts... :oops:
Here are some examples of what does not work now but would work if testing was done on bit 0 of boolean variable (whether explicit or internally formed to evaluate logical expression)
Ah, bits.
Also bits and booleans should be incompatible (which they are not of course). In standard Pascal (if there were a thing like 'bit') the expressions in your example would cause compiling errors, but not in mP of course. Bits and booleans are (should be) distinct types, a bit can have values 0 and 1, a boolean false and true, they should not be mixable, and trying to do so will always give problems.

So,

Code: Select all

if LatA.0 and (varX > 3) then ...
should not be allowed, while

Code: Select all

if (LatA.0 = 1) and (varX > 3) then ...
should be the way to handle bit/boolean combinations.
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Testing boolean expressions: ambiguity

#8 Post by janni » 06 Aug 2014 22:44

Dany wrote:By the way all ones ($ff for a byte) is a very logical choice for 'true', because not(true) gives false ($0) when applying a bitwise not. $1 as "true" is not so easy to "invert" to its logical counterpart: one can not use the bitwise not to get "false": one gets $FE after inversion. So, I have my doubts... :oops:
I can see that :) . Apparently, having been through tough lessons of mP quirks (as we all :( ), you cannot separate the inner workings of a compiler from the effects visible to a programmer. Once again, programmer should not have to worry how compiler does something. Any solution that breaks the connection is better than worrying whether some expression will work. When programming in Delphi, do you really worry about its inner workings? Does it bother you what is internally used for boolean values and do you worry how they're tested? (If you do :wink: , nowadays Delphi uses 0 and 1 and tests are always performed against 0.)
Ah, bits.
Also bits and booleans should be incompatible (which they are not of course).
They're different types in mP (bit and byte). But types do not have to be identical to make casting possible.
In standard Pascal (if there were a thing like 'bit') the expressions in your example would cause compiling errors, but not in mP of course.
And what makes you think so? Boolean logic is binary logic with 0 called FALSE and 1 called TRUE. There's natural casting of bit to boolean and reverse. There's no reason why logic of single bits should be separated from boolean logic.
Anyway, as bit logic was already introduced in mP, it should work (and it not always does now). If a solution may at the same time make it coexist with boolean logic then why shouldn't it?

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: Testing boolean expressions: ambiguity

#9 Post by Dany » 08 Aug 2014 13:07

Hi Janni, I understand your reasoning.

By the way I did some experiments on your "bit" based examples (tried to convert "bits" into 'booleans") and found the following:

Code: Select all

  bit1 := 1;
  boo := true;
  if not((bit1 = 1) and boo)
  then var_2 := 'true'    // <----  ??????? wrong???? !!!!!!!!!!!!!!!!!!1
  else var_2 := 'false';

  bit1 := 1;
  boo := true;
  if (bit1 = 1) and boo
  then var_2 := 'true'      // <----
  else var_2 := 'false';
I think this is a compiler problem..., both expressions "not((bit1 = 1) and boo)" and "(bit1 = 1) and boo" yield to "true" when tested in the "if" statement... (done with the simulator).
All other of your examples can be made work as wanted by converting a bit to a boolean with e.g. "bit1 = 1" in stead of simply "bit1".
So, I am a little surprised that one of the examples, after conversion, did not work well. I did not look to the assembly code yet...
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

Re: Testing boolean expressions: ambiguity

#10 Post by janni » 08 Aug 2014 16:15

Yeah, I've forgotten about this outcome of bit logic introduction :( . While typecast from mixed logic expression to boolean may even be performed properly in assignments, like

Code: Select all

boo := not((bit1 = 1) and boo);
in conditionals compiler tries to use bit logic simultaneously with boolean logic with predictably bad results.

I stopped long ago using complex expressions in conditionals and use my bool function whenever in doubt about mixing bits with booleans. Would like to trust mP again, but that requires changes in testing logical expressions.

User avatar
dejan.odabasic
mikroElektronika team
Posts: 2649
Joined: 30 Apr 2012 14:20

Re: Testing boolean expressions: ambiguity

#11 Post by dejan.odabasic » 11 Aug 2014 15:40

Hello,

Thank you Dany for posting this code snippet.
I have presented this issue to our developers and they will solve it as soon as possible.

Best regards.

Post Reply

Return to “mikroPascal PRO for PIC Beta Testing”