shithub: mc

Download patch

ref: 5850140d219ed3f49c735c8933f752f25d2af0f3
parent: 1d621484cf5a247351702ef7b2c111ca83a41d97
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Jul 28 11:04:50 EDT 2012

Fix chained if statements.

    Jump to the end, not to the next test.

--- a/8/simp.c
+++ b/8/simp.c
@@ -321,19 +321,40 @@
 
 /* if foo; bar; else baz;;
  *      => cjmp (foo) :bar :baz */
-static void simpif(Simp *s, Node *n)
+static void simpif(Simp *s, Node *n, Node *exit)
 {
-    Node *l1, *l2;
+    Node *l1, *l2, *l3;
+    Node *iftrue, *iffalse;
     Node *c;
 
     l1 = genlbl();
     l2 = genlbl();
+    if (exit)
+        l3 = exit;
+    else
+        l3 = genlbl();
+
+    iftrue = n->ifstmt.iftrue;
+    iffalse = n->ifstmt.iffalse;
+
     c = rval(s, n->ifstmt.cond, NULL);
     cjmp(s, c, l1, l2);
     simp(s, l1);
-    simp(s, n->ifstmt.iftrue);
+    simp(s, iftrue);
+    jmp(s, l3);
     simp(s, l2);
-    simp(s, n->ifstmt.iffalse);
+    /* because lots of bunched up end labels are ugly,
+     * coalesce them by handling 'elif'-like constructs
+     * separately */
+    if (iffalse && iffalse->type == Nifstmt) {
+        simpif(s, iffalse, exit);
+    } else {
+        simp(s, iffalse);
+        jmp(s, l3);
+    }
+
+    if (!exit)
+        simp(s, l3);
 }
 
 /* init; while cond; body;; 
@@ -1062,7 +1083,7 @@
         case Nlit:       r = n;                 break;
         case Nlbl:       append(s, n);          break;
         case Nblock:     simpblk(s, n);         break;
-        case Nifstmt:    simpif(s, n);          break;
+        case Nifstmt:    simpif(s, n, NULL);    break;
         case Nloopstmt:  simploop(s, n);        break;
         case Nmatchstmt: simpmatch(s, n);       break;
         case Nexpr: