[fpc-devel] Fwd: While - Otherwise Statement

MohsenTi mohsen.timar at gmail.com
Sun Oct 11 18:55:55 CEST 2015


I create 2 test files depends on testsuite readme file and make testsuite
with make full command and set TEST_FPC variable to fpc ppcx64 compiler.

for-otherwise and while-otherwise diff file and test files attached to
email.

test result :

Total = 6906 (75:6831)
Total number of compilations = 4264 (60:4204)
Successfully compiled = 3147
Successfully failed = 1057
Compilation failures = 55
Compilation that did not fail while they should = 5
Total number of runs = 2642 (15:2627)
Successful runs = 2627
Failed runs = 15
Number units compiled = 135
Number program that should not be run = 367
Number of skipped tests = 404
Number of skipped graph tests = 10
Number of skipped interactive tests = 31
Number of skipped known bug tests = 6
Number of skipped tests for other versions = 4
Number of skipped tests for other cpus = 190
Number of skipped tests for other targets = 163

I checked failed ones but it seems they are not related to my changes.
What you think?

thanks a lot


On Sun, Oct 11, 2015 at 6:44 PM, Sven Barth <pascaldragon at googlemail.com>
wrote:

> Am 11.10.2015 15:56 schrieb "MohsenTi" <mohsen.timar at gmail.com>:
> >
> > Hi everybody
> >
> > I add new feature to FPC compiler to simplify programming.
> > this is While - Otherwise working like While - Else in python and has
> backwards compatibility.
>
> Nice idea with the otherwise. I first thought that this would break
> case-statements that use otherwise instead of else, but then I remembered
> that the case-label-blocks can and IMHO should be terminated by ; anyway.
> At least problems can be easily circumvented.
>
> I don't know whether we'll add it to trunk, but I'll at least take a look
> at your code to give you feedback.
>
> Oh, and please provide simple tests for your feature that could be added
> to our testsuite (in tests/test or tests/tbs) in case we decide to
> incorporate it.
> Speaking of which: did you run the testsuite and compared the results to a
> run without modifications?
> (If you need help with running the testsuite or interpreting the results,
> please ask, I have yet to write a wiki page for that...)
>
> Regards,
> Sven
>
> _______________________________________________
> fpc-devel maillist  -  fpc-devel at lists.freepascal.org
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20151011/40c11fae/attachment.html>
-------------- next part --------------
Index: ncgflw.pas
===================================================================
--- ncgflw.pas	(revision 32016)
+++ ncgflw.pas	(working copy)
@@ -132,7 +132,7 @@
 
     procedure tcgwhilerepeatnode.pass_generate_code;
       var
-         lcont,lbreak,lloop,
+         lcont,lbreak,lloop,lotherwise,
          oldclabel,oldblabel : tasmlabel;
          truelabel,falselabel : tasmlabel;
          oldflowcontrol : tflowcontrol;
@@ -143,6 +143,7 @@
          current_asmdata.getjumplabel(lloop);
          current_asmdata.getjumplabel(lcont);
          current_asmdata.getjumplabel(lbreak);
+         current_asmdata.getjumplabel(lotherwise);
          { arrange continue and breaklabels: }
          oldflowcontrol:=flowcontrol;
          oldclabel:=current_procinfo.CurrContinueLabel;
@@ -184,17 +185,21 @@
          hlcg.a_label(current_asmdata.CurrAsmList,lcont);
          if lnf_checknegate in loopflags then
            begin
-             truelabel:=lbreak;
+             truelabel:=lotherwise;
              falselabel:=lloop;
            end
          else
            begin
              truelabel:=lloop;
-             falselabel:=lbreak;
+             falselabel:=lotherwise;
            end;
          secondpass(left);
+         hlcg.maketojumpboollabels(current_asmdata.CurrAsmList,left,truelabel,falselabel);
+         hlcg.a_label(current_asmdata.CurrAsmList,lotherwise);
+         if (Assigned(t1)) then begin
+           secondpass(t1);
+         end;
 
-         hlcg.maketojumpboollabels(current_asmdata.CurrAsmList,left,truelabel,falselabel);
          hlcg.a_label(current_asmdata.CurrAsmList,lbreak);
 
          sync_regvars(false);
@@ -413,7 +418,7 @@
 
     procedure tcgfornode.pass_generate_code;
       var
-         l3,oldclabel,oldblabel : tasmlabel;
+         l3,lotherwise,oldclabel,oldblabel : tasmlabel;
          temptovalue : boolean;
          hop : topcg;
          hcond : topcmp;
@@ -430,7 +435,7 @@
          current_asmdata.getjumplabel(current_procinfo.CurrContinueLabel);
          current_asmdata.getjumplabel(current_procinfo.CurrBreakLabel);
          current_asmdata.getjumplabel(l3);
-
+         current_asmdata.getjumplabel(lotherwise);
          { only calculate reference }
          opsize := def_cgsize(left.resultdef);
          count_var_is_signed:=is_signed(left.resultdef);
@@ -794,6 +799,16 @@
                tcgint(cmp_const.svalue),left.location,l3);
            end;
 
