summaryrefslogtreecommitdiff
path: root/src/cmd/gc/walk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/walk.c')
-rw-r--r--src/cmd/gc/walk.c267
1 files changed, 8 insertions, 259 deletions
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index e1f2d1bf8..1121915b5 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -285,7 +285,10 @@ walkstmt(Node **np)
case OFOR:
walkstmtlist(n->ninit);
- walkexpr(&n->ntest, &n->ntest->ninit);
+ if(n->ntest != N) {
+ walkstmtlist(n->ntest->ninit);
+ walkexpr(&n->ntest, &n->ntest->ninit);
+ }
walkstmt(&n->nincr);
walkstmtlist(n->nbody);
break;
@@ -319,6 +322,10 @@ walkstmt(Node **np)
walkswitch(n);
break;
+ case ORANGE:
+ walkrange(n);
+ break;
+
case OXFALL:
yyerror("fallthrough statement out of place");
n->op = OFALL;
@@ -1703,264 +1710,6 @@ out:
}
/*
- * rewrite a range statement
- * k and v are names/new_names
- * m is an array or map
- * local is 0 (meaning =) or 1 (meaning :=)
- */
-Node*
-dorange(Node *nn)
-{
- Node *k, *v, *m;
- Node *n, *hv, *hc, *ha, *hk, *ohk, *on, *r, *a, *as;
- NodeList *init, *args;
- Type *t, *th;
- int local;
- NodeList *nl;
-
- if(nn->op != ORANGE)
- fatal("dorange not ORANGE");
-
- nl = nn->list;
- k = nl->n;
- if((nl = nl->next) != nil) {
- v = nl->n;
- nl = nl->next;
- } else
- v = N;
- if(nl != nil)
- yyerror("too many variables in range");
-
- n = nod(OFOR, N, N);
- init = nil;
-
- typecheck(&nn->right, Erv);
- m = nn->right;
- local = nn->etype;
-
- t = m->type;
- if(t == T)
- goto out;
- if(t->etype == TARRAY)
- goto ary;
- if(t->etype == TMAP)
- goto map;
- if(t->etype == TCHAN)
- goto chan;
- if(t->etype == TSTRING)
- goto strng;
-
- yyerror("range must be over map/array/chan/string");
- goto out;
-
-ary:
- hk = nod(OXXX, N, N); // hidden key
- tempname(hk, types[TINT]);
-
- ha = nod(OXXX, N, N); // hidden array
- tempname(ha, t);
-
- a = nod(OAS, hk, nodintconst(0));
- init = list(init, a);
-
- a = nod(OAS, ha, m);
- init = list(init, a);
-
- n->ntest = nod(OLT, hk, nod(OLEN, ha, N));
- n->nincr = nod(OASOP, hk, nodintconst(1));
- n->nincr->etype = OADD;
-
- if(local)
- k = old2new(k, hk->type, &init);
- n->nbody = list1(nod(OAS, k, hk));
-
- if(v != N) {
- if(local)
- v = old2new(v, t->type, &init);
- n->nbody = list(n->nbody,
- nod(OAS, v, nod(OINDEX, ha, hk)) );
- }
- goto out;
-
-map:
- th = typ(TARRAY);
- th->type = ptrto(types[TUINT8]);
- th->bound = (sizeof(struct Hiter) + types[tptr]->width - 1) /
- types[tptr]->width;
- hk = nod(OXXX, N, N); // hidden iterator
- tempname(hk, th); // hashmap hash_iter
-
- on = syslook("mapiterinit", 1);
- argtype(on, t->down);
- argtype(on, t->type);
- argtype(on, th);
- a = nod(OADDR, hk, N);
- r = nod(OCALL, on, N);
- r->list = list(list1(m), a);
-
- init = list(init, r);
-
- r = nod(OINDEX, hk, nodintconst(0));
- a = nod(OLITERAL, N, N);
- a->val.ctype = CTNIL;
- a->type = types[TNIL];
- r = nod(ONE, r, a);
- n->ntest = r;
-
- on = syslook("mapiternext", 1);
- argtype(on, th);
- r = nod(OADDR, hk, N);
- args = list1(r);
- r = nod(OCALL, on, N);
- r->list = args;
- n->nincr = r;
-
- if(local)
- k = old2new(k, t->down, &init);
- if(v == N) {
- on = syslook("mapiter1", 1);
- argtype(on, th);
- argtype(on, t->down);
- r = nod(OADDR, hk, N);
- args = list1(r);
- r = nod(OCALL, on, N);
- r->list = args;
- n->nbody = list1(nod(OAS, k, r));
- goto out;
- }
- if(local)
- v = old2new(v, t->type, &init);
- on = syslook("mapiter2", 1);
- argtype(on, th);
- argtype(on, t->down);
- argtype(on, t->type);
- r = nod(OADDR, hk, N);
- args = list1(r);
- r = nod(OCALL, on, N);
- r->list = args;
- as = nod(OAS2, N, N);
- as->list = list(list1(k), v);
- as->rlist = list1(r);
- n->nbody = list1(as);
- goto out;
-
-chan:
- if(v != N)
- yyerror("chan range can only have one variable");
-
- hc = nod(OXXX, N, N); // hidden chan
- tempname(hc, t);
-
- hv = nod(OXXX, N, N); // hidden value
- tempname(hv, t->type);
-
- a = nod(OAS, hc, m);
- init = list(init, a);
-
- a = nod(ORECV, hc, N);
- a = nod(OAS, hv, a);
- init = list(init, a);
-
- a = nod(OCLOSED, N, N);
- a->list = list1(hc);
- n->ntest = nod(ONOT, a, N);
- n->nincr = nod(OAS, hv, nod(ORECV, hc, N));
-
- if(local)
- k = old2new(k, hv->type, &init);
- n->nbody = list1(nod(OAS, k, hv));
-
- goto out;
-
-strng:
- hk = nod(OXXX, N, N); // hidden key
- tempname(hk, types[TINT]);
-
- ohk = nod(OXXX, N, N); // old hidden key
- tempname(ohk, types[TINT]);
-
- ha = nod(OXXX, N, N); // hidden string
- tempname(ha, types[TSTRING]);
-
- hv = N;
- if(v != N) {
- hv = nod(OXXX, N, N); // hidden value
- tempname(hv, types[TINT]);
- }
-
- if(local) {
- k = old2new(k, types[TINT], &init);
- if(v != N)
- v = old2new(v, types[TINT], &init);
- }
-
- // ha = s
- a = nod(OCONV, m, N);
- a->type = ha->type;
- a = nod(OAS, ha, a);
- init = list(init, a);
-
- // ohk = 0
- a = nod(OAS, ohk, nodintconst(0));
- init = list(init, a);
-
- // hk[,hv] = stringiter(ha,hk)
- if(v != N) {
- // hk,v = stringiter2(ha, hk)
- on = syslook("stringiter2", 0);
- a = nod(OCALL, on, N);
- a->list = list(list1(ha), nodintconst(0));
- as = nod(OAS2, N, N);
- as->list = list(list1(hk), hv);
- as->rlist = list1(a);
- a = as;
- } else {
- // hk = stringiter(ha, hk)
- on = syslook("stringiter", 0);
- a = nod(OCALL, on, N);
- a->list = list(list1(ha), nodintconst(0));
- a = nod(OAS, hk, a);
- }
- init = list(init, a);
-
- // while(hk != 0)
- n->ntest = nod(ONE, hk, nodintconst(0));
-
- // hk[,hv] = stringiter(ha,hk)
- if(v != N) {
- // hk,hv = stringiter2(ha, hk)
- on = syslook("stringiter2", 0);
- a = nod(OCALL, on, N);
- a->list = list(list1(ha), hk);
- as = nod(OAS2, N, N);
- as->list = list(list1(hk), hv);
- as->rlist = list1(a);
- a = as;
- } else {
- // hk = stringiter(ha, hk)
- on = syslook("stringiter", 0);
- a = nod(OCALL, on, N);
- a->list = list(list1(ha), hk);
- a = nod(OAS, hk, a);
- }
- n->nincr = a;
-
- // k,ohk[,v] = ohk,hk,[,hv]
- a = nod(OAS, k, ohk);
- n->nbody = list1(a);
- a = nod(OAS, ohk, hk);
- n->nbody = list(n->nbody, a);
- if(v != N) {
- a = nod(OAS, v, hv);
- n->nbody = list(n->nbody, a);
- }
-
-out:
- n->ninit = concat(n->ninit, init);
- return n;
-}
-
-/*
* from ascompat[te]
* evaluating actual function arguments.
* f(a,b)