]> Cypherpunks repositories - gostls13.git/commitdiff
delayed evaluation of var blocks
authorRuss Cox <rsc@golang.org>
Tue, 4 Aug 2009 23:53:06 +0000 (16:53 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 4 Aug 2009 23:53:06 +0000 (16:53 -0700)
R=ken
OCL=32750
CL=32753

src/cmd/gc/dcl.c
src/cmd/gc/export.c
src/cmd/gc/gen.c
src/cmd/gc/go.h
src/cmd/gc/go.y
src/cmd/gc/walk.c
test/declbad.go

index d1802c83d3e317199f1aba81b503b459c547ceb3..3b8e67d15a951e51f9b1cd478d453edcc19da32e 100644 (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;
-
-       t = T;
-       if(nt) {
-               typecheck(&nt, Etype);
-               t = nt->type;
-       }
+       int doexpr, gen;
+       Node *v, *e;
+       NodeList *init;
+       Sym *s;
+       Dcl *r, *d;
 
-       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);
+       }
+}
index e7ff59bb5b81269e13af836ece6f62d0bcfca426..74df553632a2919c8c6bd6e0fd120101854ee499 100644 (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;
index f87b70e95cbb131dfc7109bdbda3356aed67d104..5fab59cdfaba392bf9e9d52441dd22fb4d989d44 100644 (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
index 71d34682b61924c2c0b754abe878da6cce3cff2e..db757fa4e776f63d6dd2cbe8ce6602460ccdc787 100644 (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
index 4e280c17780783cfb68941c90f2db69b7f139e53..f048c29d146f9f80b70d35b156de7ff04e1ddd9c 100644 (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 '(' ')'
        {
index a77163323c711c132f325ebf5ee0a7048c674a30..43cdcbb475af1baa4f740737aa95ed23a6e6e5bf 100644 (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++;
        }
 
index 7f6e56d7e44e42ee9ff54fbd9e08446681c01565..78f8c8d54801aca921a3b22e4a70daa0a5d93e56 100644 (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