Recent

Author Topic: and operator order  (Read 1491 times)

scribly

  • Jr. Member
  • **
  • Posts: 81
and operator order
« on: November 11, 2024, 02:16:39 pm »
Hi, a long time ago I programmed in Delphi and there the AND operator would get evaluated in a willy nilly order. 

E.g:
Code: [Select]
var x: TSomeClass; //(it's initialized when used)
function getObjectX(var _x: TSomeClass): boolean;
  _x:=x;
  return true   
end
...
if getObjectX(x) and x.dosomethingthatreturnsaboolean() then ... 
this would randomly crash as x would sometimes be uninitialized

Is this still the case in modern freepascal? (I still make sure my code splits this up into separate lines but wondering if I still have to)

Zvoni

  • Hero Member
  • *****
  • Posts: 2754
Re: and operator order
« Reply #1 on: November 11, 2024, 02:53:40 pm »
Hi, a long time ago I programmed in Delphi and there the AND operator would get evaluated in a willy nilly order. 

E.g:
Code: [Select]
var x: TSomeClass; //(it's initialized when used)
function getObjectX(var _x: TSomeClass): boolean;
  _x:=x;
  return true   
end
...
if getObjectX(x) and x.dosomethingthatreturnsaboolean() then ... 
this would randomly crash as x would sometimes be uninitialized

Is this still the case in modern freepascal? (I still make sure my code splits this up into separate lines but wondering if I still have to)
If GetObjectx(x) returns False, the second part of the "and" DOES NOT get evaluated.
For Debugging-purposes i'd rather use
Code: Pascal  [Select][+][-]
  1. var a,b:Boolean;
  2. ....
  3. a:=GetObjectx(x);
  4. If a Then b:=x.dosomethingthatreturnsaboolean();  
  5.  

This way i'm protecting myself in case a is False
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Warfley

  • Hero Member
  • *****
  • Posts: 1763
Re: and operator order
« Reply #2 on: November 11, 2024, 05:45:27 pm »
There is the $BoolEval which does configure the behavior of boolean operators. By default it is disabled, resulting in so called short circuit evalutation. So:
Code: Pascal  [Select][+][-]
  1. if A and B then
  2.   ...
is basically translated to
Code: Pascal  [Select][+][-]
  1. if A then
  2.   if B then
  3.     ...
So if A is false, the evaluation of B never starts.

If you manually enable it, e.g. With {$B+}, then all the expressions will be evaluated. Then the order of evaluation (associativity as it is called for operators) is, as with any operators in Pascal undefined.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5764
  • Compiler Developer
Re: and operator order
« Reply #3 on: November 11, 2024, 07:29:19 pm »
Hi, a long time ago I programmed in Delphi and there the AND operator would get evaluated in a willy nilly order.

And what Warfley said also applies to Delphi, even “a long time ago”.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8039
Re: and operator order
« Reply #4 on: November 11, 2024, 08:26:07 pm »
Hi, a long time ago I programmed in Delphi and there the AND operator would get evaluated in a willy nilly order.

And what Warfley said also applies to Delphi, even “a long time ago”.

And to Turbo Pascal, and even unto ALGOL-60.

Boolean expressions in conditional statements (if, while, until) are fundamentally different from arithmetic expressions. In effect, they're evaluated into nested if-then-else statements rather than being evaluated in a single calculation.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 16199
  • Censorship about opinions does not belong here.
Re: and operator order
« Reply #5 on: November 12, 2024, 01:38:56 pm »
That depends on (sorry C style ) & or &&, for which Pascal has the same notation.
I removed an example, though, but will write a better one.
(a and b) and (c and d) is not always the same as a and b and c and d.
« Last Edit: November 12, 2024, 01:43:16 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

Warfley

  • Hero Member
  • *****
  • Posts: 1763
Re: and operator order
« Reply #6 on: November 12, 2024, 09:03:43 pm »
Maybe we should adopt the c style notation to also have this differentation:
Code: Pascal  [Select][+][-]
  1. // Short circuit
  2. if A andand B then
  3. // Bitwise/full eval
  4. if A and B then

Kays

  • Hero Member
  • *****
  • Posts: 613
  • Whasup!?
    • KaiBurghardt.de
Re: and operator order
« Reply #7 on: November 13, 2024, 01:40:36 pm »
Maybe we should adopt the c style notation to also have this [differentiation]:
ISO standard 10206 “Extended Pascal” defines the operator and_then that has the short‑circuit evaluation semantics. As of today FPC does not support it, though.
Quote from: ISO 10206:1990 § 6.8.3.1 General
[…] Except for the and_then and or_else operators, the order of evaluation of the operands of a dyadic operator shall be implementation‑dependent.

NOTE — This means, for example, that the operands may be evaluated in textual order, or in reverse order, or in parallel, or they may not both be evaluated.
Quote from: ISO 10206:1990 § 6.8.3.3 Boolean operators
[…] In a term of the form A and_then B, the right operand shall be evaluated if and only if the left operand denotes the value true; […] In a simple‑expression of the form A or_else B, the right operand shall be evaluated if and only if the left operand denotes the value false; […]
Yours Sincerely
Kai Burghardt

