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
This commit is contained in:
Russ Cox 2009-07-10 16:29:26 -07:00
parent ed124a971e
commit 0dadc4fe4f
7 changed files with 412 additions and 494 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

File diff suppressed because it is too large Load Diff