shithub: mc

Download patch

ref: ae9a74441cba3160943ad18bf500781143bff096
parent: 80c52bc20a53ac4c1c304df7a1e470c0ab62c576
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Sep 12 04:35:08 EDT 2015

Allow 'var' in loop statements.

--- a/parse/gram.y
+++ b/parse/gram.y
@@ -855,10 +855,14 @@
             {$$ = mkloopstmt($1->loc, $2, $3, $4, $5);}
         | Tfor expr Tin exprln block
             {$$ = mkiterstmt($1->loc, $2, $4, $5);}
-        /* FIXME: allow decls in for loops
-        | Tfor decl Tendln optexprln optexprln block
-            {$$ = mkloopstmt($1->loc, $2, $4, $5, $6);}
-        */
+        | Tfor decl Tendln optexprln optexprln block {
+                //Node *init;
+                if ($2.nn != 1)
+                    lfatal($1->loc, "only one declaration is allowed in for loop");
+                $$ = mkloopstmt($1->loc, $2.nl[0], $4, $5, $6);
+                putdcl($$->loopstmt.scope, $2.nl[0]);
+            }
+
         ;
 
 whilestmt
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -1651,11 +1651,14 @@
             unify(st, n, type(st, n->ifstmt.cond), mktype(n->loc, Tybool));
             break;
         case Nloopstmt:
+            setsuper(n->loopstmt.scope, curstab());
+            pushstab(n->loopstmt.scope);
             infernode(st, &n->loopstmt.init, ret, sawret);
             infernode(st, &n->loopstmt.cond, NULL, sawret);
             infernode(st, &n->loopstmt.step, ret, sawret);
             infernode(st, &n->loopstmt.body, ret, sawret);
             unify(st, n, type(st, n->loopstmt.cond), mktype(n->loc, Tybool));
+            popstab();
             break;
         case Niterstmt:
             bound = NULL;
--- a/parse/node.c
+++ b/parse/node.c
@@ -146,6 +146,7 @@
     n->loopstmt.cond = cond;
     n->loopstmt.step = incr;
     n->loopstmt.body = body;
+    n->loopstmt.scope = mkstab();
 
     return n;
 }
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -266,6 +266,7 @@
             Node *cond;
             Node *step;
             Node *body;
+            Stab *scope;
         } loopstmt;
 
         struct {
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -191,10 +191,12 @@
             fixup(n->ifstmt.iffalse);
             break;
         case Nloopstmt:
+            pushstab(n->loopstmt.scope);
             fixup(n->loopstmt.init);
             fixup(n->loopstmt.cond);
             fixup(n->loopstmt.step);
             fixup(n->loopstmt.body);
+            popstab();
             break;
         case Niterstmt:
             pushstab(n->iterstmt.body->block.scope);
@@ -290,10 +292,14 @@
             r->ifstmt.iffalse = specializenode(n->ifstmt.iffalse, tsmap);
             break;
         case Nloopstmt:
+            r->loopstmt.scope = mkstab();
+            r->loopstmt.scope->super = curstab();
+            pushstab(r->loopstmt.scope);
             r->loopstmt.init = specializenode(n->loopstmt.init, tsmap);
             r->loopstmt.cond = specializenode(n->loopstmt.cond, tsmap);
             r->loopstmt.step = specializenode(n->loopstmt.step, tsmap);
             r->loopstmt.body = specializenode(n->loopstmt.body, tsmap);
+            popstab();
             break;
         case Niterstmt:
             r->iterstmt.elt = specializenode(n->iterstmt.elt, tsmap);