]> Cypherpunks repositories - gostls13.git/commitdiff
gc: renamed walkdef to typecheckdef and moved from walk to typedef.
authorLuuk van Dijk <lvd@golang.org>
Fri, 3 Jun 2011 15:44:02 +0000 (17:44 +0200)
committerLuuk van Dijk <lvd@golang.org>
Fri, 3 Jun 2011 15:44:02 +0000 (17:44 +0200)
also inlined a typechecking function in dcl away.

R=rsc
CC=golang-dev
https://golang.org/cl/4550115

src/cmd/gc/dcl.c
src/cmd/gc/go.h
src/cmd/gc/lex.c
src/cmd/gc/typecheck.c
src/cmd/gc/walk.c

index 78c676346fa1545fb08822f08dd7adbba3e4c9e9..83be82f92fe5e47697582b399eb3df46b6528930 100644 (file)
@@ -438,20 +438,6 @@ newtype(Sym *s)
        return t;
 }
 
-/*
- * type check top level declarations
- */
-void
-dclchecks(void)
-{
-       NodeList *l;
-
-       for(l=externdcl; l; l=l->next) {
-               if(l->n->op != ONAME)
-                       continue;
-               typecheck(&l->n, Erv);
-       }
-}
 
 /*
  * := declarations
index f5c0443f84b9b20742166d84287c13000771f480..d379a0d88a96ff8f60cca24d5e9ab8b1ce8f9fee 100644 (file)
@@ -862,7 +862,6 @@ NodeList*   checkarglist(NodeList *all, int input);
 Node*  colas(NodeList *left, NodeList *right);
 void   colasdefn(NodeList *left, Node *defn);
 NodeList*      constiter(NodeList *vl, Node *t, NodeList *cl);
-void   dclchecks(void);
 Node*  dclname(Sym *s);
 void   declare(Node *n, int ctxt);
 Type*  dostruct(NodeList *l, int et);
@@ -1166,6 +1165,11 @@ int      exportassignok(Type *t, char *desc);
 int    islvalue(Node *n);
 Node*  typecheck(Node **np, int top);
 void   typechecklist(NodeList *l, int top);
+Node*  typecheckdef(Node *n);
+void   resumetypecopy(void);
+void   copytype(Node *n, Type *t);
+void   defertypecopy(Node *n, Type *t);
+void   queuemethod(Node *n);
 
 /*
  *     unsafe.c
@@ -1177,15 +1181,10 @@ Node*   unsafenmagic(Node *n);
  */
 Node*  callnew(Type *t);
 Node*  chanfn(char *name, int n, Type *t);
-void   copytype(Node *n, Type *t);
-void   defertypecopy(Node *n, Type *t);
 Node*  mkcall(char *name, Type *t, NodeList **init, ...);
 Node*  mkcall1(Node *fn, Type *t, NodeList **init, ...);
-void   queuemethod(Node *n);
-void   resumetypecopy(void);
 int    vmatch1(Node *l, Node *r);
 void   walk(Node *fn);
-Node*  walkdef(Node *n);
 void   walkexpr(Node **np, NodeList **init);
 void   walkexprlist(NodeList *l, NodeList **init);
 void   walkexprlistsafe(NodeList *l, NodeList **init);
index 5e2f73fc5ab22840d7b437e5dd01ef20533d90a2..0c36e53a353bf9536ff3bd74dac9be0ce47543d3 100644 (file)
@@ -274,7 +274,9 @@ main(int argc, char *argv[])
                        funccompile(l->n, 1);
        }
 
-       dclchecks();
+       for(l=externdcl; l; l=l->next)
+               if(l->n->op == ONAME)
+                       typecheck(&l->n, Erv);
 
        if(nerrors)
                errorexit();
index 44d08352da7420ff82a4207d727470f77025a89d..04dc1a5077d6d489089481de09fad775d45f199d 100644 (file)
@@ -8,7 +8,6 @@
  * evaluates compile time constants.
  * marks variables that escape the local frame.
  * rewrites n->op to be more specific in some cases.
