mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
delayed evaluation of var blocks
R=ken OCL=32750 CL=32753
This commit is contained in:
parent
b8732215c3
commit
dbe004efe4
7 changed files with 99 additions and 50 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 '(' ')'
|
||||
{
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue