From 0dadc4fe4fb3124fcaed535c92bdc2354205e521 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 10 Jul 2009 16:29:26 -0700 Subject: [PATCH] cleanup in preparation for new scoping. walkstate -> walkstmt walktype -> walkexpr; stmts moved to walkstmt walktype and friends have a final Node **init argument that can have side effects appended, making it more explicit when they do and do not happen. this replaces the old global addtop and addtotop. delete switch map and interface conversion cases (dropped from the language months ago). R=ken OCL=31465 CL=31468 --- src/cmd/gc/dcl.c | 76 ++--- src/cmd/gc/go.h | 42 ++- src/cmd/gc/go.y | 50 ++-- src/cmd/gc/sinit.c | 2 +- src/cmd/gc/subr.c | 27 +- src/cmd/gc/swt.c | 16 +- src/cmd/gc/walk.c | 693 ++++++++++++++++++++------------------------- 7 files changed, 412 insertions(+), 494 deletions(-) diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index f889cf606e..64a4735ae1 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -17,8 +17,12 @@ dflag(void) return 1; } +/* + * declare (possible list) n of type t. + * append ODCL nodes to *init + */ void -dodclvar(Node *n, Type *t) +dodclvar(Node *n, Type *t, Node **init) { if(n == N) return; @@ -26,7 +30,7 @@ dodclvar(Node *n, Type *t) if(t != T && (t->etype == TIDEAL || t->etype == TNIL)) fatal("dodclvar %T", t); for(; n->op == OLIST; n = n->right) - dodclvar(n->left, t); + dodclvar(n->left, t, init); dowidth(t); @@ -39,7 +43,7 @@ dodclvar(Node *n, Type *t) addvar(n, t, dclcontext); autoexport(n->sym); if(funcdepth > 0) - addtop = list(addtop, nod(ODCL, n, N)); + *init = list(*init, nod(ODCL, n, N)); } void @@ -1665,13 +1669,14 @@ embedded(Sym *s) /* * declare variables from grammar - * new_name_list [type] = expr_list + * new_name_list (type | [type] = expr_list) */ Node* variter(Node *vv, Type *t, Node *ee) { Iter viter, eiter; Node *v, *e, *r, *a; + Type *tv; vv = rev(vv); ee = rev(ee); @@ -1680,29 +1685,31 @@ variter(Node *vv, Type *t, Node *ee) e = listfirst(&eiter, &ee); r = N; -loop: - if(v == N && e == N) - return rev(r); + while(v != N) { + if(ee != N && e == N) { + yyerror("missing expr in var dcl"); + break; + } - if(v == N || e == N) { - yyerror("shape error in var dcl"); - return rev(r); + a = N; + if(e != N || funcdepth > 0) + a = nod(OAS, v, e); + tv = t; + if(t == T) { + gettype(e, &r); + defaultlit(e, T); + tv = e->type; + } + dodclvar(v, tv, &r); + r = list(r, a); + + v = listnext(&viter); + if(ee != N) + e = listnext(&eiter); } - - a = nod(OAS, v, N); - if(t == T) { - gettype(e, a); - defaultlit(e, T); - dodclvar(v, e->type); - } else - dodclvar(v, t); - a->right = e; - - r = list(r, a); - - v = listnext(&viter); - e = listnext(&eiter); - goto loop; + if(e != N) + yyerror("extra expr in var dcl"); + return rev(r); } /* @@ -1713,7 +1720,7 @@ void constiter(Node *vv, Type *t, Node *cc) { Iter viter, citer; - Node *v, *c, n1; + Node *v, *c, *init; if(cc == N) { if(t != T) @@ -1741,9 +1748,9 @@ loop: return; } - memset(&n1, 0, sizeof n1); - gettype(c, &n1); - if(n1.ninit != nil) { + init = N; + gettype(c, &init); + if(init != N) { // the expression had extra code to run. // dodclconst is going to print an error // because the expression isn't constant, @@ -1771,7 +1778,7 @@ loop: Node* unsafenmagic(Node *l, Node *r) { - Node *n; + Node *n, *init; Sym *s; Type *t, *tr; long v; @@ -1787,8 +1794,9 @@ unsafenmagic(Node *l, Node *r) if(strcmp(s->package, "unsafe") != 0) goto no; + init = N; if(strcmp(s->name, "Sizeof") == 0) { - walktype(r, Erv); + walkexpr(r, Erv, &init); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; @@ -1800,12 +1808,12 @@ unsafenmagic(Node *l, Node *r) if(strcmp(s->name, "Offsetof") == 0) { if(r->op != ODOT && r->op != ODOTPTR) goto no; - walktype(r, Erv); + walkexpr(r, Erv, &init); v = r->xoffset; goto yes; } if(strcmp(s->name, "Alignof") == 0) { - walktype(r, Erv); + walkexpr(r, Erv, &init); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; @@ -1830,7 +1838,7 @@ no: return N; yes: - addtop = N; // any side effects disappear + // any side effects disappear; ignore init val.ctype = CTINT; val.u.xval = mal(sizeof(*n->val.u.xval)); mpmovecfix(val.u.xval, v); diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 1bcfd420c6..011d6dc957 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -601,7 +601,6 @@ EXTERN int widthptr; EXTERN Node* retnil; EXTERN Node* fskel; -EXTERN Node* addtop; EXTERN Node* typeswvar; EXTERN char* structpkg; @@ -765,7 +764,7 @@ void tempname(Node*, Type*); Node* staticname(Type*); int iscomposite(Type*); Node* callnew(Type*); -Node* saferef(Node*); +Node* saferef(Node*, Node**); int is64(Type*); int noconv(Type*, Type*); @@ -812,7 +811,7 @@ int simsimtype(Type*); /* * dcl.c */ -void dodclvar(Node*, Type*); +void dodclvar(Node*, Type*, Node**); Type* dodcltype(Type*); void updatetype(Type*, Type*); void dodclconst(Node*, Node*); @@ -907,30 +906,29 @@ Type* pkgtype(Sym*); /* * walk.c */ -void addtotop(Node*); -void gettype(Node*, Node*); +void gettype(Node*, Node**); void walk(Node*); -void walkstate(Node*); -void walktype(Node*, int); -void walkconv(Node*); +void walkstmt(Node*); +void walkexpr(Node*, int, Node**); +void walkconv(Node*, Node**); void walkas(Node*); void walkbool(Node*); void walkswitch(Node*); void walkselect(Node*); -void walkdot(Node*); -Node* ascompatee(int, Node**, Node**); -Node* ascompatet(int, Node**, Type**, int); -Node* ascompatte(int, Type**, Node**, int); +void walkdot(Node*, Node**); +Node* ascompatee(int, Node**, Node**, Node**); +Node* ascompatet(int, Node**, Type**, int, Node**); +Node* ascompatte(int, Type**, Node**, int, Node**); int ascompat(Type*, Type*); Node* prcompat(Node*, int); Node* nodpanic(int32); Node* newcompat(Node*); Node* makecompat(Node*); -Node* stringop(Node*, int); +Node* stringop(Node*, int, Node**); Type* fixmap(Type*); -Node* mapop(Node*, int); +Node* mapop(Node*, int, Node**); Type* fixchan(Type*); -Node* chanop(Node*, int); +Node* chanop(Node*, int, Node**); Node* arrayop(Node*, int); Node* ifacecvt(Type*, Node*, int); Node* ifaceop(Node*); @@ -938,18 +936,18 @@ int ifaceas(Type*, Type*, int); int ifaceas1(Type*, Type*, int); void ifacecheck(Type*, Type*, int, int); void runifacechecks(void); -Node* convas(Node*); +Node* convas(Node*, Node**); void arrayconv(Type*, Node*); -Node* colas(Node*, Node*); +Node* colas(Node*, Node*, Node**); Node* dorange(Node*); Node* reorder1(Node*); Node* reorder3(Node*); Node* reorder4(Node*); -Node* structlit(Node*, Node*); -Node* arraylit(Node*, Node*); -Node* maplit(Node*, Node*); -Node* selectas(Node*, Node*); -Node* old2new(Node*, Type*); +Node* structlit(Node*, Node*, Node**); +Node* arraylit(Node*, Node*, Node**); +Node* maplit(Node*, Node*, Node**); +Node* selectas(Node*, Node*, Node**); +Node* old2new(Node*, Type*, Node**); void addrescapes(Node*); void heapmoves(void); diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 046db1d914..263b6bf07f 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -351,30 +351,15 @@ varoptsemi: vardcl: name_list type varoptsemi { - dodclvar($$, $2); - - if(funcdepth == 0) { - $$ = N; - } else { - $$ = nod(OAS, $$, N); - addtotop($$); - } + $$ = variter($1, $2, N); } | name_list type varoptsemi '=' expr_list { - if(addtop != N) - fatal("new_name_list_r type '=' expr_list"); - $$ = variter($1, $2, $5); - addtotop($$); } | name_list '=' expr_list { - if(addtop != N) - fatal("new_name_list_r '=' expr_list"); - $$ = variter($1, T, $3); - addtotop($$); } constdcl: @@ -438,16 +423,17 @@ simple_stmt: } | expr_list LCOLAS expr_list { - if(addtop != N) - fatal("expr_list LCOLAS expr_list"); + Node *top; + if($3->op == OTYPESW) { $$ = nod(OTYPESW, $1, $3->left); break; } - $$ = colas($$, $3); + top = N; + $$ = colas($$, $3, &top); $$ = nod(OAS, $$, $3); $$->colas = 1; - addtotop($$); + $$->ninit = top; } | expr LINC { @@ -463,9 +449,12 @@ simple_stmt: case: LCASE expr_list ':' { + Node *top; + // will be converted to OCASE // right will point to next case // done in casebody() + top = N; poptodcl(); if(typeswvar != N && typeswvar->right != N) { int e; @@ -476,14 +465,14 @@ case: break; } if($2->op == OTYPE) { - $$ = old2new(typeswvar->right, $2->type); + $$ = old2new(typeswvar->right, $2->type, &top); $$ = nod(OTYPESW, $$, N); $$ = nod(OXCASE, $$, N); - addtotop($$); + $$->ninit = top; break; } e = nerrors; - gettype($2, N); + gettype($2, nil); // maybe gettype found problems that keep // e from being valid even outside a type switch. // only complain if gettype didn't print new errors. @@ -497,15 +486,18 @@ case: } | LCASE type ':' { + Node *top; + + top = N; poptodcl(); if(typeswvar == N || typeswvar->right == N) { yyerror("type case not in a type switch"); $$ = N; } else - $$ = old2new(typeswvar->right, $2); + $$ = old2new(typeswvar->right, $2, &top); $$ = nod(OTYPESW, $$, N); $$ = nod(OXCASE, $$, N); - addtotop($$); + $$->ninit = top; } | LCASE name '=' expr ':' { @@ -518,13 +510,16 @@ case: } | LCASE name LCOLAS expr ':' { + Node *top; + // will be converted to OCASE // right will point to next case // done in casebody() poptodcl(); - $$ = nod(OAS, selectas($2,$4), $4); + top = N; + $$ = nod(OAS, selectas($2, $4, &top), $4); $$ = nod(OXCASE, $$, N); - addtotop($$); + $$->ninit = top; } | LDEFAULT ':' { @@ -621,7 +616,6 @@ for_header: | range_stmt { $$ = dorange($1); - addtotop($$); } for_body: diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index 021b030146..fa7aabdabd 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -249,7 +249,7 @@ mapindex(Node *n) b = nod(OAS, b, val); a = nod(OLIST, a, b); - walktype(a, Etop); + walkexpr(a, Etop, nil); return a; } diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 9c5d2c1264..06790c8568 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -517,11 +517,13 @@ appendr(Node *na, Node *nb) Type* aindex(Node *b, Type *t) { + Node *top; Type *r; int bound; bound = -1; // open bound - walktype(b, Erv); + top = N; + walkexpr(b, Erv, &top); if(b != nil) { switch(consttype(b)) { default: @@ -2452,25 +2454,26 @@ staticname(Type *t) } /* - * return side effect-free n, moving side effects to top. + * return side effect-free n, appending side effects to init. */ Node* -saferef(Node *n) +saferef(Node *n, Node **init) { Node *l; Node *r; + Node *a; switch(n->op) { case ONAME: return n; case ODOT: - l = saferef(n->left); + l = saferef(n->left, init); if(l == n->left) return n; r = nod(OXXX, N, N); *r = *n; r->left = l; - walktype(r, Elv); + walkexpr(r, Elv, init); return r; case OINDEX: @@ -2478,9 +2481,11 @@ saferef(Node *n) case OIND: l = nod(OXXX, N, N); tempname(l, ptrto(n->type)); - addtop = list(addtop, nod(OAS, l, nod(OADDR, n, N))); + a = nod(OAS, l, nod(OADDR, n, N)); + walkexpr(a, Etop, init); + *init = list(*init, a); r = nod(OIND, l, N); - walktype(r, Elv); + walkexpr(r, Elv, init); return r; } fatal("saferef %N", n); @@ -2634,11 +2639,13 @@ out: Node* adddot(Node *n) { + Node *top; Type *t; Sym *s; int c, d; - walktype(n->left, Erv); + top = N; + walkexpr(n->left, Erv, &top); t = n->left->type; if(t == T) goto ret; @@ -2666,8 +2673,8 @@ out: n->left->right = newname(dotlist[c].field->sym); } ret: - n->ninit = list(addtop, n->ninit); - addtop = N; + if(top != N) + n->ninit = list(top, n->ninit); return n; } diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c index 4347eeac95..282e5d157b 100644 --- a/src/cmd/gc/swt.c +++ b/src/cmd/gc/swt.c @@ -247,7 +247,7 @@ sw0(Node *c, Type *place, int arg) yyerror("inappropriate case for a type switch"); return T; } - walktype(c, Erv); + walkexpr(c, Erv, nil); break; case OTYPESW: if(arg != Stype) @@ -298,7 +298,7 @@ sw3(Node *c, Type *place, int arg) } /* - * over all cases, call paramenter function. + * over all cases, call parameter function. * four passes of these are used to allocate * types to cases and switch */ @@ -335,7 +335,7 @@ loop: } Node* -newlabel() +newlabel(void) { static int label; @@ -598,7 +598,7 @@ exprswitch(Node *sw) if(sw->ntest->val.u.bval == 0) arg = Sfalse; } - walktype(sw->ntest, Erv); + walkexpr(sw->ntest, Erv, &sw->ninit); /* * pass 0,1,2,3 @@ -639,7 +639,7 @@ loop: if(c0 == C) { cas = list(cas, def); sw->nbody->left = rev(cas); - walkstate(sw->nbody); + walkstmt(sw->nbody); return; } @@ -773,7 +773,7 @@ typeswitch(Node *sw) yyerror("type switch must have an assignment"); return; } - walktype(sw->ntest->right, Erv); + walkexpr(sw->ntest->right, Erv, &sw->ninit); if(!istype(sw->ntest->right->type, TINTER)) { yyerror("type switch must be on an interface"); return; @@ -818,7 +818,7 @@ loop: if(c0 == C) { cas = list(cas, def); sw->nbody->left = rev(cas); - walkstate(sw->nbody); + walkstmt(sw->nbody); return; } @@ -860,7 +860,7 @@ walkswitch(Node *sw) * cases have OGOTO into statements. * both have inserted OBREAK statements */ - walkstate(sw->ninit); + walkstmt(sw->ninit); if(sw->ntest == N) sw->ntest = nodbool(1); casebody(sw); diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 65313bcbce..21f19773ba 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -72,11 +72,7 @@ walk(Node *fn) if(curfn->type->outtuple) if(walkret(curfn->nbody)) yyerror("function ends without a return statement"); - if(addtop != N) { - dump("addtop", addtop); - fatal("addtop in walk"); - } - walkstate(curfn->nbody); + walkstmt(curfn->nbody); if(debug['W']) { snprint(s, sizeof(s), "after walk %S", curfn->nname->sym); dump(s, curfn->nbody); @@ -89,55 +85,37 @@ walk(Node *fn) } void -addtotop(Node *n) -{ - Node *l; - - while(addtop != N) { - l = addtop; - addtop = N; - walktype(l, Etop); - n->ninit = list(n->ninit, l); - } -} - -void -gettype(Node *n, Node *a) +gettype(Node *n, Node **init) { if(debug['W']) dump("\nbefore gettype", n); - walktype(n, Erv); - if(a == N && addtop != N) - fatal("gettype: addtop"); - addtotop(a); + walkexpr(n, Erv, init); if(debug['W']) dump("after gettype", n); } void -walkstate(Node *n) +walkstmt(Node *n) { - Node *more; + Node *init, *l; + int lno; -loop: + while(n != N && n->op == OLIST) { + walkstmt(n->left); + n = n->right; + } if(n == N) return; - more = N; + lno = lineno; setlineno(n); switch(n->op) { - - case OLIST: - walkstate(n->left); - more = n->right; - break; - default: if(n->op == ONAME) - yyerror("walkstate: %S not a top level statement", n->sym); + yyerror("walkstmt: %S not a top level statement", n->sym); else - yyerror("walkstate: %O not a top level statement", n->op); + yyerror("walkstmt: %O not a top level statement", n->op); break; case OASOP: @@ -147,38 +125,79 @@ loop: case OCALLMETH: case OCALLINTER: case OCALL: - case ODCL: case OSEND: case ORECV: case OPRINT: case OPRINTN: case OPANIC: case OPANICN: - case OFOR: - case OIF: - case OSWITCH: - case OSELECT: case OEMPTY: + init = N; + walkexpr(n, Etop, &init); + n->ninit = list(n->ninit, init); + break; + case OBREAK: + case ODCL: case OCONTINUE: + case OFALL: case OGOTO: case OLABEL: - case OFALL: - case OXCASE: - case OCASE: - case OXFALL: - case ORETURN: - case OPROC: - case ODEFER: - walktype(n, Etop); break; - } - addtotop(n); + case OXCASE: + yyerror("case statement out of place"); + n->op = OCASE; + case OCASE: + walkstmt(n->right); + break; - if(more != N) { - n = more; - goto loop; + case ODEFER: + hasdefer = 1; + walkexpr(n->left, Etop, &n->ninit); + break; + + case OFOR: + walkstmt(n->ninit); + walkbool(n->ntest); + walkstmt(n->nincr); + walkstmt(n->nbody); + break; + + case OIF: + walkstmt(n->ninit); + walkbool(n->ntest); + walkstmt(n->nbody); + walkstmt(n->nelse); + break; + + case OPROC: + walkexpr(n->left, Etop, &n->ninit); + break; + + case ORETURN: + walkexpr(n->left, Erv, &n->ninit); + if(curfn->type->outnamed && n->left == N) { + // print("special return\n"); + break; + } + l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1, &n->ninit); + if(l != N) + n->left = reorder4(l); + break; + + case OSELECT: + walkselect(n); + break; + + case OSWITCH: + walkswitch(n); + break; + + case OXFALL: + yyerror("fallthrough statement out of place"); + n->op = OFALL; + break; } } @@ -206,12 +225,19 @@ implicitstar(Node **nn) if(!isfixedarray(t)) return; n = nod(OIND, n, N); - walktype(n, Elv); + walkexpr(n, Elv, nil); *nn = n; } +/* + * walk the whole tree of the body of an + * expression or simple statement. + * the types expressions are calculated. + * compile-time constants are evaluated. + * complex side effects like statements are appended to init + */ void -walktype(Node *n, int top) +walkexpr(Node *n, int top, Node **init) { Node *r, *l; Type *t; @@ -223,12 +249,6 @@ walktype(Node *n, int top) return; lno = setlineno(n); - /* - * walk the whole tree of the body of a function. - * the types expressions are calculated. - * compile-time constants are evaluated. - */ - loop: if(n == N) goto ret; @@ -244,7 +264,7 @@ loop: switch(n->op) { default: dump("walk", n); - fatal("walktype: switch 1 unknown op %N", n); + fatal("walkexpr: switch 1 unknown op %N", n); goto ret; case OTYPE: @@ -254,40 +274,37 @@ loop: } goto ret; - case ODCL: - goto ret; - case OLIST: case OKEY: - walktype(n->left, top); + walkexpr(n->left, top, init); n = n->right; goto loop; case OPRINT: if(top != Etop) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); indir(n, prcompat(n->left, 0)); goto ret; case OPRINTN: if(top != Etop) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); indir(n, prcompat(n->left, 1)); goto ret; case OPANIC: if(top != Etop) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); indir(n, list(prcompat(n->left, 0), nodpanic(n->lineno))); goto ret; case OPANICN: if(top != Etop) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); indir(n, list(prcompat(n->left, 2), nodpanic(n->lineno))); goto ret; @@ -317,53 +334,14 @@ loop: s = n->sym; if(s->undef == 0) { if(n->etype != 0) - yyerror("walktype: %S must be called", s); + yyerror("walkexpr: %S must be called", s, init); else - yyerror("walktype: %S undeclared", s); + yyerror("walkexpr: %S undeclared", s, init); s->undef = 1; } } goto ret; - case OFOR: - if(top != Etop) - goto nottop; - walkstate(n->ninit); - walkbool(n->ntest); - walkstate(n->nincr); - walkstate(n->nbody); - goto ret; - - case OSWITCH: - if(top != Etop) - goto nottop; - - walkswitch(n); - goto ret; - - case OSELECT: - if(top != Etop) - goto nottop; - walkselect(n); - goto ret; - - case OIF: - if(top != Etop) - goto nottop; - walkstate(n->ninit); - walkbool(n->ntest); - walkstate(n->nbody); - walkstate(n->nelse); - goto ret; - - case ODEFER: - hasdefer = 1; - case OPROC: - if(top != Etop) - goto nottop; - walktype(n->left, Etop); - goto ret; - case OCALLMETH: case OCALLINTER: case OCALL: @@ -376,7 +354,7 @@ loop: if(n->left == N) goto ret; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); defaultlit(n->left, T); t = n->left->type; @@ -409,32 +387,32 @@ loop: break; } - walktype(n->right, Erv); + walkexpr(n->right, Erv, init); switch(n->op) { default: fatal("walk: op: %O", n->op); case OCALLINTER: - l = ascompatte(n->op, getinarg(t), &n->right, 0); + l = ascompatte(n->op, getinarg(t), &n->right, 0, init); n->right = reorder1(l); break; case OCALL: - l = ascompatte(n->op, getinarg(t), &n->right, 0); + l = ascompatte(n->op, getinarg(t), &n->right, 0, init); n->right = reorder1(l); if(isselect(n)) { // clear output bool - special prob with selectsend Node *b; b = nodbool(0); - r = ascompatte(n->op, getoutarg(t), &b, 0); + r = ascompatte(n->op, getoutarg(t), &b, 0, init); n->right = list(n->right, r); } break; case OCALLMETH: - l = ascompatte(n->op, getinarg(t), &n->right, 0); - r = ascompatte(n->op, getthis(t), &n->left->left, 0); + l = ascompatte(n->op, getinarg(t), &n->right, 0, init); + r = ascompatte(n->op, getthis(t), &n->left->left, 0, init); l = list(r, l); n->left->left = N; ullmancalc(n->left); @@ -447,12 +425,12 @@ loop: if(top != Etop) goto nottop; - addtop = list(addtop, n->ninit); + *init = list(*init, n->ninit); n->ninit = N; l = n->left; r = n->right; - walktype(l, Elv); + walkexpr(l, Elv, init); if(l == N || r == N) goto ret; @@ -461,8 +439,8 @@ loop: if(cl == cr) { simpleas: - walktype(r, Erv); - l = ascompatee(n->op, &n->left, &n->right); + walkexpr(r, Erv, init); + l = ascompatee(n->op, &n->left, &n->right, init); if(l != N) indir(n, reorder3(l)); goto ret; @@ -475,10 +453,10 @@ loop: case OCALL: if(cr == 1) { // a,b,... = fn() - walktype(r, Erv); + walkexpr(r, Erv, init); if(r->type == T || r->type->etype != TSTRUCT) break; - l = ascompatet(n->op, &n->left, &r->type, 0); + l = ascompatet(n->op, &n->left, &r->type, 0, init); if(l != N) indir(n, list(r, l)); goto ret; @@ -488,11 +466,11 @@ loop: case OINDEX: if(cl == 2 && cr == 1) { // a,b = map[] - mapaccess2 - walktype(r->left, Erv); + walkexpr(r->left, Erv, init); implicitstar(&r->left); if(!istype(r->left->type, TMAP)) break; - l = mapop(n, top); + l = mapop(n, top, init); if(l == N) break; indir(n, l); @@ -503,10 +481,10 @@ loop: case ORECV: if(cl == 2 && cr == 1) { // a,b = left, Erv); + walkexpr(r->left, Erv, init); if(!istype(r->left->type, TCHAN)) break; - l = chanop(n, top); + l = chanop(n, top, init); if(l == N) break; indir(n, l); @@ -517,7 +495,7 @@ loop: case ODOTTYPE: if(cl == 2 && cr == 1) { // a,b = i.(T) - walktype(r->left, Erv); + walkexpr(r->left, Erv, init); if(r->left == N) break; et = ifaceas1(r->type, r->left->type, 1); @@ -548,7 +526,7 @@ loop: if(et == Inone) break; r = ifacecvt(r->type, r->left, et); - l = ascompatet(n->op, &n->left, &r->type, 0); + l = ascompatet(n->op, &n->left, &r->type, 0, init); if(l != N) indir(n, list(r, l)); goto ret; @@ -562,7 +540,7 @@ loop: // map[] = a,b - mapassign2 if(!istype(l->left->type, TMAP)) break; - l = mapop(n, top); + l = mapop(n, top, init); if(l == N) break; indir(n, l); @@ -576,33 +554,6 @@ loop: } goto ret; - case OBREAK: - case OCONTINUE: - case OGOTO: - case OLABEL: - if(top != Etop) - goto nottop; - goto ret; - - case OXCASE: - if(top != Etop) - goto nottop; - yyerror("case statement out of place"); - n->op = OCASE; - - case OCASE: - if(top != Etop) - goto nottop; - walkstate(n->right); - goto ret; - - case OXFALL: - if(top != Etop) - goto nottop; - yyerror("fallthrough statement out of place"); - n->op = OFALL; - - case OFALL: case OINDREG: case OEMPTY: goto ret; @@ -611,7 +562,7 @@ loop: case ODOTTYPE: if(top != Erv) goto nottop; - walkconv(n); + walkconv(n, init); goto ret; case OCONVNOP: @@ -635,32 +586,18 @@ loop: goto ret; case TSTRUCT: - r = structlit(n, N); + r = structlit(n, N, init); break; case TARRAY: - r = arraylit(n, N); + r = arraylit(n, N, init); break; case TMAP: - r = maplit(n, N); + r = maplit(n, N, init); break; } indir(n, r); -// walktype(l, Erv); - goto ret; - - case ORETURN: - if(top != Etop) - goto nottop; - walktype(n->left, Erv); - if(curfn->type->outnamed && n->left == N) { - // print("special return\n"); - goto ret; - } - l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1); - if(l != N) - n->left = reorder4(l); goto ret; case ONOT: @@ -669,7 +606,7 @@ loop: evconst(n); if(n->op == OLITERAL) goto ret; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); if(n->left == N || n->left->type == T) goto ret; et = n->left->type->etype; @@ -678,10 +615,10 @@ loop: case OASOP: if(top != Etop) goto nottop; - walktype(n->left, Elv); + walkexpr(n->left, Elv, init); l = n->left; if(l->op == OINDEX && istype(l->left->type, TMAP)) - indir(n, mapop(n, top)); + indir(n, mapop(n, top, init)); if(n->etype == OLSH || n->etype == ORSH) goto shft; goto com; @@ -690,10 +627,10 @@ loop: case ORSH: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); shft: - walktype(n->right, Erv); + walkexpr(n->right, Erv, init); if(n->left == N || n->right == N) goto ret; evconst(n); @@ -728,10 +665,10 @@ loop: case ODIV: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); com: - walktype(n->right, Erv); + walkexpr(n->right, Erv, init); if(n->left == N || n->right == N) goto ret; evconst(n); @@ -757,6 +694,11 @@ loop: n->right->type = n->right->left->type; break; } + if(istype(n->left->type, TSTRING)) { + indir(n, stringop(n, top, init)); + goto ret; + } + break; case OEQ: case ONE: @@ -766,7 +708,7 @@ loop: case OGT: case OADD: if(istype(n->left->type, TSTRING)) { - indir(n, stringop(n, top)); + indir(n, stringop(n, top, nil)); goto ret; } break; @@ -778,7 +720,7 @@ loop: case OCOM: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); if(n->left == N) goto ret; evconst(n); @@ -789,7 +731,7 @@ loop: case OLEN: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); if(n->left == N) { yyerror("missing argument to len"); goto ret; @@ -819,7 +761,7 @@ loop: case OCAP: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); defaultlit(n->left, T); implicitstar(&n->left); t = n->left->type; @@ -840,8 +782,8 @@ loop: if(top == Etop) goto nottop; - walktype(n->left, Erv); - walktype(n->right, Erv); + walkexpr(n->left, Erv, init); + walkexpr(n->right, Erv, init); if(n->left == N || n->right == N) goto ret; @@ -867,7 +809,7 @@ loop: break; if(!isint[n->right->type->etype]) goto badt; - indir(n, stringop(n, top)); + indir(n, stringop(n, top, nil)); break; case TMAP: @@ -879,7 +821,7 @@ loop: goto badt; n->type = t->type; if(top == Erv) - indir(n, mapop(n, top)); + indir(n, mapop(n, top, nil)); break; case TARRAY: @@ -897,44 +839,44 @@ loop: case OCLOSE: if(top != Etop) goto nottop; - walktype(n->left, Erv); // chan - indir(n, chanop(n, top)); + walkexpr(n->left, Erv, init); // chan + indir(n, chanop(n, top, nil)); goto ret; case OCLOSED: if(top == Elv) goto nottop; - walktype(n->left, Erv); // chan - indir(n, chanop(n, top)); + walkexpr(n->left, Erv, init); // chan + indir(n, chanop(n, top, nil)); goto ret; case OSEND: if(top == Elv) goto nottop; - walktype(n->left, Erv); // chan - walktype(n->right, Erv); // e - indir(n, chanop(n, top)); + walkexpr(n->left, Erv, init); // chan + walkexpr(n->right, Erv, init); // e + indir(n, chanop(n, top, nil)); goto ret; case ORECV: if(top == Elv) goto nottop; if(n->right == N) { - walktype(n->left, Erv); // chan - indir(n, chanop(n, top)); // returns e blocking + walkexpr(n->left, Erv, init); // chan + indir(n, chanop(n, top, init)); // returns e blocking goto ret; } - walktype(n->left, Elv); // e - walktype(n->right, Erv); // chan - indir(n, chanop(n, top)); // returns bool non-blocking + walkexpr(n->left, Elv, init); // e + walkexpr(n->right, Erv, init); // chan + indir(n, chanop(n, top, nil)); // returns bool non-blocking goto ret; case OSLICE: if(top == Etop) goto nottop; - walktype(n->left, top); - walktype(n->right, Erv); + walkexpr(n->left, top, init); + walkexpr(n->right, Erv, init); if(n->left == N || n->right == N) goto ret; defaultlit(n->left, T); @@ -945,7 +887,7 @@ loop: if(t == T) goto ret; if(t->etype == TSTRING) { - indir(n, stringop(n, top)); + indir(n, stringop(n, top, nil)); goto ret; } if(t->etype == TARRAY) { @@ -962,7 +904,7 @@ loop: if(top == Etop) goto nottop; defaultlit(n->left, T); - walkdot(n); + walkdot(n, init); goto ret; case OADDR: @@ -982,27 +924,27 @@ loop: tempname(nvar, ptrto(n->left->type)); nas = nod(OAS, nvar, callnew(n->left->type)); - walktype(nas, Etop); - addtop = list(addtop, nas); + walkexpr(nas, Etop, init); + *init = list(*init, nas); nstar = nod(OIND, nvar, N); nstar->type = n->left->type; switch(n->left->type->etype) { case TSTRUCT: - structlit(n->left, nstar); + structlit(n->left, nstar, init); break; case TARRAY: - arraylit(n->left, nstar); + arraylit(n->left, nstar, init); break; case TMAP: - maplit(n->left, nstar); + maplit(n->left, nstar, init); break; default: goto badlit; } -// walktype(n->left->left, Erv); +// walkexpr(n->left->left, Erv, init); indir(n, nvar); goto ret; } @@ -1016,7 +958,7 @@ loop: } if(n->left == N) goto ret; - walktype(n->left, Elv); + walkexpr(n->left, Elv, init); t = n->left->type; if(t == T) goto ret; @@ -1029,7 +971,7 @@ loop: goto nottop; if(top == Elv) // even if n is lvalue, n->left is rvalue top = Erv; - walktype(n->left, top); + walkexpr(n->left, top, init); defaultlit(n->left, T); if(n->left == N) goto ret; @@ -1075,7 +1017,7 @@ loop: switch(n->op) { default: - fatal("walktype: switch 2 unknown op %N", n); + fatal("walkexpr: switch 2 unknown op %N", n, init); goto ret; case OASOP: @@ -1140,7 +1082,7 @@ loop: // TODO(rsc): Can do this more efficiently, // but OSUB is wrong. Should be in back end anyway. indir(n, nod(OMUL, n->left, nodintconst(-1))); - walktype(n, Erv); + walkexpr(n, Erv, init); goto ret; } break; @@ -1187,7 +1129,7 @@ loop: r = nod(OCALL, l, list(n->left, n->right)); r = nod(OCONV, r, N); r->type = n->left->left->type; - walktype(r, Erv); + walkexpr(r, Erv, init); indir(n, r); goto ret; @@ -1195,9 +1137,9 @@ loop: et = n->left->type->etype; if(widthptr > 4 || (et != TUINT64 && et != TINT64)) break; - l = saferef(n->left); + l = saferef(n->left, init); r = nod(OAS, l, nod(n->etype, l, n->right)); - walktype(r, Etop); + walkexpr(r, Etop, init); indir(n, r); goto ret; } @@ -1253,16 +1195,16 @@ ret: void walkbool(Node *n) { - walktype(n, Erv); + if(n == N) + return; + walkexpr(n, Erv, &n->ninit); defaultlit(n, T); - addtotop(n); - if(n != N && n->type != T) - if(!eqtype(n->type, types[TBOOL])) - yyerror("IF and FOR require a boolean type"); + if(n->type != T && !eqtype(n->type, types[TBOOL])) + yyerror("IF and FOR require a boolean type"); } void -walkconv(Node *n) +walkconv(Node *n, Node **init) { int et; char *what; @@ -1275,7 +1217,7 @@ walkconv(Node *n) l = n->left; if(l == N) return; - walktype(l, Erv); + walkexpr(l, Erv, init); if(l->type == T) return; @@ -1334,7 +1276,7 @@ walkconv(Node *n) if(istype(t, TSTRING)) { et = l->type->etype; if(isint[et]) { - indir(n, stringop(n, Erv)); + indir(n, stringop(n, Erv, nil)); return; } @@ -1342,7 +1284,7 @@ walkconv(Node *n) if((isptr[et] && isfixedarray(l->type->type) && istype(l->type->type->type, TUINT8)) || (isslice(l->type) && istype(l->type->type, TUINT8))) { n->op = OARRAY; - indir(n, stringop(n, Erv)); + indir(n, stringop(n, Erv, nil)); return; } @@ -1350,7 +1292,7 @@ walkconv(Node *n) if((isptr[et] && isfixedarray(l->type->type) && istype(l->type->type->type, TINT)) || (isslice(l->type) && istype(l->type->type, TINT))) { n->op = OARRAY; - indir(n, stringop(n, Erv)); + indir(n, stringop(n, Erv, nil)); return; } } @@ -1399,7 +1341,7 @@ bad: } Node* -selcase(Node *n, Node *var) +selcase(Node *n, Node *var, Node **init) { Node *a, *r, *on, *c; Type *t; @@ -1410,8 +1352,8 @@ selcase(Node *n, Node *var) if(c->op == ORECV) goto recv; - walktype(c->left, Erv); // chan - walktype(c->right, Erv); // elem + walkexpr(c->left, Erv, init); // chan + walkexpr(c->right, Erv, init); // elem t = fixchan(c->left->type); if(t == T) @@ -1446,7 +1388,7 @@ recv: if(c->right != N) goto recv2; - walktype(c->left, Erv); // chan + walkexpr(c->left, Erv, init); // chan t = fixchan(c->left->type); if(t == T) @@ -1475,7 +1417,7 @@ recv: goto out; recv2: - walktype(c->right, Erv); // chan + walkexpr(c->right, Erv, init); // chan t = fixchan(c->right->type); if(t == T) @@ -1486,7 +1428,7 @@ recv2: return N; } - walktype(c->left, Elv); // elem + walkexpr(c->left, Elv, init); // elem convlit(c->left, t->type); if(!ascompat(t->type, c->left->type)) { badtype(c->op, t->type, c->left->type); @@ -1526,55 +1468,23 @@ out: * enumerate the special cases * of the case statement: * case v := <-chan // select and switch - * case v := map[] // switch - * case v := interface.(TYPE) // switch */ Node* -selectas(Node *name, Node *expr) +selectas(Node *name, Node *expr, Node **init) { - Node *a; Type *t; - if(expr == N) - goto bad; - switch(expr->op) { - default: -//dump("case", expr); + if(expr == N || expr->op != ORECV) goto bad; - case ORECV: - walktype(expr->left, Erv); - t = expr->left->type; - if(t == T) - goto bad; - if(t->etype != TCHAN) - goto bad; - t = t->type; - break; - - case OINDEX: - walktype(expr->left, Erv); - walktype(expr->right, Erv); - t = expr->left->type; - if(t == T) - goto bad; - if(t->etype != TMAP) - goto bad; - t = t->type; - break; - - case ODOTTYPE: - walktype(expr->left, Erv); - t = expr->left->type; - if(t == T) - goto bad; - if(t->etype != TINTER) - goto bad; - t = expr->type; - break; - } - a = old2new(name, t); - return a; + walkexpr(expr->left, Erv, init); + t = expr->left->type; + if(t == T) + goto bad; + if(t->etype != TCHAN) + goto bad; + t = t->type; + return old2new(name, t, init); bad: return name; @@ -1584,13 +1494,15 @@ void walkselect(Node *sel) { Iter iter, iter1; - Node *n, *n1, *l, *oc, *on, *r; + Node *n, *n1, *l, *oc, *on, *r, *init; Node *var, *bod, *nbod, *res, *def; int count, op; int32 lno; lno = setlineno(sel); + init = N; + // generate sel-struct var = nod(OXXX, N, N); tempname(var, ptrto(types[TUINT8])); @@ -1665,7 +1577,7 @@ walkselect(Node *sel) nbod = list(nbod, nod(OBREAK, N, N)); n->nbody = N; - oc = selcase(n, var); + oc = selcase(n, var, &init); if(oc != N) { oc->nbody = rev(nbod); res = list(res, oc); @@ -1690,11 +1602,11 @@ walkselect(Node *sel) sel->nbody = rev(res); sel->left = N; - walkstate(sel->ninit); - walkstate(sel->nbody); - + walkstmt(sel->ninit); + walkstmt(sel->nbody); //dump("sel", sel); + sel->ninit = list(sel->ninit, init); lineno = lno; } @@ -1741,7 +1653,7 @@ lookdot(Node *n, Type *t) if(t->etype == TINTER) { if(isptr[n->left->type->etype]) { n->left = nod(OIND, n->left, N); // implicitstar - walktype(n->left, Elv); + walkexpr(n->left, Elv, nil); } n->op = ODOTINTER; } @@ -1753,7 +1665,7 @@ lookdot(Node *n, Type *t) rcvr = getthisx(f2->type)->type->type; if(!eqtype(rcvr, tt)) { if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) { - walktype(n->left, Elv); + walkexpr(n->left, Elv, nil); addrescapes(n->left); n->left = nod(OADDR, n->left, N); n->left->type = ptrto(tt); @@ -1776,12 +1688,15 @@ lookdot(Node *n, Type *t) } void -walkdot(Node *n) +walkdot(Node *n, Node **init) { Type *t; - addtop = list(addtop, n->ninit); - n->ninit = N; + walkexpr(n->ninit, Etop, init); + if(n->ninit != N) { + *init = list(*init, n->ninit); + n->ninit = N; + } if(n->left == N || n->right == N) return; @@ -1791,7 +1706,7 @@ walkdot(Node *n) return; // already done } - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); if(n->right->op != ONAME) { yyerror("rhs of . must be a name"); return; @@ -1818,7 +1733,7 @@ walkdot(Node *n) } Node* -ascompatee(int op, Node **nl, Node **nr) +ascompatee(int op, Node **nl, Node **nr, Node **init) { Node *l, *r, *nn, *a; Iter savel, saver; @@ -1849,7 +1764,7 @@ loop: yyerror("cannot assign to function"); a = nod(OAS, l, r); - a = convas(a); + a = convas(a, init); nn = list(a, nn); l = listnext(&savel); @@ -1874,7 +1789,7 @@ fncall(Node *l, Type *rt) } Node* -ascompatet(int op, Node **nl, Type **nr, int fp) +ascompatet(int op, Node **nl, Type **nr, int fp, Node **init) { Node *l, *nn, *mm, *tmp, *a; Type *r; @@ -1919,13 +1834,13 @@ loop: tmp = nod(OXXX, N, N); tempname(tmp, r->type); a = nod(OAS, l, tmp); - a = convas(a); + a = convas(a, init); mm = list(mm, a); l = tmp; } a = nod(OAS, l, nodarg(r, fp)); - a = convas(a); + a = convas(a, init); ullmancalc(a); if(a->ullman >= UINF) ucount++; @@ -1968,7 +1883,7 @@ sigtype(Type *st) * with a pointer to the structure. */ Node* -mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) +mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp, Node **init) { Type *t, *st, *ft; Node *a, *n, *var; @@ -2017,7 +1932,7 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) var->sym = lookup(".ddd"); // assign the fields to the struct. - // use addtop so that reorder1 doesn't reorder + // use the init list so that reorder1 doesn't reorder // these assignments after the interface conversion // below. n = rev(n); @@ -2028,7 +1943,8 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) *r->left = *var; r->left->type = r->right->type; r->left->xoffset += t->width; - addtop = list(addtop, r); + walkexpr(r, Etop, init); + *init = list(*init, r); r = listnext(&saven); t = t->down; } @@ -2036,7 +1952,7 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) // last thing is to put assignment // of the structure to the DDD parameter a = nod(OAS, nodarg(l, fp), var); - nn = list(convas(a), nn); + nn = list(convas(a, init), nn); return nn; } @@ -2094,7 +2010,7 @@ dumpnodetypes(Node **nr, char *what) * func(expr-list) */ Node* -ascompatte(int op, Type **nl, Node **nr, int fp) +ascompatte(int op, Type **nl, Node **nr, int fp, Node **init) { Type *l, *ll; Node *r, *rr, *nn, *a; @@ -2118,7 +2034,7 @@ ascompatte(int op, Type **nl, Node **nr, int fp) fatal("misaligned multiple return\n\t%T\n\t%T", r->type, *nl); a = nodarg(*nl, fp); a->type = r->type; - return convas(nod(OAS, a, r)); + return convas(nod(OAS, a, r), init); } loop: @@ -2135,7 +2051,7 @@ loop: rr = listnext(&saver); if(r != N && rr == N && isddd(r->type)) { a = nod(OAS, nodarg(l, fp), r); - a = convas(a); + a = convas(a, init); nn = list(a, nn); return rev(nn); } @@ -2143,7 +2059,7 @@ loop: // normal case -- make a structure of all // remaining arguments and pass a pointer to // it to the ddd parameter (empty interface) - nn = mkdotargs(r, rr, &saver, nn, l, fp); + nn = mkdotargs(r, rr, &saver, nn, l, fp, init); return rev(nn); } @@ -2167,7 +2083,7 @@ loop: a = nod(OAS, nodarg(l, fp), r); - a = convas(a); + a = convas(a, init); nn = list(a, nn); l = structnext(&savel); @@ -2296,7 +2212,7 @@ loop: on = syslook("printnl", 0); r = list(r, nod(OCALL, on, N)); } - walktype(r, Etop); + walkexpr(r, Etop, nil); return r; } @@ -2305,7 +2221,7 @@ loop: r = list(r, nod(OCALL, on, N)); } - walktype(l, Erv); + walkexpr(l, Erv, nil); if(l->op == OLITERAL) { switch(l->val.ctype) { case CTINT: @@ -2376,7 +2292,7 @@ nodpanic(int32 lineno) on = syslook("panicl", 0); n = nodintconst(lineno); n = nod(OCALL, on, n); - walktype(n, Etop); + walkexpr(n, Etop, nil); return n; } @@ -2408,9 +2324,9 @@ makecompat(Node *n) goto bad; return arrayop(n, Erv); case TMAP: - return mapop(n, Erv); + return mapop(n, Erv, nil); case TCHAN: - return chanop(n, Erv); + return chanop(n, Erv, nil); } bad: @@ -2431,12 +2347,12 @@ callnew(Type *t) argtype(on, t); r = nodintconst(t->width); r = nod(OCALL, on, r); - walktype(r, Erv); + walkexpr(r, Erv, nil); return r; } Node* -stringop(Node *n, int top) +stringop(Node *n, int top, Node **init) { Node *r, *c, *on; @@ -2540,7 +2456,7 @@ stringop(Node *n, int top) break; } - walktype(r, top); + walkexpr(r, top, init); return r; } @@ -2584,7 +2500,7 @@ bad: } Node* -mapop(Node *n, int top) +mapop(Node *n, int top, Node **init) { Node *r, *a; Type *t; @@ -2632,7 +2548,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-2 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); r->type = n->type; break; @@ -2665,7 +2581,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-4 r = nod(OCALL, on, r); - walktype(r, Erv); + walkexpr(r, Erv, nil); r->type = t->type; break; @@ -2703,7 +2619,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-4 r = nod(OCALL, on, r); - walktype(r, Etop); + walkexpr(r, Etop, init); break; assign2: @@ -2732,7 +2648,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-4 r = nod(OCALL, on, r); - walktype(r, Etop); + walkexpr(r, Etop, init); break; access2: @@ -2759,7 +2675,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-4 n->right = nod(OCALL, on, r); - walktype(n, Etop); + walkexpr(n, Etop, init); r = n; break; @@ -2778,7 +2694,7 @@ mapop(Node *n, int top) a = nod(n->etype, a, n->right); // m[tmpi] op right a = nod(OAS, n->left, a); // map[tmpi] = map[tmpi] op right r = nod(OLIST, r, a); - walktype(r, Etop); + walkexpr(r, Etop, init); break; } return r; @@ -2794,15 +2710,13 @@ nottop: } Node* -chanop(Node *n, int top) +chanop(Node *n, int top, Node **init) { Node *r, *a; Type *t; Node *on; int cl, cr; -//dump("chanop", n); - r = n; switch(n->op) { default: @@ -2821,7 +2735,7 @@ chanop(Node *n, int top) argtype(on, t); // any-1 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); r->type = n->type; break; @@ -2838,7 +2752,7 @@ chanop(Node *n, int top) argtype(on, t); // any-1 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); n->type = r->type; break; @@ -2871,7 +2785,7 @@ chanop(Node *n, int top) argtype(on, t->type); // any-1 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); r->type = n->type; break; @@ -2903,7 +2817,7 @@ chanop(Node *n, int top) r = nod(OCALL, on, r); n->right = r; r = n; - walktype(r, Etop); + walkexpr(r, Etop, init); break; case ORECV: @@ -2929,7 +2843,7 @@ chanop(Node *n, int top) argtype(on, t->type); // any-1 argtype(on, t->type); // any-2 r = nod(OCALL, on, r); - walktype(r, Erv); + walkexpr(r, Erv, nil); break; recv2: @@ -2956,7 +2870,7 @@ chanop(Node *n, int top) r = nod(OCALL, on, r); n->right = r; r = n; - walktype(r, Etop); + walkexpr(r, Etop, nil); break; case OSEND: @@ -2981,7 +2895,7 @@ chanop(Node *n, int top) argtype(on, t->type); // any-1 argtype(on, t->type); // any-2 r = nod(OCALL, on, r); - walktype(r, Etop); + walkexpr(r, Etop, nil); break; send2: @@ -2995,7 +2909,7 @@ chanop(Node *n, int top) argtype(on, t->type); // any-1 argtype(on, t->type); // any-2 r = nod(OCALL, on, r); - walktype(r, Etop); + walkexpr(r, Etop, nil); break; } return r; @@ -3059,7 +2973,7 @@ arrayop(Node *n, int top) argtype(on, tl->type); // any-2 r = nod(OCALL, on, r); n->left = r; - walktype(n, top); + walkexpr(n, top, nil); return n; case OAS: @@ -3104,7 +3018,7 @@ arrayop(Node *n, int top) argtype(on, t->type); // any-1 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); r->type = t; // if t had a name, going through newarray lost it break; @@ -3152,7 +3066,7 @@ arrayop(Node *n, int top) argtype(on, t->type); // any-2 } r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); break; } return r; @@ -3311,7 +3225,7 @@ ifacecvt(Type *tl, Node *n, int et) } r = nod(OCALL, on, r); - walktype(r, Erv); + walkexpr(r, Erv, nil); return r; } @@ -3345,18 +3259,13 @@ ifaceop(Node *n) r = nod(OCALL, on, r); if(n->op == ONE) r = nod(ONOT, r, N); - - walktype(r, Erv); + walkexpr(r, Erv, nil); return r; } - - r = nod(OCALL, on, r); - walktype(r, Erv); - return r; } Node* -convas(Node *n) +convas(Node *n, Node **init) { Node *l, *r; Type *lt, *rt; @@ -3380,13 +3289,13 @@ convas(Node *n) if(n->left->op == OINDEX) if(istype(n->left->left->type, TMAP)) { - indir(n, mapop(n, Elv)); + indir(n, mapop(n, Elv, init)); goto out; } if(n->left->op == OSEND) if(n->left->type != T) { - indir(n, chanop(n, Elv)); + indir(n, chanop(n, Elv, init)); goto out; } @@ -3437,7 +3346,7 @@ colasname(Node *n) } Node* -old2new(Node *n, Type *t) +old2new(Node *n, Type *t, Node **init) { Node *l; @@ -3446,7 +3355,7 @@ old2new(Node *n, Type *t) return n; } l = newname(n->sym); - dodclvar(l, t); + dodclvar(l, t, init); return l; } @@ -3459,7 +3368,7 @@ mixedoldnew(Node *n, Type *t) } static Node* -checkmixed(Node *nl) +checkmixed(Node *nl, Node **init) { Iter save; Node *l, *n, *a; @@ -3504,7 +3413,7 @@ checkmixed(Node *nl) a = l; if(l->sym->block != block) - a = old2new(l, t); + a = old2new(l, t, init); n = list(n, a); l = listnext(&save); @@ -3519,7 +3428,7 @@ allnew: t = l->type; l = l->left; - a = old2new(l, t); + a = old2new(l, t, init); n = list(n, a); l = listnext(&save); } @@ -3527,7 +3436,7 @@ allnew: } Node* -colas(Node *nl, Node *nr) +colas(Node *nl, Node *nr, Node **init) { Iter savel, saver; Node *l, *r, *a, *n; @@ -3549,16 +3458,16 @@ colas(Node *nl, Node *nr) case OCALLMETH: case OCALLINTER: case OCALL: - walktype(nr->left, Erv); + walkexpr(nr->left, Erv, init); convlit(nr->left, types[TFUNC]); t = nr->left->type; if(t == T) - return nl; // error already printed + goto outl; // error already printed if(t->etype == tptr) t = t->type; if(t == T || t->etype != TFUNC) { yyerror("cannot call %T", t); - return nl; + goto outl; } if(t->outtuple != cl) { cr = t->outtuple; @@ -3568,15 +3477,15 @@ colas(Node *nl, Node *nr) l = listfirst(&savel, &nl); t = structfirst(&saver, getoutarg(t)); if(t == T) - return N; + goto outl; while(l != N) { a = mixedoldnew(l, t->type); n = list(n, a); l = listnext(&savel); t = structnext(&saver); } - n = checkmixed(n); - return n; + n = checkmixed(n, init); + goto out; } } if(cl != cr) { @@ -3589,7 +3498,7 @@ colas(Node *nl, Node *nr) r = listfirst(&saver, &nr); while(l != N) { - walktype(r, Erv); + walkexpr(r, Erv, init); defaultlit(r, T); a = mixedoldnew(l, r->type); n = list(n, a); @@ -3597,8 +3506,8 @@ colas(Node *nl, Node *nr) l = listnext(&savel); r = listnext(&saver); } - n = checkmixed(n); - return n; + n = checkmixed(n, init); + goto out; multi: /* @@ -3616,7 +3525,7 @@ multi: // if so, types are valuetype,bool if(cl != 2) goto badt; - walktype(nr->left, Erv); + walkexpr(nr->left, Erv, init); implicitstar(&nr->left); t = nr->left->type; if(!istype(t, TMAP)) @@ -3625,14 +3534,14 @@ multi: n = a; a = mixedoldnew(nl->right, types[TBOOL]); n = list(n, a); - n = checkmixed(n); + n = checkmixed(n, init); break; case ODOTTYPE: // a,b := i.(T) if(cl != 2) goto badt; - walktype(nr->left, Erv); + walkexpr(nr->left, Erv, init); if(!isinter(nr->left->type)) goto badt; // a,b = iface @@ -3640,13 +3549,13 @@ multi: n = a; a = mixedoldnew(nl->right, types[TBOOL]); n = list(n, a); - n = checkmixed(n); + n = checkmixed(n, init); break; case ORECV: if(cl != 2) goto badt; - walktype(nr->left, Erv); + walkexpr(nr->left, Erv, init); t = nr->left->type; if(!istype(t, TCHAN)) goto badt; @@ -3654,10 +3563,11 @@ multi: n = a; a = mixedoldnew(nl->right, types[TBOOL]); n = list(n, a); - n = checkmixed(n); + n = checkmixed(n, init); break; } n = rev(n); +out: return n; badt: @@ -3665,6 +3575,7 @@ badt: nl->diag = 1; yyerror("assignment count mismatch: %d = %d", cl, cr); } +outl: return nl; } @@ -3695,7 +3606,7 @@ dorange(Node *nn) n = nod(OFOR, N, N); init = N; - walktype(nn->right, Erv); + walkexpr(nn->right, Erv, &init); implicitstar(&nn->right); m = nn->right; local = nn->etype; @@ -3733,16 +3644,15 @@ ary: n->nincr->etype = OADD; if(local) - k = old2new(k, hk->type); + k = old2new(k, hk->type, &init); n->nbody = nod(OAS, k, hk); if(v != N) { if(local) - v = old2new(v, t->type); + v = old2new(v, t->type, &init); n->nbody = list(n->nbody, nod(OAS, v, nod(OINDEX, ha, hk)) ); } - addtotop(n); goto out; map: @@ -3777,7 +3687,7 @@ map: n->nincr = r; if(local) - k = old2new(k, t->down); + k = old2new(k, t->down, &init); if(v == N) { on = syslook("mapiter1", 1); argtype(on, th); @@ -3788,7 +3698,7 @@ map: goto out; } if(local) - v = old2new(v, t->type); + v = old2new(v, t->type, &init); on = syslook("mapiter2", 1); argtype(on, th); argtype(on, t->down); @@ -3819,9 +3729,9 @@ chan: n->nincr = nod(OAS, hv, nod(ORECV, hc, N)); if(local) - k = old2new(k, hv->type); + k = old2new(k, hv->type, &init); n->nbody = nod(OAS, k, hv); - addtotop(n); + goto out; strng: @@ -3841,9 +3751,9 @@ strng: } if(local) { - k = old2new(k, types[TINT]); + k = old2new(k, types[TINT], &init); if(v != N) - v = old2new(v, types[TINT]); + v = old2new(v, types[TINT], &init); } // ha = s @@ -3900,9 +3810,6 @@ strng: n->nbody = list(n->nbody, a); } - addtotop(n); - goto out; - out: n->ninit = list(n->ninit, init); return n; @@ -4124,7 +4031,7 @@ fielddup(Node *n, Node *hash[], ulong nhash) } Node* -structlit(Node *n, Node *var) +structlit(Node *n, Node *var, Node **init) { Iter savel, saver; Type *l, *t; @@ -4164,10 +4071,10 @@ structlit(Node *n, Node *var) // build list of var.field = expr a = nod(ODOT, var, newname(l->sym)); a = nod(OAS, a, r); - walktype(a, Etop); + walkexpr(a, Etop, init); if(nerr != nerrors) return var; - addtop = list(addtop, a); + *init = list(*init, a); l = structnext(&savel); r = listnext(&saver); @@ -4181,7 +4088,8 @@ structlit(Node *n, Node *var) keyval: memset(hash, 0, sizeof(hash)); a = nod(OAS, var, N); - addtop = list(addtop, a); + walkexpr(a, Etop, init); + *init = list(*init, a); while(r != N) { // assignment to field:value elements @@ -4197,11 +4105,11 @@ keyval: break; a = nod(OAS, a, r->right); - walktype(a, Etop); + walkexpr(a, Etop, init); if(nerr != nerrors) break; - addtop = list(addtop, a); + *init = list(*init, a); r = listnext(&saver); } @@ -4232,7 +4140,7 @@ indexdup(Node *n, Node *hash[], ulong nhash) } Node* -arraylit(Node *n, Node *var) +arraylit(Node *n, Node *var, Node **init) { Iter saver; Type *t; @@ -4283,13 +4191,15 @@ arraylit(Node *n, Node *var) // slice a = nod(OMAKE, nod(OLIST, typenod(t), nodintconst(ninit)), N); a = nod(OAS, var, a); - addtop = list(addtop, a); + walkexpr(a, Etop, init); + *init = list(*init, a); } else { // if entire array isnt initialized, // then clear the array if(ninit < b) { a = nod(OAS, var, N); - addtop = list(addtop, a); + walkexpr(a, Etop, init); + *init = list(*init, a); } } @@ -4322,11 +4232,11 @@ arraylit(Node *n, Node *var) a = nod(OINDEX, var, a); a = nod(OAS, a, r); - walktype(a, Etop); // add any assignments in r to addtop + walkexpr(a, Etop, init); // add any assignments in r to top if(nerr != nerrors) break; - addtop = list(addtop, a); + *init = list(*init, a); b++; r = listnext(&saver); @@ -4390,7 +4300,7 @@ keydup(Node *n, Node *hash[], ulong nhash) } Node* -maplit(Node *n, Node *var) +maplit(Node *n, Node *var, Node **init) { Iter saver; Type *t; @@ -4410,7 +4320,8 @@ maplit(Node *n, Node *var) a = nod(OMAKE, typenod(t), N); a = nod(OAS, var, a); - addtop = list(addtop, a); + walkexpr(a, Etop, init); + *init = list(*init, a); r = listfirst(&saver, &n->left); if(r != N && r->op == OEMPTY) @@ -4433,11 +4344,11 @@ maplit(Node *n, Node *var) a = nod(OINDEX, var, r->left); a = nod(OAS, a, r->right); - walktype(a, Etop); + walkexpr(a, Etop, init); if(nerr != nerrors) break; - addtop = list(addtop, a); + *init = list(*init, a); r = listnext(&saver); }