MarkMLl

  • Hero Member
  • *****
  • Posts: 8039
Re: and operator order
« Reply #8 on: November 13, 2024, 01:59:01 pm »
Quote
Maybe we should adopt the c style notation to also have this [differentiation]:
ISO standard 10206 “Extended Pascal” defines the operator and_then that has the short‑circuit evaluation semantics. As of today FPC does not support it, though.

The short-circuiting is a can of worms though, since it precludes all parallelisation of the subexpressions unless they can be identified by the compiler (or by explicit hints) as having no side-effects.

MarkMLl
« Last Edit: November 13, 2024, 05:29:07 pm by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Thaddy

  • Hero Member
  • *****
  • Posts: 16199
  • Censorship about opinions does not belong here.
Re: and operator order
« Reply #9 on: November 13, 2024, 04:01:32 pm »
short-circuiting has only one, 1, issue:time: scbe allows timing attacks. Jonas fixed a bug relating to that, that I reported and demo'd.
If I smell bad code it usually is bad code and that includes my own code.

Warfley

  • Hero Member
  • *****
  • Posts: 1763
Re: and operator order
« Reply #10 on: November 13, 2024, 09:24:10 pm »
Well they have more than one issue, they introduce branching, which can be quite slow. This is my goto function for UTF-8 char handling:
Code: Pascal  [Select][+][-]
  1. function ValidFirstUTF8Char(FirstChar: Char): Boolean; inline;
  2. begin
  3.   Result := ((ord(FirstChar) And %10000000) = %00000000)  // One char sequence
  4.          Or ((ord(FirstChar) And %11100000) = %11000000)  // Two char sequence
  5.          Or ((ord(FirstChar) And %11110000) = %11100000)  // Three char sequence
  6.          Or ((ord(FirstChar) And %11111000) = %11110000); // Four char sequence
  7. end;

Let's benchmark this function with short cuircut vs without:
Code: Pascal  [Select][+][-]
  1. uses
  2.   sysutils;
  3.  
  4. function ValidFirstUTF8CharSC(FirstChar: Char): Boolean; inline;
  5. begin
  6.   Result := ((ord(FirstChar) And %10000000) = %00000000)  // One char sequence
  7.          Or ((ord(FirstChar) And %11100000) = %11000000)  // Two char sequence
  8.          Or ((ord(FirstChar) And %11110000) = %11100000)  // Three char sequence
  9.          Or ((ord(FirstChar) And %11111000) = %11110000); // Four char sequence
  10. end;
  11.  
  12. function ValidFirstUTF8Char(FirstChar: Char): Boolean; inline;
  13. begin
  14.   {$Push}
  15.   {$B+} // Disable short circuit to avoid jump instructions
  16.   Result := ((ord(FirstChar) And %10000000) = %00000000)  // One char sequence
  17.          Or ((ord(FirstChar) And %11100000) = %11000000)  // Two char sequence
  18.          Or ((ord(FirstChar) And %11110000) = %11100000)  // Three char sequence
  19.          Or ((ord(FirstChar) And %11111000) = %11110000); // Four char sequence
  20.   {$Pop}
  21. end;
  22.  
  23. const Iter=10000000;
  24. var
  25.   i: Integer;
  26.   start:QWord;
  27. begin
  28.   start:=GetTickCount64;
  29.   for i:=1 to iter do
  30.     ValidFirstUTF8CharSC(chr(random(256)));
  31.   WriteLn('Short Circuit: ', GetTickCount64-start);
  32.   start:=GetTickCount64;
  33.   for i:=1 to iter do
  34.     ValidFirstUTF8Char(chr(random(256)));
  35.   WriteLn('Long Circuit: ', GetTickCount64-start);
  36. end.
Results (compiled on O4):
Code: Pascal  [Select][+][-]
  1. Short Circuit: 119
  2. Long Circuit: 69
Short circuit is nearly twice as slow as "long cuircuit". Short Circuit can provide massive benefits if the conditions are complex to evaluate. Like anything involving memory accesses, function calls, floating point operations, etc. but if you have very simple operations, the branching instructions take more time than skipping part of the branches saves.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5764
  • Compiler Developer
Re: and operator order
« Reply #11 on: November 14, 2024, 09:48:05 pm »
Quote
Maybe we should adopt the c style notation to also have this [differentiation]:
ISO standard 10206 “Extended Pascal” defines the operator and_then that has the short‑circuit evaluation semantics. As of today FPC does not support it, though.

The short-circuiting is a can of worms though, since it precludes all parallelisation of the subexpressions unless they can be identified by the compiler (or by explicit hints) as having no side-effects.

But it also allows operations like scribly showed in their initial post. The use there in my opinion is more important than parallelisation issues. And if needed someone can still disable that per condition.

 

TinyPortal © 2005-2018