Operator precedence curiosity

Part of the enjoyable challenge of learning Oxygene is trying to discover what is more C# (.Net/CLI) like or Object-Pascal like. Oxygene appears to have inherited quite a bit from .Net (understandably) such as integer division (10/3 = 3) vs returning a real number as Delphi/Lazarus FPC would do (10/3 = 3.333). Then I came upon the topic of operator precedence in the Oxygene online manual:

I read something similar as well in Marco Cantù’s book Essential Pascal :

Contrary to most other programming languages, the and and or operators have higher precedence than comparison ones. So if you write:

a < b and c < d

the compiler will do the and operation first, resulting in a compiler error. So you should enclose each of the < expressions in parentheses:

(a < b) and (c < d)

So I decided to run a quick test case in Delphi, Lazarus FPC, PascalABC.Net and Oxygene and all resulted in compiler errors except for … Oxygene. :upside_down_face:

namespace Oxy_precedence;

interface

uses
  System.Linq;

type
  Program = class
  public
    class method Main(args: array of String): Int32;
  end;

implementation

class method Program.Main(args: array of String): Int32;
begin
  var a := 10;
  var b := 12;
  var c := 5;
  var d := 8;
  
  // returns 'The magic happens here.'
  if (a < b) and (c < d) then 
    writeLn('The magic happens here.') 
  else
    writeLn('The magic is not here.');
  
  // returns 'The magic is not here.'
  if a < b and c < d then 
    writeLn('The magic happens here.') 
  else
    writeLn('The magic is not here.');
  
end;

end.

I was quite surprised that ’ a < b and c < d’ made it through Elements Compiler although it returned a dissimilar result than C#(Hydrogene). :nerd_face:

Cheers,

Gary

Tests done using Fire .2667

if a < b and c < d then

evaluates to

if a < (b and c) < d then

and this is what we call a Double Boolean Comparison, see Arithmetic & Logical Expressions. Basically it checks if the middle operand against there first and the last, a example would be:

if 12 < age < 20 then 
  writeLn("teenager");
1 Like

Very cool, thanks Marc. I wasn’t quite sure how (b and c) would be evaluated, given that other cousin Pascal languages appear to disallow it in this situation - but it appears that Oxygene does allow a bitwise AND operation to be performed in this case. :nerd_face:

1 Like

I think Delphi & Co would do the same. what they don’t so is the (“a < X < d”), which causes the actual error they emit. the (“b and c”) they will do fine.

That’s pretty much my findings as well.

Delphi (et al) will not allow the following statements (the bitwise AND not being allowed), but is allowed in Oxygene.

if a < b and c < d then
if a < (b and c) < d then

But the following will compile in all Pascal-derived languages I’ve worked with, the bitwise AND being performed.

writeln(b and c);
1 Like

yeah. what happens is

if a < (b and c) < d then

if a < X < d then

if Y < d then // Y is a boolean, and “bool < int” fails.

1 Like

This is the test I ran. It’s mostly academic in nature, but I included it for completeness. :nerd_face:

namespace OxyPrecedenceNetC1;

type
  Program = class
  public


    class method Main(args: array of String): Int32;
    begin
      var a := 25;
      var b := 12;
      var c := 3;
      var d := 5;
      var e := 5;

(* Bitwise AND operations with integer value returned *)

      writeLn(a and b); //returns '8'
      writeLn(d and e); //returns '5'
      writeLn(a and a); //returns '10
      writeLn(b and c); //returns '0'
      writeLn(c and d); // returns '1'
      writeLn(b and d); // returns '4'

(* Bitwise AND operations allowed by Oxygene in the following *)
      if a < (b and c) then
        writeLn('a < (b and c)')  // 10 < (0) -> False
      else
        writeLn('no'); // returns 'no'

      if (b and c) < d then  // (0) < 5 - > True
        writeLn('True')
      else
        writeLn('False');

      if (d and e) = e  then  // (5) = 5 -> True
        writeLn('True')
      else
        writeLn('False');

      if (d and e) < e then // (5) < 5 - > False
        writeLn('True')
      else
        writeLn('False');

      if (d or e) = e then  // (5) = 5 - > True
        writeLn('True')
      else
        writeLn('False');

      if (c and d) < (b and d) then // (1) < (4) - > True
        writeLn('True')
      else
        writeLn('False');

      if (b and d) < (c and d) then // (4) < (1) - > False
        writeLn('True')
      else
        writeLn('False');

      readLn
    end;
  end;
end.

1 Like