- * sets n->walk to walking function.
  */
 
 #include "go.h"
@@ -33,6 +32,8 @@ static void   stringtoarraylit(Node**);
 static Node*   resolve(Node*);
 static Type*   getforwtype(Node*);
 
+static NodeList*       typecheckdefstack;
+
 /*
  * resolve ONONAME to definition, if any.
  */
@@ -159,7 +160,7 @@ typecheck(Node **np, int top)
                if(n->op == OTYPE && (ft = getforwtype(n->ntype)) != T)
                        defertypecopy(n, ft);
 
-               walkdef(n);
+               typecheckdef(n);
                n->realtype = n->type;
                if(n->op == ONONAME)
                        goto error;
@@ -2523,3 +2524,294 @@ getforwtype(Node *n)
                }
        }
 }
+
+static int ntypecheckdeftype;
+static NodeList *methodqueue;
+
+static void
+domethod(Node *n)
+{
+       Node *nt;
+
+       nt = n->type->nname;
+       typecheck(&nt, Etype);
+       if(nt->type == T) {
+               // type check failed; leave empty func
+               n->type->etype = TFUNC;
+               n->type->nod = N;
+               return;
+       }
+       *n->type = *nt->type;
+       n->type->nod = N;
+       checkwidth(n->type);
+}
+
+typedef struct NodeTypeList NodeTypeList;
+struct NodeTypeList {
+       Node *n;
+       Type *t;
+       NodeTypeList *next;
+};
+
+static NodeTypeList    *dntq;
+static NodeTypeList    *dntend;
+
+void
+defertypecopy(Node *n, Type *t)
+{
+       NodeTypeList *ntl;
+
+       if(n == N || t == T)
+               return;
+
+       ntl = mal(sizeof *ntl);
+       ntl->n = n;
+       ntl->t = t;
+       ntl->next = nil;
+
+       if(dntq == nil)
+               dntq = ntl;
+       else
+               dntend->next = ntl;
+
+       dntend = ntl;
+}
+
+void
+resumetypecopy(void)
+{
+       NodeTypeList *l;
+
+       for(l=dntq; l; l=l->next)
+               copytype(l->n, l->t);
+}
+
+void
+copytype(Node *n, Type *t)
+{
+       *n->type = *t;
+
+       t = n->type;
+       t->sym = n->sym;
+       t->local = n->local;
+       t->vargen = n->vargen;
+       t->siggen = 0;
+       t->method = nil;
+       t->nod = N;
+       t->printed = 0;
+       t->deferwidth = 0;
+}
+
+static void
+typecheckdeftype(Node *n)
+{
+       int maplineno, embedlineno, lno;
+       Type *t;
+       NodeList *l;
+
+       ntypecheckdeftype++;
+       lno = lineno;
+       setlineno(n);
+       n->type->sym = n->sym;
+       n->typecheck = 1;
+       typecheck(&n->ntype, Etype);
+       if((t = n->ntype->type) == T) {
+               n->diag = 1;
+               goto ret;
+       }
+       if(n->type == T) {
+               n->diag = 1;
+               goto ret;
+       }
+
+       maplineno = n->type->maplineno;
+       embedlineno = n->type->embedlineno;
+
+       // copy new type and clear fields
+       // that don't come along.
+       // anything zeroed here must be zeroed in
+       // typedcl2 too.
+       copytype(n, t);
+
+       // double-check use of type as map key.
+       if(maplineno) {
+               lineno = maplineno;
+               maptype(n->type, types[TBOOL]);
+       }
+       if(embedlineno) {
+               lineno = embedlineno;
+               if(isptr[t->etype])
+                       yyerror("embedded type cannot be a pointer");
+       }
+
+ret:
+       lineno = lno;
+
+       // if there are no type definitions going on, it's safe to
+       // try to resolve the method types for the interfaces
+       // we just read.
+       if(ntypecheckdeftype == 1) {
+               while((l = methodqueue) != nil) {
+                       methodqueue = nil;
+                       for(; l; l=l->next)
+                               domethod(l->n);
+               }
+       }
+       ntypecheckdeftype--;
+}
+
+void
+queuemethod(Node *n)
+{
+       if(ntypecheckdeftype == 0) {
+               domethod(n);
+               return;
+       }
+       methodqueue = list(methodqueue, n);
+}
+
+Node*
+typecheckdef(Node *n)
+{
+       int lno;
+       Node *e;
+       Type *t;
+       NodeList *l;
+
+       lno = lineno;
+       setlineno(n);
+
+       if(n->op == ONONAME) {
+               if(!n->diag) {
+                       n->diag = 1;
+                       if(n->lineno != 0)
+                               lineno = n->lineno;
+                       yyerror("undefined: %S", n->sym);
+               }
+               return n;
+       }
+
+       if(n->walkdef == 1)
+               return n;
+
+       l = mal(sizeof *l);
+       l->n = n;
+       l->next = typecheckdefstack;
+       typecheckdefstack = l;
+
+       if(n->walkdef == 2) {
+               flusherrors();
+               print("typecheckdef loop:");
+               for(l=typecheckdefstack; l; l=l->next)
+                       print(" %S", l->n->sym);
+               print("\n");
+               fatal("typecheckdef loop");
+       }
+       n->walkdef = 2;
+
+       if(n->type != T || n->sym == S) // builtin or no name
+               goto ret;
+
+       switch(n->op) {
+       default:
+               fatal("typecheckdef %O", n->op);
+
+       case OLITERAL:
+               if(n->ntype != N) {
+                       typecheck(&n->ntype, Etype);
+                       n->type = n->ntype->type;
+                       n->ntype = N;
+                       if(n->type == T) {
+                               n->diag = 1;
+                               goto ret;
+                       }
+               }
+               e = n->defn;
+               n->defn = N;
+               if(e == N) {
+                       lineno = n->lineno;
+                       dump("typecheckdef nil defn", n);
+                       yyerror("xxx");
+               }
+               typecheck(&e, Erv | Eiota);
+               if(e->type != T && e->op != OLITERAL) {
+                       yyerror("const initializer must be constant");
+                       goto ret;
+               }
+               if(isconst(e, CTNIL)) {
+                       yyerror("const initializer cannot be nil");
+                       goto ret;
+               }
+               t = n->type;
+               if(t != T) {
+                       if(!okforconst[t->etype]) {
+                               yyerror("invalid constant type %T", t);
+                               goto ret;
+                       }
+                       if(!isideal(e->type) && !eqtype(t, e->type)) {
+                               yyerror("cannot use %+N as type %T in const initializer", e, t);
+                               goto ret;
+                       }
+                       convlit(&e, t);
+               }
+               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;
+                       }
+               }
+               if(n->type != T)
+                       break;
+               if(n->defn == N) {
+                       if(n->etype != 0)       // like OPRINTN
+                               break;
+                       if(nerrors > 0) {
+                               // Can have undefined variables in x := foo
+                               // that make x have an n->ndefn == nil.
+                               // If there are other errors anyway, don't
+                               // bother adding to the noise.
+                               break;
+                       }
+                       fatal("var without type, init: %S", n->sym);
+               }
+               if(n->defn->op == ONAME) {
+                       typecheck(&n->defn, Erv);
+                       n->type = n->defn->type;
+                       break;
+               }
+               typecheck(&n->defn, Etop);      // fills in n->type
+               break;
+
+       case OTYPE:
+               if(curfn)
+                       defercheckwidth();
+               n->walkdef = 1;
+               n->type = typ(TFORW);
+               n->type->sym = n->sym;
+               typecheckdeftype(n);
+               if(curfn)
+                       resumecheckwidth();
+               break;
+
+       case OPACK:
+               // nothing to see here
+               break;
+       }
+
+ret:
+       if(typecheckdefstack->n != n)
+               fatal("typecheckdefstack mismatch");
+       l = typecheckdefstack;
+       typecheckdefstack = l->next;
+
+       lineno = lno;
+       n->walkdef = 1;
+       return n;
+}
index ccc65ff2158e6a52ec38112283f118ae2844c338..65a504bff5f338b57af9054411854bd3e57a4b82 100644 (file)
@@ -21,8 +21,6 @@ static        Node*   addstr(Node*, NodeList**);
 static Node*   appendslice(Node*, NodeList**);
 static Node*   append(Node*, NodeList**);
 
