Browse Source

* fixed support for macpas & and | operators: they only work on booleans
now, and always perform short circuit boolean evaluation (also in {$b+})

git-svn-id: trunk@3745 -

Jonas Maebe 19 years ago
parent
commit
03302dc7c4

+ 2 - 0
.gitattributes

@@ -5757,6 +5757,7 @@ tests/test/tintfdef.pp svneol=native#text/plain
 tests/test/tintuint.pp svneol=native#text/plain
 tests/test/tlibrary1.pp svneol=native#text/plain
 tests/test/tlibrary2.pp svneol=native#text/plain
+tests/test/tmacbool.pp svneol=native#text/plain
 tests/test/tmacfunret.pp svneol=native#text/plain
 tests/test/tmaclocalprocparam.pp svneol=native#text/plain
 tests/test/tmacnonlocalexit.pp svneol=native#text/plain
@@ -5767,6 +5768,7 @@ tests/test/tmacpas3.pp svneol=native#text/plain
 tests/test/tmacpas4.pp svneol=native#text/plain
 tests/test/tmacprocvar.pp svneol=native#text/plain
 tests/test/tmath1.pp svneol=native#text/plain
+tests/test/tmcbool2.pp svneol=native#text/plain
 tests/test/tmmx1.pp svneol=native#text/plain
 tests/test/tmove.pp svneol=native#text/plain
 tests/test/tmt1.pp svneol=native#text/plain

+ 22 - 3
compiler/nadd.pas

@@ -812,8 +812,25 @@ implementation
                  exit;
                end;
 
+              { set for & and | operations in macpas mode: they only work on }
+              { booleans, and always short circuit evaluation                }
+              if (nf_short_bool in flags) then
+                begin
+                  if not is_boolean(ld) then
+                    begin
+                      inserttypeconv(left,booltype);
+                      ld := left.resulttype.def;
+                    end;
+                  if not is_boolean(rd) then
+                    begin
+                      inserttypeconv(right,booltype);
+                      rd := right.resulttype.def;
+                    end;
+                end;
+
              { 2 booleans? Make them equal to the largest boolean }
-             if is_boolean(ld) and is_boolean(rd) then
+             if (is_boolean(ld) and is_boolean(rd)) or
+                (nf_short_bool in flags) then
               begin
                 if torddef(left.resulttype.def).size>torddef(right.resulttype.def).size then
                  begin
@@ -840,7 +857,8 @@ implementation
                   unequaln,
                   equaln:
                     begin
-                      if not(cs_full_boolean_eval in aktlocalswitches) then
+                      if not(cs_full_boolean_eval in aktlocalswitches) or
+                         (nf_short_bool in flags) then
                        begin
                          { Remove any compares with constants }
                          if (left.nodetype=ordconstn) then
@@ -2079,7 +2097,8 @@ implementation
            { 2 booleans ? }
              if is_boolean(ld) and is_boolean(rd) then
               begin
-                if not(cs_full_boolean_eval in aktlocalswitches) and
+                if (not(cs_full_boolean_eval in aktlocalswitches) or
+                    (nf_short_bool in flags)) and
                    (nodetype in [andn,orn]) then
                  begin
                    expectloc:=LOC_JUMP;

+ 2 - 1
compiler/ncgadd.pas

@@ -379,7 +379,8 @@ interface
         { And,Or will only evaluate from left to right only the
           needed nodes unless full boolean evaluation is enabled }
         if (nodetype in [orn,andn]) and
-           not(cs_full_boolean_eval in aktlocalswitches) then
+           (not(cs_full_boolean_eval in aktlocalswitches) or
+            (nf_short_bool in flags)) then
           begin
             location_reset(location,LOC_JUMP,OS_NO);
             case nodetype of

+ 1 - 0
compiler/node.pas

@@ -220,6 +220,7 @@ interface
          { taddnode }
          nf_is_currency,
          nf_has_pointerdiv,
+         nf_short_bool,
 
          { tassignmentnode }
          nf_concat_string,

+ 10 - 2
compiler/pexpr.pas

@@ -2567,10 +2567,18 @@ implementation
                  p1:=cisnode.create(p1,p2);
                _OP_OR,
                _PIPE {macpas only} :
-                 p1:=caddnode.create(orn,p1,p2);
+                 begin
+                   p1:=caddnode.create(orn,p1,p2);
+                   if (oldt = _PIPE) then
+                     include(p1.flags,nf_short_bool);
+                 end;
                _OP_AND,
                _AMPERSAND {macpas only} :
-                 p1:=caddnode.create(andn,p1,p2);
+                 begin
+                   p1:=caddnode.create(andn,p1,p2);
+                   if (oldt = _AMPERSAND) then
+                     include(p1.flags,nf_short_bool);
+                 end;
                _OP_DIV :
                  p1:=cmoddivnode.create(divn,p1,p2);
                _OP_NOT :

+ 2 - 1
compiler/powerpc/nppcadd.pas

