shithub: mc

Download patch

ref: 1ac0bb9cd95650fd0029f354f874974d1772a601
parent: ae494e5d5cbc5ff8094f47efdec22898d84dde63
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Aug 1 20:18:36 EDT 2015

Initial support for indexed initializers.

--- a/6/blob.c
+++ b/6/blob.c
@@ -255,6 +255,7 @@
         case Olit:      sz = bloblit(b, strtab, n->expr.args[0], exprtype(n));        break;
         case Otup:
         case Oarr:
+                        /* Assumption: We sorted this while folding */
                         sz = 0;
                         for (i = 0; i < n->expr.nargs; i++)
                             sz += blobrec(b, globls, strtab, n->expr.args[i]);
--- a/mi/fold.c
+++ b/mi/fold.c
@@ -13,7 +13,7 @@
 #include "parse.h"
 #include "mi.h"
 
-static int islit(Node *n, vlong *v)
+static int getintlit(Node *n, vlong *v)
 {
     Node *l;
 
@@ -26,11 +26,11 @@
     return 1;
 }
 
-static int isval(Node *n, vlong val)
+static int isintval(Node *n, vlong val)
 {
     vlong v;
 
-    if (!islit(n, &v))
+    if (!getintlit(n, &v))
         return 0;
     return v == val;
 }
@@ -98,8 +98,26 @@
     return n;
 }
 
+int idxcmp(const void *pa, const void *pb)
+{
+    Node *a, *b;
+    vlong av, bv;
 
+    a = *(Node **)pa;
+    b = *(Node **)pb;
 
+    assert(getintlit(a->expr.idx, &av));
+    assert(getintlit(b->expr.idx, &bv));
+
+    /* don't trust overflow with int64 */
+    if (av < bv)
+        return -1;
+    else if (av == bv)
+        return 0;
+    else
+        return 1;
+}
+
 Node *fold(Node *n, int foldvar)
 {
     Node **args, *r;
@@ -114,6 +132,8 @@
 
     r = NULL;
     args = n->expr.args;
+    if (n->expr.idx)
+        n->expr.idx = fold(n->expr.idx, foldvar);
     for (i = 0; i < n->expr.nargs; i++)
         args[i] = fold(args[i], foldvar);
     switch (exprop(n)) {
@@ -123,76 +143,76 @@
             break;
         case Oadd:
             /* x + 0 = 0 */
-            if (isval(args[0], 0))
+            if (isintval(args[0], 0))
                 r = args[1];
-            if (isval(args[1], 0))
+            if (isintval(args[1], 0))
                 r = args[0];
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a + b, exprtype(n));
             break;
         case Osub:
             /* x - 0 = 0 */
-            if (isval(args[1], 0))
+            if (isintval(args[1], 0))
                 r = args[0];
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a - b, exprtype(n));
             break;
         case Omul:
             /* 1 * x = x */
-            if (isval(args[0], 1))
+            if (isintval(args[0], 1))
                 r = args[1];
-            if (isval(args[1], 1))
+            if (isintval(args[1], 1))
                 r = args[0];
             /* 0 * x = 0 */
-            if (isval(args[0], 0))
+            if (isintval(args[0], 0))
                 r = args[0];
-            if (isval(args[1], 0))
+            if (isintval(args[1], 0))
                 r = args[1];
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a * b, exprtype(n));
             break;
         case Odiv:
             /* x/0 = error */
-            if (isval(args[1], 0))
+            if (isintval(args[1], 0))
                 fatal(args[1], "division by zero");
             /* x/1 = x */
-            if (isval(args[1], 1))
+            if (isintval(args[1], 1))
                 r = args[0];
             /* 0/x = 0 */
-            if (isval(args[1], 0))
+            if (isintval(args[1], 0))
                 r = args[1];
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a / b, exprtype(n));
             break;
         case Omod:
             /* x%1 = x */
-            if (isval(args[1], 0))
+            if (isintval(args[1], 0))
                 r = args[0];
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a % b, exprtype(n));
             break;
         case Oneg:
-            if (islit(args[0], &a))
+            if (getintlit(args[0], &a))
                 r = val(n->loc, -a, exprtype(n));
             break;
         case Obsl:
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a << b, exprtype(n));
             break;
         case Obsr:
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a >> b, exprtype(n));
             break;
         case Obor:
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a | b, exprtype(n));
             break;
         case Oband:
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a & b, exprtype(n));
             break;
         case Obxor:
-            if (islit(args[0], &a) && islit(args[1], &b))
+            if (getintlit(args[0], &a) && getintlit(args[1], &b))
                 r = val(n->loc, a ^ b, exprtype(n));
             break;
         case Omemb:
@@ -200,6 +220,9 @@
             /* we only fold lengths right now */
             if (t->type == Tyarray && !strcmp(namestr(args[1]), "len"))
                 r = t->asize;
+            break;
+        case Oarr:
+            qsort(n->expr.args, n->expr.nargs, sizeof(Node*), idxcmp);
             break;
         case Ocast:
             r = foldcast(n);
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -792,13 +792,23 @@
         : optendlns arrayelt {
                 $$.nl = NULL;
                 $$.nn = 0;
-                lappend(&$$.nl, &$$.nn, mkidxinit($2->loc, mkint($2->loc, 0), $2));
+                if ($2->expr.idx)
+                    lappend(&$$.nl, &$$.nn, $2);
+                else
+                    lappend(&$$.nl, &$$.nn, mkidxinit($2->loc, mkintlit($2->loc, 0), $2));
             }
-        | arrayelts Tcomma optendlns arrayelt
-             {lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkint($4->loc, $$.nn), $4));}
+        | arrayelts Tcomma optendlns arrayelt {
+                if ($4->expr.idx)
+                    lappend(&$$.nl, &$$.nn, $4);
+                else
+                    lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkintlit($4->loc, $$.nn), $4));
+            }
         ;
 
 arrayelt: expr optendlns {$$ = $1;}
+        | expr Tcolon expr optendlns {
+                $$ = mkidxinit($2->loc, $1, $3);
+            }
         ;
 
 structelts
@@ -807,12 +817,15 @@
                 $$.nn = 0;
                 lappend(&$$.nl, &$$.nn, $2);
             }
-        | structelts Tcomma optendlns structelt
-             {lappend(&$$.nl, &$$.nn, $4);}
+        | structelts Tcomma optendlns structelt {
+                lappend(&$$.nl, &$$.nn, $4);
+            }
         ;
 
-structelt: Tdot Tident Tasn expr optendlns
-            {$$ = mkidxinit($2->loc, mkname($2->loc, $2->id), $4);}
+structelt: Tdot Tident Tasn expr optendlns {
+                $$ = $4;
+                mkidxinit($2->loc, mkname($2->loc, $2->id), $4);
+            }
          ;
 
 optendlns  : /* none */