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: