summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--6/blob.c1
-rw-r--r--mi/fold.c73
-rw-r--r--parse/gram.y27
3 files changed, 69 insertions, 32 deletions
diff --git a/6/blob.c b/6/blob.c
index 59a5dbf..95e5678 100644
--- a/6/blob.c
+++ b/6/blob.c
@@ -255,6 +255,7 @@ static size_t blobrec(Blob *b, Htab *globls, Htab *strtab, Node *n)
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]);
diff --git a/mi/fold.c b/mi/fold.c
index 38c4824..3bf960d 100644
--- 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 @@ static int islit(Node *n, vlong *v)
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,7 +98,25 @@ static Node *foldcast(Node *n)
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)
{
@@ -114,6 +132,8 @@ Node *fold(Node *n, int foldvar)
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 @@ Node *fold(Node *n, int foldvar)
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:
@@ -201,6 +221,9 @@ Node *fold(Node *n, int foldvar)
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);
break;
diff --git a/parse/gram.y b/parse/gram.y
index 5c8b291..8b643da 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -792,13 +792,23 @@ arrayelts
: 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 {
+ if ($4->expr.idx)
+ lappend(&$$.nl, &$$.nn, $4);
+ else
+ lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkintlit($4->loc, $$.nn), $4));
}
- | arrayelts Tcomma optendlns arrayelt
- {lappend(&$$.nl, &$$.nn, mkidxinit($4->loc, mkint($4->loc, $$.nn), $4));}
;
arrayelt: expr optendlns {$$ = $1;}
+ | expr Tcolon expr optendlns {
+ $$ = mkidxinit($2->loc, $1, $3);
+ }
;
structelts
@@ -807,12 +817,15 @@ structelts
$$.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 */