@@ -261,7 +261,8 @@ interface
         else
            cgsize:=OS_32;
 
-        if (cs_full_boolean_eval in aktlocalswitches) or
+        if ((cs_full_boolean_eval in aktlocalswitches) and
+            not(nf_short_bool in flags)) or
            (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
           begin
             if left.nodetype in [ordconstn,realconstn] then

+ 2 - 1
compiler/powerpc64/nppcadd.pas

@@ -254,7 +254,8 @@ begin
   else
     cgsize := OS_32;
 
-  if (cs_full_boolean_eval in aktlocalswitches) or
+  if ((cs_full_boolean_eval in aktlocalswitches) and
+      not(nf_short_bool in flags)) or
     (nodetype in [unequaln, ltn, lten, gtn, gten, equaln, xorn]) then
   begin
     if left.nodetype in [ordconstn, realconstn] then

+ 1 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 
 const
-  CurrentPPUVersion=57;
+  CurrentPPUVersion=58;
 
 { buffer sizes }
   maxentrysize = 1024;

+ 189 - 0
tests/test/tmacbool.pp

@@ -0,0 +1,189 @@
+program macbool;
+
+{$mode macpas}
+
+{ checks boolean evaluation in macpas mode }
+
+var
+  ftruecalled, ffalsecalled: boolean;
+
+function ftrue: boolean;
+begin
+  ftruecalled := true;
+  ftrue := true;
+end;
+
+function ffalse: boolean;
+begin
+  ffalsecalled := true;
+  ffalse := false;
+end;
+
+
+begin
+  { OR and |, short circuit }
+{$b-}
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ftrue or ffalse) then
+    begin
+      if not(ftruecalled) then
+        halt(1);
+      if ffalsecalled then
+        halt(2);
+    end
+  else
+    halt(128);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if not(ffalse or ftrue) then
+    halt(3);
+  if not(ffalsecalled) then
+    halt(4);
+  if not(ftruecalled) then
+    halt(5);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ftrue | ffalse) then
+    begin
+      if not(ftruecalled) then
+        halt(6);
+      if ffalsecalled then
+        halt(7);
+    end
+  else
+    halt(129);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if not(ffalse | ftrue) then
+    halt(8);
+  if not(ffalsecalled) then
+    halt(9);
+  if not(ftruecalled) then
+    halt(10);
+
+
+  { OR and |, full evaluation }
+{$b+}
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ftrue or ffalse) then
+    begin
+      if not(ftruecalled) then
+        halt(11);
+      if not(ffalsecalled) then
+        halt(12);
+    end
+  else
+    halt(130);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if not(ffalse or ftrue) then
+    halt(13);
+  if not(ffalsecalled) then
+    halt(14);
+  if not(ftruecalled) then
+    halt(15);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ftrue | ffalse) then
+    begin
+      if not(ftruecalled) then
+        halt(16);
+      if ffalsecalled then
+        halt(17);
+    end
+  else
+    halt(131);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if not(ffalse | ftrue) then
+    halt(18);
+  if not(ffalsecalled) then
+    halt(19);
+  if not(ftruecalled) then
+    halt(20);
+
+  { AND and &, short circuit }
+{$b-}
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ftrue and ffalse) then
+    halt(21);
+   if not(ftruecalled) then
+     halt(211);
+   if not(ffalsecalled) then
+     halt(22);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ffalse and ftrue) then
+    halt(23);
+  if not(ffalsecalled) then
+    halt(24);
+  if (ftruecalled) then
+    halt(25);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ftrue & ffalse) then
+    halt(206);
+  if not(ftruecalled) then
+    halt(26);
+  if not(ffalsecalled) then
+    halt(27);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ffalse & ftrue) then
+    halt(28);
+  if not(ffalsecalled) then
+    halt(29);
+  if (ftruecalled) then
+    halt(30);
+
+
+  { AND and &, full evaluation }
+{$b+}
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ftrue and ffalse) then
+    halt(31);
+   if not(ftruecalled) then
+     halt(111);
+   if not(ffalsecalled) then
+     halt(32);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ffalse and ftrue) then
+    halt(33);
+  if not(ffalsecalled) then
+    halt(34);
+  if not(ftruecalled) then
+    halt(35);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ftrue & ffalse) then
+    halt(133);
+  if not(ftruecalled) then
+    halt(36);
+  if not(ffalsecalled) then
+    halt(37);
+
+  ffalsecalled := false;
+  ftruecalled := false;
+  if (ffalse & ftrue) then
+    halt(38);
+  if not(ffalsecalled) then
+    halt(39);
+  if (ftruecalled) then
+    halt(40);
+end.

+ 10 - 0
tests/test/tmcbool2.pp

@@ -0,0 +1,10 @@
+{ %fail}
+program mcbool2;
+
+{$mode macpas}
+
+var
+  a, b: longint;
+begin
+  a := a & b;
+end.