-static NodeList*       walkdefstack;
-
 // can this code branch reach the end
 // without an unconditional RETURN
 // this is hard, so it is conservative
@@ -100,296 +98,6 @@ walk(Node *fn)
        }
 }
 
-static int nwalkdeftype;
-static NodeList *methodqueue;
-
-static void
-domethod(Node *n)
-{
-       Node *nt;
-
-       nt = n->type->nname;
-       typecheck(&nt, Etype);
-       if(nt->type == T) {
-               // type check failed; leave empty func
-               n->type->etype = TFUNC;
-               n->type->nod = N;
-               return;
-       }
-       *n->type = *nt->type;
-       n->type->nod = N;
-       checkwidth(n->type);
-}
-
-typedef struct NodeTypeList NodeTypeList;
-struct NodeTypeList {
-       Node *n;
-       Type *t;
-       NodeTypeList *next;
-};
-
-static NodeTypeList    *dntq;
-static NodeTypeList    *dntend;
-
-void
-defertypecopy(Node *n, Type *t)
-{
-       NodeTypeList *ntl;
-
-       if(n == N || t == T)
-               return;
-
-       ntl = mal(sizeof *ntl);
-       ntl->n = n;
-       ntl->t = t;
-       ntl->next = nil;
-
-       if(dntq == nil)
-               dntq = ntl;
-       else
-               dntend->next = ntl;
-
-       dntend = ntl;
-}
-
-void
-resumetypecopy(void)
-{
-       NodeTypeList *l;
-
-       for(l=dntq; l; l=l->next)
-               copytype(l->n, l->t);
-}
-
-void
-copytype(Node *n, Type *t)
-{
-       *n->type = *t;
-
-       t = n->type;
-       t->sym = n->sym;
-       t->local = n->local;
-       t->vargen = n->vargen;
-       t->siggen = 0;
-       t->method = nil;
-       t->nod = N;
-       t->printed = 0;
-       t->deferwidth = 0;
-}
-
-static void
-walkdeftype(Node *n)
-{
-       int maplineno, embedlineno, lno;
-       Type *t;
-       NodeList *l;
-
-       nwalkdeftype++;
-       lno = lineno;
-       setlineno(n);
-       n->type->sym = n->sym;
-       n->typecheck = 1;
-       typecheck(&n->ntype, Etype);
-       if((t = n->ntype->type) == T) {
-               n->diag = 1;
-               goto ret;
-       }
-       if(n->type == T) {
-               n->diag = 1;
-               goto ret;
-       }
-
-       maplineno = n->type->maplineno;
-       embedlineno = n->type->embedlineno;
-
-       // copy new type and clear fields
-       // that don't come along.
-       // anything zeroed here must be zeroed in
-       // typedcl2 too.
-       copytype(n, t);
-
-       // double-check use of type as map key.
-       if(maplineno) {
-               lineno = maplineno;
-               maptype(n->type, types[TBOOL]);
-       }
-       if(embedlineno) {
-               lineno = embedlineno;
-               if(isptr[t->etype])
-                       yyerror("embedded type cannot be a pointer");
-       }
-
-ret:
-       lineno = lno;
-
-       // if there are no type definitions going on, it's safe to
-       // try to resolve the method types for the interfaces
-       // we just read.
-       if(nwalkdeftype == 1) {
-               while((l = methodqueue) != nil) {
-                       methodqueue = nil;
-                       for(; l; l=l->next)
-                               domethod(l->n);
-               }
-       }
-       nwalkdeftype--;
-}
-
-void
-queuemethod(Node *n)
-{
-       if(nwalkdeftype == 0) {
-               domethod(n);
-               return;
-       }
-       methodqueue = list(methodqueue, n);
-}
-
-Node*
-walkdef(Node *n)
-{
-       int lno;
-       Node *e;
-       Type *t;
-       NodeList *l;
-
-       lno = lineno;
-       setlineno(n);
-
-       if(n->op == ONONAME) {
-               if(!n->diag) {
-                       n->diag = 1;
-                       if(n->lineno != 0)
-                               lineno = n->lineno;
-                       yyerror("undefined: %S", n->sym);
-               }
-               return n;
-       }
-
-       if(n->walkdef == 1)
-               return n;
-
-       l = mal(sizeof *l);
-       l->n = n;
-       l->next = walkdefstack;
-       walkdefstack = l;
-
-       if(n->walkdef == 2) {
-               flusherrors();
-               print("walkdef loop:");
-               for(l=walkdefstack; l; l=l->next)
-                       print(" %S", l->n->sym);
-               print("\n");
-               fatal("walkdef loop");
-       }
-       n->walkdef = 2;
-
-       if(n->type != T || n->sym == S) // builtin or no name
-               goto ret;
-
-       switch(n->op) {
-       default:
-               fatal("walkdef %O", n->op);
-
-       case OLITERAL:
-               if(n->ntype != N) {
-                       typecheck(&n->ntype, Etype);
-                       n->type = n->ntype->type;
-                       n->ntype = N;
-                       if(n->type == T) {
-                               n->diag = 1;
-                               goto ret;
-                       }
-               }
-               e = n->defn;
-               n->defn = N;
-               if(e == N) {
-                       lineno = n->lineno;
-                       dump("walkdef nil defn", n);
-                       yyerror("xxx");
-               }
-               typecheck(&e, Erv | Eiota);
-               if(e->type != T && e->op != OLITERAL) {
-                       yyerror("const initializer must be constant");
-                       goto ret;
-               }
-               if(isconst(e, CTNIL)) {
-                       yyerror("const initializer cannot be nil");
-                       goto ret;
-               }
-               t = n->type;
-               if(t != T) {
-                       if(!okforconst[t->etype]) {
-                               yyerror("invalid constant type %T", t);
-                               goto ret;
-                       }
-                       if(!isideal(e->type) && !eqtype(t, e->type)) {
-                               yyerror("cannot use %+N as type %T in const initializer", e, t);
-                               goto ret;
-                       }
-                       convlit(&e, t);
-               }
-               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;
-                       }
-               }
-               if(n->type != T)
-                       break;
-               if(n->defn == N) {
-                       if(n->etype != 0)       // like OPRINTN
-                               break;
-                       if(nerrors > 0) {
-                               // Can have undefined variables in x := foo
-                               // that make x have an n->ndefn == nil.
-                               // If there are other errors anyway, don't
-                               // bother adding to the noise.
-                               break;
-                       }
-                       fatal("var without type, init: %S", n->sym);
-               }
-               if(n->defn->op == ONAME) {
-                       typecheck(&n->defn, Erv);
-                       n->type = n->defn->type;
-                       break;
-               }
-               typecheck(&n->defn, Etop);      // fills in n->type
-               break;
-
-       case OTYPE:
-               if(curfn)
-                       defercheckwidth();
-               n->walkdef = 1;
-               n->type = typ(TFORW);
-               n->type->sym = n->sym;
-               walkdeftype(n);
-               if(curfn)
-                       resumecheckwidth();
-               break;
-
-       case OPACK:
-               // nothing to see here
-               break;
-       }
-
-ret:
-       if(walkdefstack->n != n)
-               fatal("walkdefstack mismatch");
-       l = walkdefstack;
-       walkdefstack = l->next;
-
-       lineno = lno;
-       n->walkdef = 1;
-       return n;
-}
 
 void
 walkstmtlist(NodeList *l)