Commit 0dadc4fe authored by Russ Cox's avatar Russ Cox

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
parent ed124a97
......@@ -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);
if(v == N || e == N) {
yyerror("shape error in var dcl");
return rev(r);
}
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;
while(v != N) {
if(ee != N && e == N) {
yyerror("missing expr in var dcl");
break;
}
r = list(r, a);
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);
e = listnext(&eiter);
goto loop;
v = listnext(&viter);
if(ee != N)
e = listnext(&eiter);
}
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);
......
......@@ -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);
......
......@@ -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:
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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:
break;
case OXCASE:
yyerror("case statement out of place");
n->op = OCASE;
case OCASE:
case OXFALL:
case ORETURN:
case OPROC:
walkstmt(n->right);
break;
case ODEFER:
walktype(n, Etop);
hasdefer = 1;
walkexpr(n->left, Etop, &n->ninit);
break;
}
addtotop(n);
case OFOR:
walkstmt(n->ninit);
walkbool(n->ntest);
walkstmt(n->nincr);
walkstmt(n->nbody);
break;
if(more != N) {
n = more;
goto loop;
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 = <chan - chanrecv2
walktype(r->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)
if(expr == N || expr->op != ORECV)
goto bad;
switch(expr->op) {
default:
//dump("case", expr);
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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment