delayed evaluation of var blocks

R=ken
OCL=32750
CL=32753
This commit is contained in:
Russ Cox 2009-08-04 16:53:06 -07:00
parent b8732215c3
commit dbe004efe4
7 changed files with 99 additions and 50 deletions

View file

@ -1200,6 +1200,7 @@ oldname(Sym *s)
// inner func is referring to var
// in outer func.
if(n->closure == N || n->closure->funcdepth != funcdepth) {
typecheck(&n, Erv);
// create new closure var.
c = nod(ONAME, N, N);
c->sym = s;
@ -1640,21 +1641,15 @@ embedded(Sym *s)
* new_name_list (type | [type] = expr_list)
*/
NodeList*
variter(NodeList *vl, Node *nt, NodeList *el)
variter(NodeList *vl, Node *t, NodeList *el)
{
int doexpr, lno;
Node *v, *e, *a;
Type *tv;
NodeList *r;
Type *t;
int doexpr, gen;
Node *v, *e;
NodeList *init;
Sym *s;
Dcl *r, *d;
t = T;
if(nt) {
typecheck(&nt, Etype);
t = nt->type;
}
r = nil;
init = nil;
doexpr = el != nil;
for(; vl; vl=vl->next) {
if(doexpr) {
@ -1663,41 +1658,53 @@ variter(NodeList *vl, Node *nt, NodeList *el)
break;
}
e = el->n;
el = el->next;
} else
e = N;
v = vl->n;
tv = t;
if(e) {
lno = lineno;
lineno = v->lineno;
typecheck(&e, Erv);
defaultlit(&e, t);
if(t)
e = typecheckconv(nil, e, t, 0);
if(tv == nil)
tv = e->type;
if(tv && tv->etype == TNIL) {
yyerror("cannot initialize %#N to untyped nil", v);
tv = nil;
}
lineno = lno;
s = v->sym;
if(dclcontext == PEXTERN || dclcontext == PFUNC) {
r = externdcl;
gen = 0;
} else {
r = autodcl;
gen = ++vargen;
pushdcl(s);
}
a = N;
if((e != N && tv != T) || funcdepth > 0)
a = nod(OAS, v, e);
dodclvar(v, tv, &r);
if(a != N)
r = list(r, a);
if(el) {
el->n = e;
el = el->next;
redeclare("variable", s);
s->def = v;
// TODO: vargen
s->offset = 0;
s->block = block;
v->op = ONAME;
v->class = dclcontext;
v->ntype = t;
v->funcdepth = funcdepth;
v->vargen = gen;
if(e != N || funcdepth > 0) {
if(funcdepth > 0)
init = list(init, nod(ODCL, v, N));
e = nod(OAS, v, e);
init = list(init, e);
if(e->right != N)
v->defn = e;
}
d = dcl();
d->dsym = s;
d->dnode = v;
d->op = ONAME;
r->back->forw = d;
r->back = d;
autoexport(s);
}
if(el != nil)
yyerror("extra expr in var dcl");
return r;
return init;
}
/*
@ -1830,3 +1837,15 @@ yes:
n->type = types[TINT];
return n;
}
void
dclchecks(void)
{
Dcl *d;
for(d=externdcl; d!=D; d=d->forw) {
if(d->op != ONAME)
continue;
typecheck(&d->dnode, Erv);
}
}

View file

@ -101,6 +101,7 @@ dumpexportconst(Sym *s)
Type *t;
n = s->def;
typecheck(&n, Erv);
if(n == N || n->op != OLITERAL)
fatal("dumpexportconst: oconst nil: %S", s);
@ -142,6 +143,7 @@ dumpexportvar(Sym *s)
Type *t;
n = s->def;
typecheck(&n, Erv);
if(n == N || n->type == T) {
yyerror("variable exported but not defined: %S", s);
return;

View file

@ -39,6 +39,7 @@ allocparams(void)
if(n->class != PAUTO)
continue;
typecheck(&n, Erv);
dowidth(n->type);
w = n->type->width;
if(n->class & PHEAP)
@ -232,7 +233,7 @@ gen(Node *n)
case OFOR:
sbreak = breakpc;
p1 = gjmp(P); // goto test
p1 = gjmp(P); // goto test
breakpc = gjmp(P); // break: goto done
scontin = continpc;
continpc = pc;
@ -263,7 +264,7 @@ gen(Node *n)
if(n->ntest != N)
if(n->ntest->ninit != nil)
genlist(n->ntest->ninit);
bgen(n->ntest, 0, p2); // if(!test) goto p2
bgen(n->ntest, 0, p2); // if(!test) goto p2
genlist(n->nbody); // then
p3 = gjmp(P); // goto done
patch(p2, pc); // else:
@ -273,7 +274,7 @@ gen(Node *n)
case OSWITCH:
sbreak = breakpc;
p1 = gjmp(P); // goto test
p1 = gjmp(P); // goto test
breakpc = gjmp(P); // break: goto done
// define break label
@ -288,7 +289,7 @@ gen(Node *n)
case OSELECT:
sbreak = breakpc;
p1 = gjmp(P); // goto test
p1 = gjmp(P); // goto test
breakpc = gjmp(P); // break: goto done
// define break label

View file

@ -933,6 +933,7 @@ NodeList* constiter(NodeList*, Node*, NodeList*);
Node* funclit0(Node*);
Node* funclit1(Node*, NodeList*);
Node* unsafenmagic(Node*, NodeList*);
void dclchecks(void);
/*
* sinit.c

View file

@ -123,10 +123,12 @@ file:
{
if(debug['f'])
frame(1);
typechecklist($4, Etop);
if(nerrors == 0)
fninit($4);
if(nsyntaxerrors == 0)
testdclstack();
dclchecks();
}
package:
@ -290,13 +292,11 @@ common_dcl:
$$ = $2;
if(yylast == LSEMIBRACE)
yyoptsemi(0);
// walkdeflist($2);
}
| LVAR '(' vardcl_list osemi ')'
{
$$ = $3;
yyoptsemi(0);
// walkdeflist($3);
}
| LVAR '(' ')'
{

View file

@ -176,6 +176,35 @@ walkdef(Node *n)
n->val = e->val;
n->type = e->type;
break;
case ONAME:
if(n->ntype != N) {
typecheck(&n->ntype, Etype);
n->type = n->ntype->type;
if(n->type == T) {
n->diag = 1;
goto ret;
}
n->ntype = N;
}
if(n->type != T)
break;
if(n->defn == N)
fatal("var without type, init: %S", n->sym);
switch(n->defn->op) {
default:
fatal("walkdef name defn");
case OAS:
typecheck(&n->defn->right, Erv);
defaultlit(&n->defn->right, T);
if((t = n->defn->right->type) == T) {
n->diag = 1;
goto ret;
}
n->type = t;
break;
}
break;
}
ret:
@ -1754,11 +1783,8 @@ checkmixed(NodeList *nl, NodeList **init)
if(!colasname(l))
goto allnew;
if(l->sym->block == block) {
if(!eqtype(l->type, t))
goto allnew;
if(l->sym->block == block)
nred++;
}
ntot++;
}

View file

@ -21,12 +21,12 @@ func main() {
{
// change of type for f
i, f, s := f3(); // GCCGO_ERROR "previous"
f, g, t := f3(); // ERROR "redeclared|redefinition"
f, g, t := f3(); // ERROR "redeclared|redefinition|cannot assign"
}
{
// change of type for i
i, f, s := f3(); // GCCGO_ERROR "previous"
j, i, t := f3(); // ERROR "redeclared|redefinition"
j, i, t := f3(); // ERROR "redeclared|redefinition|cannot assign"
}
{
// no new variables