+           hlcg.a_label(current_asmdata.CurrAsmList,lotherwise);
+
+           if (Assigned(e)) then
+           begin
+             oldexecutionweight:=cg.executionweight;
+             cg.executionweight:=cg.executionweight*8;
+             secondpass(e);
+             cg.executionweight:=oldexecutionweight;
+           end;
+
          { this is the break label: }
          hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel);
 
Index: nflw.pas
===================================================================
--- nflw.pas	(revision 32016)
+++ nflw.pas	(working copy)
@@ -71,8 +71,11 @@
           function docompare(p: tnode): boolean; override;
        end;
 
+       { twhilerepeatnode }
+
        twhilerepeatnode = class(tloopnode)
           constructor create(l,r:Tnode;tab,cn:boolean);virtual;reintroduce;
+          constructor create(l,r,e:Tnode;tab,cn:boolean);virtual;reintroduce;
           function pass_typecheck:tnode;override;
           function pass_1 : tnode;override;
 {$ifdef state_tracking}
@@ -92,6 +95,8 @@
        end;
        tifnodeclass = class of tifnode;
 
+       { tfornode }
+
        tfornode = class(tloopnode)
           { if count isn divisable by unrolls then
             the for loop must jump to this label to get the correct
@@ -99,8 +104,10 @@
           entrylabel,
           { this is a dummy node used by the dfa to store life information for the loop iteration }
           loopiteration : tnode;
+          e:TNode;
           loopvar_notid:cardinal;
-          constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;reintroduce;
+          //constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;reintroduce;
+          constructor create(l,r,_t1,_t2,_e : tnode;back : boolean);virtual;reintroduce;
           function wrap_to_value:tnode;
           function pass_typecheck:tnode;override;
           function pass_1 : tnode;override;
@@ -258,10 +265,11 @@
 
     function create_type_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
       begin
+      //Todo: Checking otherwise for for-in
         result:=cfornode.create(hloopvar,
           cinlinenode.create(in_low_x,false,expr.getcopy),
           cinlinenode.create(in_high_x,false,expr.getcopy),
-          hloopbody,
+          hloopbody,nil,
           false);
       end;
 
@@ -528,10 +536,11 @@
         { add the actual statement to the loop }
         addstatement(loopbodystatement,hloopbody);
 
+        //Todo: Checking otherwise for for-in string
         forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
           genintconstnode(1),
           cinlinenode.create(in_length_x,false,ctemprefnode.create(stringvar)),
-          loopbody,
+          loopbody,nil,
           false);
 
         addstatement(loopstatement,forloopnode);
@@ -641,11 +650,11 @@
 
         { add the actual statement to the loop }
         addstatement(loopbodystatement,hloopbody);
-
+        //Todo: Checking otherwise for for-in array
         forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
           lowbound,
           highbound,
-          loopbody,
+          loopbody,nil,
           false);
 
         addstatement(loopstatement,forloopnode);
@@ -706,11 +715,11 @@
         addstatement(loopbodystatement,cassignmentnode.create(hloopvar,ctemprefnode.create(loopvar)));
         { add the actual statement to the loop }
         addstatement(loopbodystatement,hloopbody);
-
+        //Todo: Checking otherwise for for-in set
         forloopnode:=cfornode.create(ctemprefnode.create(loopvar),
           cinlinenode.create(in_low_x,false,ctemprefnode.create(setvar)),
           cinlinenode.create(in_high_x,false,ctemprefnode.create(setvar)),
-          loopbody,
+          loopbody,nil,
           false);
 
         addstatement(loopstatement,forloopnode);
@@ -1046,7 +1055,7 @@
                                TWHILEREPEATNODE
 *****************************************************************************}
 
-    constructor Twhilerepeatnode.create(l,r:Tnode;tab,cn:boolean);
+        constructor twhilerepeatnode.create(l, r: Tnode; tab, cn: boolean);
       begin
           inherited create(whilerepeatn,l,r,nil,nil);
           if tab then
@@ -1055,6 +1064,15 @@
               include(loopflags,lnf_checknegate);
       end;
 
+    constructor twhilerepeatnode.create(l, r, e: Tnode; tab, cn: boolean);
+    begin
+            inherited create(whilerepeatn,l,r,e,nil);
+          if tab then
+              include(loopflags, lnf_testatbegin);
+          if cn then
+              include(loopflags,lnf_checknegate);
+    end;
+
     function twhilerepeatnode.pass_typecheck:tnode;
       var
          t:Tunarynode;
@@ -1432,14 +1450,24 @@
                               TFORNODE
 *****************************************************************************}
 
-    constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
+    //constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
+    //
+    //  begin
+    //     inherited create(forn,l,r,_t1,_t2);
+    //     if back then
+    //       include(loopflags,lnf_backward);
+    //     include(loopflags,lnf_testatbegin);
+    //     e:=nil;
+    //  end;
 
-      begin
-         inherited create(forn,l,r,_t1,_t2);
+    constructor tfornode.create(l, r, _t1, _t2, _e: tnode; back: boolean);
+    begin
+       inherited create(forn,l,r,_t1,_t2);
          if back then
            include(loopflags,lnf_backward);
          include(loopflags,lnf_testatbegin);
