ref: 57bf65bd49ad06d0eb5f66b570cc87abb50d676b
parent: e07b79bf077459eda3d7d59cbaf1b4f431e3b2c6
author: Ori Bernstein <[email protected]>
date: Sat Dec 28 11:09:53 EST 2013
Add initial working 'for x in y' loop
--- a/6/simp.c
+++ b/6/simp.c
@@ -55,6 +55,10 @@
static void declarelocal(Simp *s, Node *n);
static void simpcond(Simp *s, Node *n, Node *ltrue, Node *lfalse);
static void simpconstinit(Simp *s, Node *dcl);
+static Node *simpcast(Simp *s, Node *val, Type *to);
+static Node *simpslice(Simp *s, Node *n, Node *dst);
+static Node *idxaddr(Simp *s, Node *seq, Node *idx);
+static void umatch(Simp *s, Node *pat, Node *val, Type *t, Node *iftrue, Node *iffalse);
/* useful constants */
static Type *tyintptr;
@@ -390,6 +394,29 @@
append(s, jmp);
}
+static Node *slicelen(Simp *s, Node *sl)
+{
+ /* *(&sl + sizeof(size_t)) */
+ return load(addk(addr(s, sl, tyintptr), Ptrsz));
+}
+
+
+static Node *seqlen(Simp *s, Node *n, Type *ty)
+{
+ Node *t, *r;
+
+ if (exprtype(n)->type == Tyslice) {
+ t = slicelen(s, n);
+ r = simpcast(s, t, ty);
+ } else if (exprtype(n)->type == Tyarray) {
+ t = exprtype(n)->asize;
+ r = simpcast(s, t, ty);
+ } else {
+ r = NULL;
+ }
+ return r;
+}
+
/* if foo; bar; else baz;;
* => cjmp (foo) :bar :baz */
static void simpif(Simp *s, Node *n, Node *exit)
@@ -431,9 +458,10 @@
* jmp :cond
* :body
* ...body...
+ * ...step...
* :cond
* ...cond...
- * cjmp (cond) :body :end
+ * cjmp (cond) :body :end
* :end
*/
static void simploop(Simp *s, Node *n)
@@ -456,6 +484,62 @@
simp(s, lend); /* exit */
}
+/* pat; seq;
+ * body;;
+ *
+ * =>
+ * .pseudo = seqinit
+ * jmp :cond
+ * :body
+ * ...body...
+ * :step
+ * ...step...
+ * :cond
+ * ...cond...
+ * cjmp (cond) :match :end
+ * :match
+ * ...match...
+ * cjmp (match) :body :step
+ * :end
+ */
+static void simpiter(Simp *s, Node *n)
+{
+ Node *lbody, *lstep, *lcond, *lmatch, *lend;
+ Node *idx, *len, *dcl, *val, *done;
+ Node *zero;
+
+ lbody = genlbl();
+ lstep = genlbl();
+ lcond = genlbl();
+ lmatch = genlbl();
+ lend = genlbl();
+
+ zero = mkintlit(n->line, 0);
+ zero->expr.type = tyintptr;
+
+ idx = gentemp(s, n, tyintptr, &dcl);
+ declarelocal(s, dcl);
+
+ /* setup */
+ append(s, assign(s, idx, zero));
+ jmp(s, lcond);
+ simp(s, lbody);
+ /* body */
+ simp(s, n->iterstmt.body);
+ /* step */
+ simp(s, lstep);
+ simp(s, assign(s, idx, addk(idx, 1)));
+ /* condition */
+ simp(s, lcond);
+ len = seqlen(s, n->iterstmt.seq, tyintptr);
+ done = mkexpr(n->line, Olt, idx, len, NULL);
+ cjmp(s, done, lmatch, lend);
+ simp(s, lmatch);
+ val = load(idxaddr(s, n->iterstmt.seq, idx));
+ umatch(s, n->iterstmt.elt, val, val->expr.type, lbody, lstep);
+ simp(s, lend);
+}
+
static Ucon *finducon(Node *n)
{
size_t i;
@@ -685,27 +769,26 @@
return r;
}
-static Node *idxaddr(Simp *s, Node *n)
+static Node *idxaddr(Simp *s, Node *seq, Node *idx)
{
Node *a, *t, *u, *v; /* temps */
Node *r; /* result */
- Node **args;
+ Type *ty;
size_t sz;
- assert(exprop(n) == Oidx);
- args = n->expr.args;
- a = rval(s, args[0], NULL);
- if (exprtype(args[0])->type == Tyarray)
- t = addr(s, a, exprtype(n));
- else if (args[0]->expr.type->type == Tyslice)
- t = load(addr(s, a, mktyptr(n->line, exprtype(n))));
+ a = rval(s, seq, NULL);
+ ty = exprtype(seq)->sub[0];
+ if (exprtype(seq)->type == Tyarray)
+ t = addr(s, a, ty);
+ else if (seq->expr.type->type == Tyslice)
+ t = load(addr(s, a, mktyptr(seq->line, ty)));
else
- die("Can't index type %s\n", tystr(n->expr.type));
+ die("Can't index type %s\n", tystr(seq->expr.type));
assert(t->expr.type->type == Typtr);
- u = rval(s, args[1], NULL);
+ u = rval(s, idx, NULL);
u = ptrsized(s, u);
- sz = size(n);
- v = mul(u, disp(n->line, sz));
+ sz = tysize(ty);
+ v = mul(u, disp(seq->line, sz));
r = add(t, v);
return r;
}
@@ -736,12 +819,6 @@
}
}
-static Node *slicelen(Simp *s, Node *sl)
-{
- /* *(&sl + sizeof(size_t)) */
- return load(addk(addr(s, sl, tyintptr), Ptrsz));
-}
-
static Node *lval(Simp *s, Node *n)
{
Node *r;
@@ -748,7 +825,7 @@
switch (exprop(n)) {
case Ovar: r = n; break;
- case Oidx: r = deref(idxaddr(s, n)); break;
+ case Oidx: r = deref(idxaddr(s, n->expr.args[0], n->expr.args[1])); break;
case Oderef: r = deref(rval(s, n->expr.args[0], NULL)); break;
case Omemb: r = deref(membaddr(s, n)); break;
default:
@@ -1163,20 +1240,14 @@
r = simpslice(s, n, dst);
break;
case Oidx:
- t = idxaddr(s, n);
+ t = idxaddr(s, n->expr.args[0], n->expr.args[1]);
r = load(t);
break;
/* array.len slice.len are magic 'virtual' members.
* they need to be special cased. */
case Omemb:
- if (exprtype(args[0])->type == Tyslice) {
- assert(!strcmp(namestr(args[1]), "len"));
- t = slicelen(s, args[0]);
- r = simpcast(s, t, exprtype(n));
- } else if (exprtype(args[0])->type == Tyarray) {
- assert(!strcmp(namestr(args[1]), "len"));
- t = exprtype(args[0])->asize;
- r = simpcast(s, t, exprtype(n));
+ if (exprtype(args[0])->type == Tyslice || exprtype(args[0])->type == Tyarray) {
+ r = seqlen(s, args[0], exprtype(n));
} else {
t = membaddr(s, n);
r = load(t);
@@ -1367,6 +1438,7 @@
case Nblock: simpblk(s, n); break;
case Nifstmt: simpif(s, n, NULL); break;
case Nloopstmt: simploop(s, n); break;
+ case Niterstmt: simpiter(s, n); break;
case Nmatchstmt: simpmatch(s, n); break;
case Nexpr:
if (islbl(n))
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -690,7 +690,7 @@
forstmt : Tfor optexprln optexprln optexprln block
{$$ = mkloopstmt($1->line, $2, $3, $4, $5);}
- | Tfor pat Tin exprln block
+ | Tfor expr Tin exprln block
{$$ = mkiterstmt($1->line, $2, $4, $5);}
/* FIXME: allow decls in for loops
| Tfor decl Tendln optexprln optexprln block