diff options
Diffstat (limited to 'src/cmd/gc/range.c')
-rw-r--r-- | src/cmd/gc/range.c | 252 |
1 files changed, 0 insertions, 252 deletions
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c deleted file mode 100644 index dfb2b8efd..000000000 --- a/src/cmd/gc/range.c +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* - * range - */ - -#include "go.h" - -void -typecheckrange(Node *n) -{ - char *why; - Type *t, *t1, *t2; - Node *v1, *v2; - NodeList *ll; - - // delicate little dance. see typecheckas2 - for(ll=n->list; ll; ll=ll->next) - if(ll->n->defn != n) - typecheck(&ll->n, Erv | Easgn); - - typecheck(&n->right, Erv); - if((t = n->right->type) == T) - goto out; - if(isptr[t->etype] && isfixedarray(t->type)) - t = t->type; - n->type = t; - - switch(t->etype) { - default: - yyerror("cannot range over %+N", n->right); - goto out; - - case TARRAY: - t1 = types[TINT]; - t2 = t->type; - break; - - case TMAP: - t1 = t->down; - t2 = t->type; - break; - - case TCHAN: - t1 = t->type; - t2 = nil; - if(count(n->list) == 2) - goto toomany; - break; - - case TSTRING: - t1 = types[TINT]; - t2 = types[TINT]; - break; - } - - if(count(n->list) > 2) { - toomany: - yyerror("too many variables in range"); - } - - v1 = n->list->n; - v2 = N; - if(n->list->next) - v2 = n->list->next->n; - - if(v1->defn == n) - v1->type = t1; - else if(v1->type != T && assignop(t1, v1->type, &why) == 0) - yyerror("cannot assign type %T to %+N in range%s", t1, v1, why); - if(v2) { - if(v2->defn == n) - v2->type = t2; - else if(v2->type != T && assignop(t2, v2->type, &why) == 0) - yyerror("cannot assign type %T to %+N in range%s", t2, v2, why); - } - -out: - typechecklist(n->nbody, Etop); - - // second half of dance - n->typecheck = 1; - for(ll=n->list; ll; ll=ll->next) - if(ll->n->typecheck == 0) - typecheck(&ll->n, Erv | Easgn); -} - -void -walkrange(Node *n) -{ - Node *ohv1, *hv1, *hv2; // hidden (old) val 1, 2 - Node *ha, *hit; // hidden aggregate, iterator - Node *hn, *hp; // hidden len, pointer - Node *hb; // hidden bool - Node *a, *v1, *v2; // not hidden aggregate, val 1, 2 - Node *fn, *tmp; - NodeList *body, *init; - Type *th, *t; - - t = n->type; - init = nil; - - a = n->right; - if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) { - a = nod(OCONV, n->right, N); - a->type = types[TSTRING]; - } - - v1 = n->list->n; - hv1 = N; - - v2 = N; - if(n->list->next) - v2 = n->list->next->n; - hv2 = N; - - if(v2 == N && t->etype == TARRAY) { - // will have just one reference to argument. - // no need to make a potentially expensive copy. - ha = a; - } else { - ha = nod(OXXX, N, N); - tempname(ha, a->type); - init = list(init, nod(OAS, ha, a)); - } - - switch(t->etype) { - default: - fatal("walkrange"); - - case TARRAY: - hv1 = nod(OXXX, N, n); - tempname(hv1, types[TINT]); - hn = nod(OXXX, N, N); - tempname(hn, types[TINT]); - hp = nil; - - init = list(init, nod(OAS, hv1, N)); - init = list(init, nod(OAS, hn, nod(OLEN, ha, N))); - if(v2) { - hp = nod(OXXX, N, N); - tempname(hp, ptrto(n->type->type)); - tmp = nod(OINDEX, ha, nodintconst(0)); - tmp->etype = 1; // no bounds check - init = list(init, nod(OAS, hp, nod(OADDR, tmp, N))); - } - - n->ntest = nod(OLT, hv1, hn); - n->nincr = nod(OASOP, hv1, nodintconst(1)); - n->nincr->etype = OADD; - body = list1(nod(OAS, v1, hv1)); - if(v2) { - body = list(body, nod(OAS, v2, nod(OIND, hp, N))); - tmp = nod(OADD, hp, nodintconst(t->type->width)); - tmp->type = hp->type; - tmp->typecheck = 1; - tmp->right->type = types[tptr]; - tmp->right->typecheck = 1; - body = list(body, nod(OAS, hp, tmp)); - } - break; - - case TMAP: - th = typ(TARRAY); - th->type = ptrto(types[TUINT8]); - th->bound = (sizeof(struct Hiter) + widthptr - 1) / widthptr; - hit = nod(OXXX, N, N); - tempname(hit, th); - - fn = syslook("mapiterinit", 1); - argtype(fn, t->down); - argtype(fn, t->type); - argtype(fn, th); - init = list(init, mkcall1(fn, T, nil, ha, nod(OADDR, hit, N))); - n->ntest = nod(ONE, nod(OINDEX, hit, nodintconst(0)), nodnil()); - - fn = syslook("mapiternext", 1); - argtype(fn, th); - n->nincr = mkcall1(fn, T, nil, nod(OADDR, hit, N)); - - if(v2 == N) { - fn = syslook("mapiter1", 1); - argtype(fn, th); - argtype(fn, t->down); - a = nod(OAS, v1, mkcall1(fn, t->down, nil, nod(OADDR, hit, N))); - } else { - fn = syslook("mapiter2", 1); - argtype(fn, th); - argtype(fn, t->down); - argtype(fn, t->type); - a = nod(OAS2, N, N); - a->list = list(list1(v1), v2); - a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, nod(OADDR, hit, N))); - } - body = list1(a); - break; - - case TCHAN: - hv1 = nod(OXXX, N, n); - tempname(hv1, t->type); - hb = nod(OXXX, N, N); - tempname(hb, types[TBOOL]); - - n->ntest = nod(ONE, hb, nodbool(0)); - a = nod(OAS2RECV, N, N); - a->typecheck = 1; - a->list = list(list1(hv1), hb); - a->rlist = list1(nod(ORECV, ha, N)); - n->ntest->ninit = list1(a); - body = list1(nod(OAS, v1, hv1)); - break; - - case TSTRING: - ohv1 = nod(OXXX, N, N); - tempname(ohv1, types[TINT]); - - hv1 = nod(OXXX, N, N); - tempname(hv1, types[TINT]); - init = list(init, nod(OAS, hv1, N)); - - if(v2 == N) - a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1)); - else { - hv2 = nod(OXXX, N, N); - tempname(hv2, types[TINT]); - a = nod(OAS2, N, N); - a->list = list(list1(hv1), hv2); - fn = syslook("stringiter2", 0); - a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, ha, hv1)); - } - n->ntest = nod(ONE, hv1, nodintconst(0)); - n->ntest->ninit = list(list1(nod(OAS, ohv1, hv1)), a); - - body = list1(nod(OAS, v1, ohv1)); - if(v2 != N) - body = list(body, nod(OAS, v2, hv2)); - break; - } - - n->op = OFOR; - typechecklist(init, Etop); - n->ninit = concat(n->ninit, init); - typechecklist(n->ntest->ninit, Etop); - typecheck(&n->ntest, Erv); - typecheck(&n->nincr, Etop); - typechecklist(body, Etop); - n->nbody = concat(body, n->nbody); - walkstmt(&n); -} - |