-      end;
+         e:=_e;
+    end;
 
     function tfornode.simplify(forinline : boolean) : tnode;
       begin
@@ -1487,8 +1515,8 @@
           ctemprefnode.create(temp),
           t1));
         { create a new for node, it is cheaper than cloning entire loop body }
-        addstatement(statements,cfornode.create(
-          left,right,ctemprefnode.create(temp),t2,lnf_backward in loopflags));
+          addstatement(statements,cfornode.create(
+          left,right,ctemprefnode.create(temp),t2,e,lnf_backward in loopflags));
         addstatement(statements,ctempdeletenode.create(temp));
         { all child nodes are reused }
         left:=nil;
@@ -1495,6 +1523,7 @@
         right:=nil;
         t1:=nil;
         t2:=nil;
+        e:=nil;
       end;
 
 
@@ -1540,6 +1569,8 @@
 
          if assigned(t2) then
            typecheckpass(t2);
+         if Assigned(e) then
+           typecheckpass(e);
       end;
 
 
@@ -1557,6 +1588,12 @@
          if codegenerror then
            exit;
 
+         if (Assigned(e)) then
+         begin
+           firstpass(e);
+           if codegenerror then exit;
+         end;
+
          { 'to' value must be evaluated once before loop, so its possible modifications
            inside loop body do not affect the number of iterations (see webtbs/tw8883). }
          if not (t1.nodetype in [ordconstn,temprefn]) then
Index: ninl.pas
===================================================================
--- ninl.pas	(revision 32016)
+++ ninl.pas	(working copy)
@@ -4301,7 +4301,7 @@
            ctemprefnode.create(loopvar),
            cinlinenode.create(in_low_x,false,packednode.getcopy),
            cinlinenode.create(in_high_x,false,packednode.getcopy),
-           loopbody,
+           loopbody,nil,
            false);
          addstatement(loopstatement,tempnode);
          { free the loop counter }
Index: optloop.pas
===================================================================
--- optloop.pas	(revision 32016)
+++ optloop.pas	(working copy)
@@ -472,7 +472,7 @@
             { create a new for node, the old one will be released by the compiler }
             with tfornode(node) do
               begin
-                fornode:=cfornode.create(left,right,t1,t2,lnf_backward in loopflags);
+                fornode:=cfornode.create(left,right,t1,t2,e,lnf_backward in loopflags);
                 left:=nil;
                 right:=nil;
                 t1:=nil;
Index: optutils.pas
===================================================================
--- optutils.pas	(revision 32016)
+++ optutils.pas	(working copy)
@@ -205,6 +205,7 @@
                 tfornode(p).loopiteration:=cnothingnode.create;
 
                 DoSet(tfornode(p).t2,tfornode(p).loopiteration);
+                
                 p.successor:=succ;
                 Breakstack.Delete(Breakstack.Count-1);
                 Continuestack.Delete(Continuestack.Count-1);
@@ -226,7 +227,7 @@
                 result:=p;
                 { the successor of the last node of the while/repeat body is the while node itself }
                 DoSet(twhilerepeatnode(p).right,p);
-
+                
                 p.successor:=succ;
 
                 { special case: we do not do a dyn. dfa, but we should handle endless loops }
Index: pstatmnt.pas
===================================================================
--- pstatmnt.pas	(revision 32016)
+++ pstatmnt.pas	(working copy)
@@ -328,7 +328,7 @@
     function while_statement : tnode;
 
       var
-         p_e,p_a : tnode;
+         p_e,p_a,else_a : tnode;
 
       begin
          consume(_WHILE);
@@ -335,7 +335,11 @@
          p_e:=comp_expr(true,false);
          consume(_DO);
          p_a:=statement;
-         result:=cwhilerepeatnode.create(p_e,p_a,true,false);
+         if (try_to_consume(_OTHERWISE)) then
+          else_a := statement
+         else
+          else_a := nil;
+        Result := cwhilerepeatnode.Create(p_e, p_a, else_a, True, False);
       end;
 
     { a helper function which is used both by "with" and "for-in loop" nodes }
@@ -370,6 +374,7 @@
           var
              hp,
              hblock,
+             else_a,
              hto,hfrom : tnode;
              backward : boolean;
              loopvarsym : tabstractvarsym;
@@ -501,7 +506,12 @@
              if assigned(loopvarsym) then
                exclude(loopvarsym.varoptions,vo_is_loop_counter);
 
-             result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
+            if (try_to_consume(_OTHERWISE)) then
+            begin
+              else_a:=statement;
+            end else else_a:=nil;
+
+             result:=cfornode.create(hloopvar,hfrom,hto,hblock,else_a,backward);
           end;
 
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: whileotherwise.pp
Type: application/octet-stream
Size: 204 bytes
Desc: not available
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20151011/40c11fae/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: forotherwise.pp
Type: application/octet-stream
Size: 657 bytes
Desc: not available
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20151011/40c11fae/attachment-0001.obj>


More information about the fpc-devel mailing list