]> Cypherpunks repositories - gostls13.git/commitdiff
gc: changes in export format in preparation of inlining.
authorLuuk van Dijk <lvd@golang.org>
Mon, 5 Dec 2011 19:40:19 +0000 (14:40 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 5 Dec 2011 19:40:19 +0000 (14:40 -0500)
Includes minimal change to gcimporter to keep it working,

R=rsc, gri
CC=golang-dev
https://golang.org/cl/5431046

src/cmd/gc/dcl.c
src/cmd/gc/export.c
src/cmd/gc/fmt.c
src/cmd/gc/go.h
src/cmd/gc/go.y
src/cmd/gc/init.c
src/cmd/gc/lex.c
src/cmd/gc/subr.c
src/cmd/gc/typecheck.c
src/pkg/exp/types/gcimporter.go

index a84b27c9ba7446b3e6dcb45ba3894da327ecdc68..c61306ad4c8d57ce330fb7bc1e366586daa6b73d 100644 (file)
@@ -8,6 +8,7 @@
 #include       "y.tab.h"
 
 static void    funcargs(Node*);
+static void    funcargs2(Type*);
 
 static int
 dflag(void)
@@ -547,13 +548,6 @@ ifacedcl(Node *n)
 void
 funchdr(Node *n)
 {
-
-       if(n->nname != N) {
-               n->nname->op = ONAME;
-               declare(n->nname, PFUNC);
-               n->nname->defn = n;
-       }
-
        // change the declaration context from extern to auto
        if(funcdepth == 0 && dclcontext != PEXTERN)
                fatal("funchdr: dclcontext");
@@ -564,10 +558,13 @@ funchdr(Node *n)
 
        n->outer = curfn;
        curfn = n;
+
        if(n->nname)
                funcargs(n->nname->ntype);
-       else
+       else if (n->ntype)
                funcargs(n->ntype);
+       else
+               funcargs2(n->type);
 }
 
 static void
@@ -582,11 +579,11 @@ funcargs(Node *nt)
 
        // declare the receiver and in arguments.
        // no n->defn because type checking of func header
-       // will fill in the types before we can demand them.
+       // will not fill in the types until later
        if(nt->left != N) {
                n = nt->left;
                if(n->op != ODCLFIELD)
-                       fatal("funcargs1 %O", n->op);
+                       fatal("funcargs receiver %O", n->op);
                if(n->left != N) {
                        n->left->op = ONAME;
                        n->left->ntype = n->right;
@@ -596,7 +593,7 @@ funcargs(Node *nt)
        for(l=nt->list; l; l=l->next) {
                n = l->n;
                if(n->op != ODCLFIELD)
-                       fatal("funcargs2 %O", n->op);
+                       fatal("funcargs in %O", n->op);
                if(n->left != N) {
                        n->left->op = ONAME;
                        n->left->ntype = n->right;
@@ -609,7 +606,7 @@ funcargs(Node *nt)
        for(l=nt->rlist; l; l=l->next) {
                n = l->n;
                if(n->op != ODCLFIELD)
-                       fatal("funcargs3 %O", n->op);
+                       fatal("funcargs out %O", n->op);
                if(n->left != N) {
                        n->left->op = ONAME;
                        n->left->ntype = n->right;
@@ -627,6 +624,48 @@ funcargs(Node *nt)
        }
 }
 
+/*
+ * Same as funcargs, except run over an already constructed TFUNC.
+ * This happens during import, where the hidden_fndcl rule has
+ * used functype directly to parse the function's type.
+ */
+static void
+funcargs2(Type *t)
+{
+       Type *ft;
+       Node *n;
+
+       if(t->etype != TFUNC)
+               fatal("funcargs2 %T", t);
+       
+       if(t->thistuple)
+               for(ft=getthisx(t)->type; ft; ft=ft->down) {
+                       if(!ft->nname || !ft->nname->sym)
+                               continue;
+                       n = newname(ft->nname->sym);
+                       n->type = ft->type;
+                       declare(n, PPARAM);
+               }
+
+       if(t->intuple)
+               for(ft=getinargx(t)->type; ft; ft=ft->down) {
+                       if(!ft->nname || !ft->nname->sym)
+                               continue;
+                       n = newname(ft->nname->sym);
+                       n->type = ft->type;
+                       declare(n, PPARAM);
+               }
+
+       if(t->outtuple)
+               for(ft=getoutargx(t)->type; ft; ft=ft->down) {
+                       if(!ft->nname || !ft->nname->sym)
+                               continue;
+                       n = newname(ft->nname->sym);
+                       n->type = ft->type;
+                       declare(n, PPARAMOUT);
+               }
+}
+
 /*
  * finish the body.
  * called in auto-declaration context.
@@ -654,7 +693,7 @@ typedcl0(Sym *s)
 {
        Node *n;
 
-       n = dclname(s);
+       n = newname(s);
        n->op = OTYPE;
        declare(n, dclcontext);
        return n;
@@ -740,8 +779,6 @@ structfield(Node *n)
                f->nname = n->left;
                f->embedded = n->embedded;
                f->sym = f->nname->sym;
-               if(importpkg && !exportname(f->sym->name))
-                       f->sym = pkglookup(f->sym->name, structpkg);
        }
 
        lineno = lno;
@@ -778,8 +815,12 @@ tostruct(NodeList *l)
        Type *t, *f, **tp;
        t = typ(TSTRUCT);
 
-       for(tp = &t->type; l; l=l->next,tp = &(*tp)->down)
-               *tp = structfield(l->n);
+       for(tp = &t->type; l; l=l->next) {
+               f = structfield(l->n);
+
+               *tp = f;
+               tp = &f->down;
+       }
 
        for(f=t->type; f && !t->broke; f=f->down)
                if(f->broke)
@@ -803,7 +844,7 @@ tofunargs(NodeList *l)
 
        for(tp = &t->type; l; l=l->next) {
                f = structfield(l->n);
-
+               f->funarg = 1;
                // esc.c needs to find f given a PPARAM to add the tag.
                if(l->n->left && l->n->left->class == PPARAM)
                        l->n->left->paramfld = f;
@@ -944,7 +985,10 @@ embedded(Sym *s)
                *utfrune(name, CenterDot) = 0;
        }
 
-       n = newname(lookup(name));
+       if(exportname(name) || s->pkg == builtinpkg)  // old behaviour, tests pass, but is it correct?
+               n = newname(lookup(name));
+       else
+               n = newname(pkglookup(name, s->pkg));
        n = nod(ODCLFIELD, n, oldname(s));
        n->embedded = 1;
        return n;
@@ -1009,6 +1053,17 @@ checkarglist(NodeList *all, int input)
                        t = n;
                        n = N;
                }
+
+               // during import l->n->op is OKEY, but l->n->left->sym == S
+               // means it was a '?', not that it was
+               // a lone type This doesn't matter for the exported
+               // declarations, which are parsed by rules that don't
+               // use checkargs, but can happen for func literals in
+               // the inline bodies.
+               // TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.c prints _ instead of ?
+               if(importpkg && n->sym == S)
+                       n = N;
+
                if(n != N && n->sym == S) {
                        t = n;
                        n = N;
@@ -1137,7 +1192,6 @@ methodsym(Sym *nsym, Type *t0, int iface)
        else
                p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
        s = pkglookup(p, s->pkg);
-       //print("methodsym:%s -> %+S\n", p, s);
        free(p);
        return s;
 
@@ -1174,7 +1228,11 @@ methodname1(Node *n, Node *t)
                p = smprint("(%s%S).%S", star, t->sym, n->sym);
        else
                p = smprint("%S.%S", t->sym, n->sym);
-       n = newname(pkglookup(p, t->sym->pkg));
+
+       if(exportname(t->sym->name))
+               n = newname(lookup(p));
+       else
+               n = newname(pkglookup(p, t->sym->pkg));
        free(p);
        return n;
 }
@@ -1234,8 +1292,6 @@ addmethod(Sym *sf, Type *t, int local)
        }
 
        pa = f;
-       if(importpkg && !exportname(sf->name))
-               sf = pkglookup(sf->name, importpkg);
 
        n = nod(ODCLFIELD, newname(sf), N);
        n->type = t;
@@ -1258,10 +1314,16 @@ addmethod(Sym *sf, Type *t, int local)
                return;
        }
 
+       f = structfield(n);
+
+       // during import unexported method names should be in the type's package
+       if(importpkg && f->sym && !exportname(f->sym->name) && f->sym->pkg != structpkg)
+               fatal("imported method name %+S in wrong package %s\n", f->sym, structpkg->name);
+
        if(d == T)
-               pa->method = structfield(n);
+               pa->method = f;
        else
-               d->down = structfield(n);
+               d->down = f;
        return;
 }
 
index 6938f0488907ddb5ecd773477b65d8061bc6a96d..5951aa2e8815c2cd9a58bb55c0effd668851065b 100644 (file)
@@ -7,11 +7,9 @@
 #include       "go.h"
 #include       "y.tab.h"
 
-static void    dumpsym(Sym*);
-static void    dumpexporttype(Type*);
-static void    dumpexportvar(Sym*);
-static void    dumpexportconst(Sym*);
+static void    dumpexporttype(Type*);
 
+// Mark n's symbol as exported
 void
 exportsym(Node *n)
 {
@@ -27,6 +25,7 @@ exportsym(Node *n)
        exportlist = list(exportlist, n);
 }
 
+// Mark n's symbol as package-local
 static void
 packagesym(Node *n)
 {
@@ -178,7 +177,7 @@ dumpexporttype(Type *t)
        Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
        for(i=0; i<n; i++) {
                f = m[i];
-               Bprint(bout, "\tfunc (%#T) %#hS%#hT\n", getthisx(f->type)->type, f->sym, f->type);
+               Bprint(bout, "\tfunc (%#T) %#hhS%#hT\n", getthisx(f->type)->type, f->sym, f->type);
        }
 }
 
@@ -200,15 +199,18 @@ dumpsym(Sym *s)
        default:
                yyerror("unexpected export symbol: %O %S", s->def->op, s);
                break;
+
        case OLITERAL:
                dumpexportconst(s);
                break;
+
        case OTYPE:
                if(s->def->type->etype == TFORW)
                        yyerror("export of incomplete type %S", s);
                else
                        dumpexporttype(s->def->type);
                break;
+
        case ONAME:
                dumpexportvar(s);
                break;
@@ -286,12 +288,25 @@ pkgtype(Sym *s)
        return s->def->type;
 }
 
-static int
-mypackage(Sym *s)
+void
+importimport(Sym *s, Strlit *z)
 {
-       // we import all definitions for runtime.
-       // lowercase ones can only be used by the compiler.
-       return s->pkg == localpkg || s->pkg == runtimepkg;
+       // Informational: record package name
+       // associated with import path, for use in
+       // human-readable messages.
+       Pkg *p;
+
+       p = mkpkg(z);
+       if(p->name == nil) {
+               p->name = s->name;
+               pkglookup(s->name, nil)->npkg++;
+       } else if(strcmp(p->name, s->name) != 0)
+               yyerror("conflicting names %s and %s for package \"%Z\"", p->name, s->name, p->path);
+       
+       if(!incannedimport && myimportpath != nil && strcmp(z->s, myimportpath) == 0) {
+               yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, z);
+               errorexit();
+       }
 }
 
 void
@@ -299,19 +314,17 @@ importconst(Sym *s, Type *t, Node *n)
 {
        Node *n1;
 
-       if(!exportname(s->name) && !mypackage(s))
-               return;
        importsym(s, OLITERAL);
        convlit(&n, t);
-       if(s->def != N) {
-               // TODO: check if already the same.
+
+       if(s->def != N)  // TODO: check if already the same.
                return;
-       }
 
        if(n->op != OLITERAL) {
                yyerror("expression must be a constant");
                return;
        }
+
        if(n->sym != S) {
                n1 = nod(OXXX, N, N);
                *n1 = *n;
@@ -325,13 +338,10 @@ importconst(Sym *s, Type *t, Node *n)
 }
 
 void
-importvar(Sym *s, Type *t, int ctxt)
+importvar(Sym *s, Type *t)
 {
        Node *n;
 
-       if(!exportname(s->name) && !initname(s->name) && !mypackage(s))
-               return;
-
        importsym(s, ONAME);
        if(s->def != N && s->def->op == ONAME) {
                if(eqtype(t, s->def->type))
@@ -340,7 +350,7 @@ importvar(Sym *s, Type *t, int ctxt)
        }
        n = newname(s);
        n->type = t;
-       declare(n, ctxt);
+       declare(n, PEXTERN);
 
        if(debug['E'])
                print("import var %S %lT\n", s, t);
@@ -351,38 +361,25 @@ importtype(Type *pt, Type *t)
 {
        Node *n;
 
-       if(pt != T && t != T) {
-               // override declaration in unsafe.go for Pointer.
-               // there is no way in Go code to define unsafe.Pointer
-               // so we have to supply it.
-               if(incannedimport &&
-                  strcmp(importpkg->name, "unsafe") == 0 &&
-                  strcmp(pt->nod->sym->name, "Pointer") == 0) {
-                       t = types[TUNSAFEPTR];
-               }
-
-               if(pt->etype == TFORW) {
-                       n = pt->nod;
-                       copytype(pt->nod, t);
-                       // unzero nod
-                       pt->nod = n;
-                       
-                       pt->sym->lastlineno = parserline();
-                       declare(n, PEXTERN);
-                       
-                       checkwidth(pt);
-               } else if(!eqtype(pt->orig, t))
-                       yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t);
+       // override declaration in unsafe.go for Pointer.
+       // there is no way in Go code to define unsafe.Pointer
+       // so we have to supply it.
+       if(incannedimport &&
+          strcmp(importpkg->name, "unsafe") == 0 &&
+          strcmp(pt->nod->sym->name, "Pointer") == 0) {
+               t = types[TUNSAFEPTR];
        }
 
+       if(pt->etype == TFORW) {
+               n = pt->nod;
+               copytype(pt->nod, t);
+               pt->nod = n;            // unzero nod
+               pt->sym->lastlineno = parserline();
+               declare(n, PEXTERN);
+               checkwidth(pt);
+       } else if(!eqtype(pt->orig, t))
+               yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t);
+
        if(debug['E'])
                print("import type %T %lT\n", pt, t);
 }
-
-void
-importmethod(Sym *s, Type *t)
-{
-       checkwidth(t);
-       addmethod(s, t, 0);
-}
-
index b32aaaab202306382d3c35799dc759e6c644b9c1..86711869d86668f2f2c6bc67d30713fedd3d941c 100644 (file)
@@ -24,7 +24,7 @@
 //     %S Sym*         Symbols
 //             Flags: +,- #: mode (see below)
 //                     "%hS"   unqualified identifier in any mode
-//                     "%hhS"  strip type qualifier off of method name
+//                     "%hhS"  in export mode: unqualified identifier if exported, qualified if not
 //
 //     %T Type*        Types
 //             Flags: +,- #: mode (see below)
@@ -341,6 +341,9 @@ Jconv(Fmt *fp)
        if(n->implicit != 0)
                fmtprint(fp, " implicit(%d)", n->implicit);
 
+       if(n->embedded != 0)
+               fmtprint(fp, " embedded(%d)", n->embedded);
+
        if(!c && n->used != 0)
                fmtprint(fp, " used(%d)", n->used);
        return 0;
@@ -488,7 +491,7 @@ symfmt(Fmt *fp, Sym *s)
                        if(s->pkg == localpkg)
                                return fmtstrcpy(fp, s->name);
                        // If the name was used by multiple packages, display the full path,
-                       if(pkglookup(s->pkg->name, nil)->npkg > 1)
+                       if(s->pkg->name && pkglookup(s->pkg->name, nil)->npkg > 1)
                                return fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name);
                        return fmtprint(fp, "%s.%s", s->pkg->name, s->name);
                case FDbg:
@@ -502,11 +505,19 @@ symfmt(Fmt *fp, Sym *s)
                }
        }
 
-       if(fp->flags&FmtByte) {
+       if(fp->flags&FmtByte) {  // FmtByte (hh) implies FmtShort (h)
                // skip leading "type." in method name
                p = utfrrune(s->name, '.');
                if(p)
-                       return fmtstrcpy(fp, p+1);
+                       p++;
+               else
+                       p = s->name;
+
+               // exportname needs to see the name without the prefix too.
+               if((fmtmode == FExp && !exportname(p)) || fmtmode == FDbg)
+                       return fmtprint(fp, "@\"%Z\".%s", s->pkg->path, p);
+
+               return fmtstrcpy(fp, p);
        }
 
        return fmtstrcpy(fp, s->name);
@@ -672,9 +683,9 @@ typefmt(Fmt *fp, Type *t)
                        fmtstrcpy(fp, "struct {");
                        for(t1=t->type; t1!=T; t1=t1->down)
                                if(t1->down)
-                                       fmtprint(fp, " %T;", t1);
+                                       fmtprint(fp, " %lT;", t1);
                                else
-                                       fmtprint(fp, " %T ", t1);
+                                       fmtprint(fp, " %lT ", t1);
                        fmtstrcpy(fp, "}");
                }
                return 0;
@@ -682,21 +693,22 @@ typefmt(Fmt *fp, Type *t)
        case TFIELD:
                if(!(fp->flags&FmtShort)) {
                        s = t->sym;
-                       switch(fmtmode) {
-                       case FErr:
-                       case FExp:
-                               // Take the name from the original, lest we substituted it with .anon%d
-                               if (t->nname)
-                                       s = t->nname->orig->sym;
-
-                               if((s == S || t->embedded)) {
+                       // Take the name from the original, lest we substituted it with .anon%d
+                       if (t->nname && (fmtmode == FErr || fmtmode == FExp))
+                               s = t->nname->orig->sym;
+                       
+                       if(s != S && !t->embedded) {
+                               if(fp->flags&FmtLong)
+                                       fmtprint(fp, "%hhS ", s);  // qualify non-exported names (used on structs, not on funarg)
+                               else 
+                                       fmtprint(fp, "%S ", s);
+                       } else if(fmtmode == FExp) {
+                               // TODO(rsc) this breaks on the eliding of unused arguments in the backend
+                               // when this is fixed, the special case in dcl.c checkarglist can go.
+                               //if(t->funarg)
+                               //      fmtstrcpy(fp, "_ ");
+                               //else
                                        fmtstrcpy(fp, "? ");
-                                       break;
-                               }
-                               // fallthrough
-                       default:
-                               if(!(s == S || t->embedded))
-                                       fmtprint(fp, "%hS ", s);
                        }
                }
 
@@ -764,15 +776,7 @@ stmtfmt(Fmt *f, Node *n)
 
        switch(n->op){
        case ODCL:
-               switch(n->left->class) {
-               case PFUNC:
-               case PEXTERN:
-                       fmtprint(f, "var %S %T", n->left->sym, n->left->type);
-                       break;
-               default:
-                       fmtprint(f, "var %hS %T", n->left->sym, n->left->type);
-                       break;
-               }
+               fmtprint(f, "var %S %T", n->left->sym, n->left->type);
                break;
 
        case ODCLFIELD:
@@ -931,9 +935,15 @@ static int opprec[] = {
        [ORECV] = 8,
        [ORUNESTR] = 8,
        [OTPAREN] = 8,
+       [OSTRUCTLIT] = 8,
+       [OMAPLIT] = 8,
+       [OARRAYLIT] = 8,
 
        [OINDEXMAP] = 8,
        [OINDEX] = 8,
+       [OSLICE] = 8,
+       [OSLICESTR] = 8,
+       [OSLICEARR] = 8,
        [ODOTINTER] = 8,
        [ODOTMETH] = 8,
        [ODOTPTR] = 8,
@@ -1006,6 +1016,7 @@ static int
 exprfmt(Fmt *f, Node *n, int prec)
 {
        int nprec;
+       NodeList *l;
 
        while(n && n->implicit)
                n = n->left;
@@ -1044,15 +1055,6 @@ exprfmt(Fmt *f, Node *n, int prec)
        case ONAME:
        case OPACK:
        case ONONAME:
-               if(fmtmode == FExp) {
-                       switch(n->class&~PHEAP) {
-                       case PEXTERN:
-                       case PFUNC:
-                               break;
-                       default:
-                               return fmtprint(f, "%hS", n->sym);
-                       }
-               }
                return fmtprint(f, "%S", n->sym);
 
        case OTYPE:
@@ -1091,39 +1093,31 @@ exprfmt(Fmt *f, Node *n, int prec)
        case OTFUNC:
                return fmtprint(f, "<func>");
 
-       case OPLUS:
-       case OMINUS:
-               if(n->left->op == n->op)
-                       return fmtprint(f, "%#O %N", n->op, n->left);
-               // fallthrough
-       case OADDR:
-       case OCOM:
-       case OIND:
-       case ONOT:
-       case ORECV:
-               return fmtprint(f, "%#O%N", n->op, n->left);
-
        case OCLOSURE:
                if(fmtmode == FErr)
                        return fmtstrcpy(f, "func literal");
-               // return fmtprint(f, "%T { %H }", n->type, n->nbody); this prints the list/rlist turned to types, not what we want
-               if(!n->rlist)
-                       return fmtprint(f, "func(%,H) { %H } ", n->list, n->nbody);
-               if(!n->rlist->next && !n->rlist->n->left)
-                       return fmtprint(f, "func(%,H) %N { %H } ", n->list, n->rlist->n->right, n->nbody);
-               return fmtprint(f, "func(%,H) (%,H) { %H } ", n->list, n->rlist, n->nbody);
+               return fmtprint(f, "%T { %H }", n->type, n->nbody);
 
        case OCOMPLIT:
                return fmtstrcpy(f, "composite literal");
 
        case OPTRLIT:
-               if(fmtmode == FErr)
-                       return fmtprint(f, "&%T literal", n->type->type);
-               return fmtprint(f, "&%T{ %,H }", n->type->type, n->list);
+               return fmtprint(f, "&%N", n->left);
+
+       case OSTRUCTLIT:
+               if (fmtmode == FExp) {   // requires special handling of field names
+                       fmtprint(f, "%T{", n->type);
+                       for(l=n->list; l; l=l->next)
+                               if(l->next)
+                                       fmtprint(f, " %hhS:%N,", l->n->left->sym, l->n->right);
+                               else
+                                       fmtprint(f, " %hhS:%N ", l->n->left->sym, l->n->right);
+                       return fmtstrcpy(f, "}");
+               }
+               // fallthrough
 
        case OARRAYLIT:
        case OMAPLIT:
-       case OSTRUCTLIT:
                if(fmtmode == FErr)
                        return fmtprint(f, "%T literal", n->type);
                return fmtprint(f, "%T{ %,H }", n->type, n->list);
@@ -1211,6 +1205,21 @@ exprfmt(Fmt *f, Node *n, int prec)
                        return fmtprint(f, "make(%T, %,H)", n->type, n->list->next);
                return fmtprint(f, "make(%T)", n->type);
 
+       // Unary
+       case OPLUS:
+       case OMINUS:
+       case OADDR:
+       case OCOM:
+       case OIND:
+       case ONOT:
+       case ORECV:
+               if(n->left->op == n->op)
+                       fmtprint(f, "%#O ", n->op);
+               else
+                       fmtprint(f, "%#O", n->op);
+               return exprfmt(f, n->left, nprec+1);
+
+       // Binary
        case OADD:
        case OADDSTR:
        case OAND:
@@ -1274,8 +1283,7 @@ indent(Fmt *fp)
 {
        int i;
 
-       if(dumpdepth > 1)
-               fmtstrcpy(fp, "\n");
+       fmtstrcpy(fp, "\n");
        for(i = 0; i < dumpdepth; ++i)
                fmtstrcpy(fp, ".   ");
 }
@@ -1324,7 +1332,6 @@ nodedump(Fmt *fp, Node *n)
        case OTYPE:
                fmtprint(fp, "%O %S type=%T", n->op, n->sym, n->type);
                if(recur && n->type == T && n->ntype) {
-                       fmtstrcpy(fp, "\n");
                        indent(fp);
                        fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
                }
@@ -1384,6 +1391,9 @@ Sconv(Fmt *fp)
        if(s == S)
                return fmtstrcpy(fp, "<S>");
 
+       if(s->name[0] == '_' && s->name[1] == '\0')
+               return fmtstrcpy(fp, "_");
+
        sf = fp->flags;
        sm = setfmode(&fp->flags);
        r = symfmt(fp, s);
index 59f43dd6d6f4ecc544d1c5ef7341a6358cfc2e9f..82d5039f0ca474bee648e9d6ffb603f2a675e5bd 100644 (file)
@@ -135,7 +135,7 @@ struct      Type
        uchar   printed;
        uchar   embedded;       // TFIELD embedded type
        uchar   siggen;
-       uchar   funarg;
+       uchar   funarg;         // on TSTRUCT and TFIELD
        uchar   copyany;
        uchar   local;          // created in this file
        uchar   deferwidth;
@@ -325,9 +325,9 @@ struct      NodeList
 
 enum
 {
-       SymExport       = 1<<0,
+       SymExport       = 1<<0, // to be exported
        SymPackage      = 1<<1,
-       SymExported     = 1<<2,
+       SymExported     = 1<<2, // already written out by export
        SymUniq         = 1<<3,
        SymSiggen       = 1<<4,
 };
@@ -794,7 +794,7 @@ EXTERN      NodeList*       xtop;
 EXTERN NodeList*       externdcl;
 EXTERN NodeList*       closures;
 EXTERN NodeList*       exportlist;
-EXTERN NodeList*       typelist;
+EXTERN NodeList*       importlist;     // imported functions and methods with inlinable bodies
 EXTERN int     dclcontext;             // PEXTERN/PAUTO
 EXTERN int     incannedimport;
 EXTERN int     statuniqgen;            // name generator for static temps
@@ -950,11 +950,11 @@ void      autoexport(Node *n, int ctxt);
 void   dumpexport(void);
 int    exportname(char *s);
 void   exportsym(Node *n);
-void   importconst(Sym *s, Type *t, Node *n);
-void   importmethod(Sym *s, Type *t);
-Sym*   importsym(Sym *s, int op);
-void   importtype(Type *pt, Type *t);
-void   importvar(Sym *s, Type *t, int ctxt);
+void    importconst(Sym *s, Type *t, Node *n);
+void   importimport(Sym *s, Strlit *z);
+Sym*    importsym(Sym *s, int op);
+void    importtype(Type *pt, Type *t);
+void    importvar(Sym *s, Type *t);
 Type*  pkgtype(Sym *s);
 
 /*
@@ -983,7 +983,7 @@ Node*       temp(Type*);
  *     init.c
  */
 void   fninit(NodeList *n);
-Node*  renameinit(Node *n);
+Sym*   renameinit(void);
 
 /*
  *     lex.c
index 530e54112a5f108ecd9f6dd48e288874f8c312eb..1b00235083ecdd0eaada58d77e4a85b6dc7806f7 100644 (file)
@@ -56,7 +56,7 @@ static void fixlbrace(int);
 %type  <node>  case caseblock
 %type  <node>  compound_stmt dotname embed expr complitexpr
 %type  <node>  expr_or_type
-%type  <node>  fndcl fnliteral
+%type  <node>  fndcl hidden_fndcl fnliteral
 %type  <node>  for_body for_header for_stmt if_header if_stmt else non_dcl_stmt
 %type  <node>  interfacedcl keyval labelname name
 %type  <node>  name_or_type non_expr_type
@@ -80,8 +80,8 @@ static void fixlbrace(int);
 
 %type  <sym>   hidden_importsym hidden_pkg_importsym
 
-%type  <node>  hidden_constant hidden_literal hidden_dcl
-%type  <node>  hidden_interfacedcl hidden_structdcl hidden_opt_sym
+%type  <node>  hidden_constant hidden_literal hidden_funarg
+%type  <node>  hidden_interfacedcl hidden_structdcl
 
 %type  <list>  hidden_funres
 %type  <list>  ohidden_funres
@@ -235,7 +235,7 @@ import_here:
        }
 
 import_package:
-       LPACKAGE sym import_safety ';'
+       LPACKAGE LNAME import_safety ';'
        {
                if(importpkg->name == nil) {
                        importpkg->name = $2->name;
@@ -1004,7 +1004,17 @@ onew_name:
 
 sym:
        LNAME
+       {
+               $$ = $1;
+               // during imports, unqualified non-exported identifiers are from builtinpkg
+               if(importpkg != nil && !exportname($1->name))
+                       $$ = pkglookup($1->name, builtinpkg);
+       }
 |      hidden_importsym
+|      '?'
+       {
+               $$ = S;
+       }
 
 hidden_importsym:
        '@' LLITERAL '.' LNAME
@@ -1186,38 +1196,43 @@ xfndcl:
        }
 
 fndcl:
-       dcl_name '(' oarg_type_list_ocomma ')' fnres
+       sym '(' oarg_type_list_ocomma ')' fnres
        {
-               Node *n;
+               Node *t;
 
+               $$ = N;
                $3 = checkarglist($3, 1);
-               $$ = nod(ODCLFUNC, N, N);
-               $$->nname = $1;
-               n = nod(OTFUNC, N, N);
-               n->list = $3;
-               n->rlist = $5;
-               if(strcmp($1->sym->name, "init") == 0) {
-                       $$->nname = renameinit($1);
+
+               if(strcmp($1->name, "init") == 0) {
+                       $1 = renameinit();
                        if($3 != nil || $5 != nil)
                                yyerror("func init must have no arguments and no return values");
                }
-               if(strcmp(localpkg->name, "main") == 0 && strcmp($1->sym->name, "main") == 0) {
+               if(strcmp(localpkg->name, "main") == 0 && strcmp($1->name, "main") == 0) {
                        if($3 != nil || $5 != nil)
                                yyerror("func main must have no arguments and no return values");
                }
-               // TODO: check if nname already has an ntype
-               $$->nname->ntype = n;
+
+               t = nod(OTFUNC, N, N);
+               t->list = $3;
+               t->rlist = $5;
+
+               $$ = nod(ODCLFUNC, N, N);
+               $$->nname = newname($1);
+               $$->nname->defn = $$;
+               $$->nname->ntype = t;           // TODO: check if nname already has an ntype
+               declare($$->nname, PFUNC);
+
                funchdr($$);
        }
 |      '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
        {
                Node *rcvr, *t;
-               Node *name;
-               
-               name = newname($4);
+
+               $$ = N;
                $2 = checkarglist($2, 0);
                $6 = checkarglist($6, 1);
-               $$ = N;
+
                if($2 == nil) {
                        yyerror("method has no receiver");
                        break;
@@ -1234,13 +1249,51 @@ fndcl:
                if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN))
                        yyerror("cannot parenthesize receiver type");
 
-               $$ = nod(ODCLFUNC, N, N);
-               $$->nname = methodname1(name, rcvr->right);
                t = nod(OTFUNC, rcvr, N);
                t->list = $6;
                t->rlist = $8;
+
+               $$ = nod(ODCLFUNC, N, N);
+               $$->shortname = newname($4);
+               $$->nname = methodname1($$->shortname, rcvr->right);
+               $$->nname->defn = $$;
                $$->nname->ntype = t;
-               $$->shortname = name;
+               declare($$->nname, PFUNC);
+
+               funchdr($$);
+       }
+
+hidden_fndcl:
+       hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres
+       {
+               Sym *s;
+               Type *t;
+
+               $$ = N;
+
+               s = $1;
+               t = functype(N, $3, $5);
+
+               importsym(s, ONAME);
+               if(s->def != N && s->def->op == ONAME) {
+                       if(eqtype(t, s->def->type))
+                               break;
+                       yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t);
+               }
+
+               $$ = newname(s);
+               $$->type = t;
+               declare($$, PFUNC);
+
+               funchdr($$);
+       }
+|      '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
+       {
+               $$ = methodname1(newname($4), $2->n->right); 
+               $$->type = functype($2->n, $6, $8);
+
+               checkwidth($$->type);
+               addmethod($4, $$->type, 0);
                funchdr($$);
        }
 
@@ -1709,31 +1762,16 @@ oliteral:
 |      LLITERAL
 
 /*
- * import syntax from header of
- * an output package
+ * import syntax from package header
  */
 hidden_import:
-       LIMPORT sym LLITERAL ';'
+       LIMPORT LNAME LLITERAL ';'
        {
-               // Informational: record package name
-               // associated with import path, for use in
-               // human-readable messages.
-               Pkg *p;
-
-               p = mkpkg($3.u.sval);
-               if(p->name == nil) {
-                       p->name = $2->name;
-                       pkglookup($2->name, nil)->npkg++;
-               } else if(strcmp(p->name, $2->name) != 0)
-                       yyerror("conflicting names %s and %s for package \"%Z\"", p->name, $2->name, p->path);
-               if(!incannedimport && myimportpath != nil && strcmp($3.u.sval->s, myimportpath) == 0) {
-                       yyerror("import \"%Z\": package depends on \"%Z\" (import cycle)", importpkg->path, $3.u.sval);
-                       errorexit();
-               }
+               importimport($2, $3.u.sval);
        }
 |      LVAR hidden_pkg_importsym hidden_type ';'
        {
-               importvar($2, $3, PEXTERN);
+               importvar($2, $3);
        }
 |      LCONST hidden_pkg_importsym '=' hidden_constant ';'
        {
@@ -1747,17 +1785,24 @@ hidden_import:
        {
                importtype($2, $3);
        }
-|      LFUNC hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres ';'
+|      LFUNC hidden_fndcl fnbody ';'
        {
-               importvar($2, functype(N, $4, $6), PFUNC);
+               if($2 == N)
+                       break;
+
+               funcbody($2);
+               importlist = list(importlist, $2);
+
+               if(debug['E']) {
+                       print("import [%Z] func %lN \n", $2->sym->pkg->path, $2);
+               }
        }
-|      LFUNC '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres ';'
+
+hidden_pkg_importsym:
+       hidden_importsym
        {
-               if($3->next != nil || $3->n->op != ODCLFIELD) {
-                       yyerror("bad receiver in method");
-                       YYERROR;
-               }
-               importmethod($5, functype($3->n, $7, $9));
+               $$ = $1;
+               structpkg = $$->pkg;
        }
 
 hidden_pkgtype:
@@ -1767,6 +1812,10 @@ hidden_pkgtype:
                importsym($1, OTYPE);
        }
 
+/*
+ *  importing types
+ */
+
 hidden_type:
        hidden_type_misc
 |      hidden_type_recv_chan
@@ -1848,52 +1897,45 @@ hidden_type_func:
                $$ = functype(nil, $3, $5);
        }
 
-hidden_opt_sym:
-       sym
-       {
-               $$ = newname($1);
-       }
-|      '?'
-       {
-               $$ = N;
-       }
-
-hidden_dcl:
-       hidden_opt_sym hidden_type oliteral
+hidden_funarg:
+       sym hidden_type oliteral
        {
-               $$ = nod(ODCLFIELD, $1, typenod($2));
+               $$ = nod(ODCLFIELD, N, typenod($2));
+               if($1)
+                       $$->left = newname($1);
                $$->val = $3;
        }
-|      hidden_opt_sym LDDD hidden_type oliteral
+|      sym LDDD hidden_type oliteral
        {
                Type *t;
-               
+       
                t = typ(TARRAY);
                t->bound = -1;
                t->type = $3;
-               $$ = nod(ODCLFIELD, $1, typenod(t));
+
+               $$ = nod(ODCLFIELD, N, typenod(t));
+               if($1)
+                       $$->left = newname($1);
                $$->isddd = 1;
                $$->val = $4;
        }
 
 hidden_structdcl:
        sym hidden_type oliteral
-       {
-               $$ = nod(ODCLFIELD, newname($1), typenod($2));
-               $$->val = $3;
-       }
-|      '?' hidden_type oliteral
        {
                Sym *s;
 
-               s = $2->sym;
-               if(s == S && isptr[$2->etype])
-                       s = $2->type->sym;
-               if(s && s->pkg == builtinpkg)
-                       s = lookup(s->name);
-               $$ = embedded(s);
-               $$->right = typenod($2);
-               $$->val = $3;
+               if($1 != S) {
+                       $$ = nod(ODCLFIELD, newname($1), typenod($2));
+                       $$->val = $3;
+               } else {
+                       s = $2->sym;
+                       if(s == S && isptr[$2->etype])
+                               s = $2->type->sym;
+                       $$ = embedded(s);
+                       $$->right = typenod($2);
+                       $$->val = $3;
+               }
        }
 
 hidden_interfacedcl:
@@ -1918,6 +1960,10 @@ hidden_funres:
                $$ = list1(nod(ODCLFIELD, N, typenod($1)));
        }
 
+/*
+ *  importing constants
+ */
+
 hidden_literal:
        LLITERAL
        {
@@ -1951,22 +1997,15 @@ hidden_constant:
                $$ = nodcplxlit($2->val, $4->val);
        }
 
-hidden_pkg_importsym:
-       hidden_importsym
-       {
-               $$ = $1;
-               structpkg = $$->pkg;
-       }
-
 hidden_import_list:
 |      hidden_import_list hidden_import
 
 hidden_funarg_list:
-       hidden_dcl
+       hidden_funarg
        {
                $$ = list1($1);
        }
-|      hidden_funarg_list ',' hidden_dcl
+|      hidden_funarg_list ',' hidden_funarg
        {
                $$ = list($1, $3);
        }
index da69e41ae318a803f8a1723e4430e1fb6488ab54..be402cc0cec3f566822eb5cc7823d8d933f77bd4 100644 (file)
  * package and also uncallable, the name,
  * normally "pkg.init", is altered to "pkg.init·1".
  */
-Node*
-renameinit(Node *n)
+Sym*
+renameinit(void)
 {
-       Sym *s;
        static int initgen;
 
-       s = n->sym;
-       if(s == S)
-               return n;
-       if(strcmp(s->name, "init") != 0)
-               return n;
-
        snprint(namebuf, sizeof(namebuf), "init·%d", ++initgen);
-       s = lookup(namebuf);
-       return newname(s);
+       return lookup(namebuf);
 }
 
 /*
@@ -125,7 +117,9 @@ fninit(NodeList *n)
        fn = nod(ODCLFUNC, N, N);
        initsym = lookup(namebuf);
        fn->nname = newname(initsym);
+       fn->nname->defn = fn;
        fn->nname->ntype = nod(OTFUNC, N, N);
+       declare(fn->nname, PFUNC);
        funchdr(fn);
 
        // (3)
index bf5a26d006e5fc75d87fb22809fd798837916b83..3267fbe389006cfc7def3709763d6e7cabdf2644 100644 (file)
@@ -334,11 +334,11 @@ main(int argc, char *argv[])
        if(nsavederrors+nerrors)
                errorexit();
 
-       // Phase 3b: escape analysis.
+       // Phase 4: escape analysis.
        if(!debug['N'])
                escapes();
 
-       // Phase 4: Compile function bodies.
+       // Phase 5: Compile top level functions.
        for(l=xtop; l; l=l->next)
                if(l->n->op == ODCLFUNC)
                        funccompile(l->n, 0);
@@ -346,16 +346,15 @@ main(int argc, char *argv[])
        if(nsavederrors+nerrors == 0)
                fninit(xtop);
 
-       // Phase 4b: Compile all closures.
+       // Phase 5b: Compile all closures.
        while(closures) {
                l = closures;
                closures = nil;
-               for(; l; l=l->next) {
+               for(; l; l=l->next)
                        funccompile(l->n, 1);
-               }
        }
 
-       // Phase 5: check external declarations.
+       // Phase 6: check external declarations.
        for(l=externdcl; l; l=l->next)
                if(l->n->op == ONAME)
                        typecheck(&l->n, Erv);
@@ -1423,7 +1422,7 @@ yylex(void)
        // Track last two tokens returned by yylex.
        yyprev = yylast;
        yylast = lx;
-       return lx;
+       return lx;
 }
 
 static int
@@ -1680,12 +1679,12 @@ static  struct
        "type",         LTYPE,          Txxx,           OXXX,
        "var",          LVAR,           Txxx,           OXXX,
 
-       "append",               LNAME,          Txxx,           OAPPEND,
+       "append",       LNAME,          Txxx,           OAPPEND,
        "cap",          LNAME,          Txxx,           OCAP,
        "close",        LNAME,          Txxx,           OCLOSE,
        "complex",      LNAME,          Txxx,           OCOMPLEX,
        "copy",         LNAME,          Txxx,           OCOPY,
-       "delete",               LNAME,          Txxx,           ODELETE,
+       "delete",       LNAME,          Txxx,           ODELETE,
        "imag",         LNAME,          Txxx,           OIMAG,
        "len",          LNAME,          Txxx,           OLEN,
        "make",         LNAME,          Txxx,           OMAKE,
@@ -1710,6 +1709,7 @@ lexinit(void)
        Sym *s, *s1;
        Type *t;
        int etype;
+       Val v;
 
        /*
         * initialize basic types array
@@ -1738,6 +1738,16 @@ lexinit(void)
                        s1->def = typenod(t);
                        continue;
                }
+
+               etype = syms[i].op;
+               if(etype != OXXX) {
+                       s1 = pkglookup(syms[i].name, builtinpkg);
+                       s1->lexical = LNAME;
+                       s1->def = nod(ONAME, N, N);
+                       s1->def->sym = s;
+                       s1->def->etype = etype;
+                       s1->def->builtin = 1;
+               }
        }
 
        // logically, the type of a string literal.
@@ -1765,6 +1775,19 @@ lexinit(void)
        types[TBLANK] = typ(TBLANK);
        s->def->type = types[TBLANK];
        nblank = s->def;
+
+       s = pkglookup("_", builtinpkg);
+       s->block = -100;
+       s->def = nod(ONAME, N, N);
+       s->def->sym = s;
+       types[TBLANK] = typ(TBLANK);
+       s->def->type = types[TBLANK];
+
+       types[TNIL] = typ(TNIL);
+       s = pkglookup("nil", builtinpkg);
+       v.ctype = CTNIL;
+       s->def = nodlit(v);
+       s->def->sym = s;
 }
 
 static void
@@ -1875,7 +1898,6 @@ lexfini(void)
        if(s->def == N)
                s->def = typenod(runetype);
 
-       types[TNIL] = typ(TNIL);
        s = lookup("nil");
        if(s->def == N) {
                v.ctype = CTNIL;
index 2ee5868bc6007580ab8b8bf5ce069212371271c3..8bdfaf7b0cc768da0c4afcee91a7af4b581c13f6 100644 (file)
@@ -2287,8 +2287,6 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
        in = structargs(getinarg(method->type), 1);
        out = structargs(getoutarg(method->type), 0);
 
-       fn = nod(ODCLFUNC, N, N);
-       fn->nname = newname(newnam);
        t = nod(OTFUNC, N, N);
        l = list1(this);
        if(iface && rcvr->width < types[tptr]->width) {
@@ -2305,7 +2303,12 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
        }
        t->list = concat(l, in);
        t->rlist = out;
+
+       fn = nod(ODCLFUNC, N, N);
+       fn->nname = newname(newnam);
+       fn->nname->defn = fn;
        fn->nname->ntype = t;
+       declare(fn->nname, PFUNC);
        funchdr(fn);
 
        // arg list
index eb6e84e63e5715b21edb45f846e2e36eac211795..072b577a56902a828b826b8f275d2fc8f1554720 100644 (file)
@@ -43,7 +43,7 @@ resolve(Node *n)
 {
        Node *r;
 
-       if(n != N && n->op == ONONAME && (r = n->sym->def) != N) {
+       if(n != N && n->op == ONONAME && n->sym != S && (r = n->sym->def) != N) {
                if(r->op != OIOTA)
                        n = r;
                else if(n->iota >= 0)
@@ -114,7 +114,6 @@ typecheck(Node **np, int top)
        NodeList *args;
        int lno, ok, ntop;
        Type *t, *tp, *ft, *missing, *have;
-       Sym *sym;
        Val v;
        char *why;
 
@@ -567,15 +566,14 @@ reswitch:
        case ODOT:
                typecheck(&n->left, Erv|Etype);
                defaultlit(&n->left, T);
-               l = n->left;
-               if((t = l->type) == T)
+               if((t = n->left->type) == T)
                        goto error;
                if(n->right->op != ONAME) {
                        yyerror("rhs of . must be a name");     // impossible
                        goto error;
                }
-               sym = n->right->sym;
-               if(l->op == OTYPE) {
+
+               if(n->left->op == OTYPE) {
                        if(!looktypedot(n, t, 0)) {
                                if(looktypedot(n, t, 1))
                                        yyerror("%N undefined (cannot refer to unexported method %S)", n, n->right->sym);
@@ -584,19 +582,18 @@ reswitch:
                                goto error;
                        }
                        if(n->type->etype != TFUNC || n->type->thistuple != 1) {
-                               yyerror("type %T has no method %hS", n->left->type, sym);
+                               yyerror("type %T has no method %hS", n->left->type, n->right->sym);
                                n->type = T;
                                goto error;
                        }
                        n->op = ONAME;
-                       n->sym = methodsym(sym, l->type, 0);
-                       n->type = methodfunc(n->type, l->type);
+                       n->sym = n->right->sym;
+                       n->type = methodfunc(n->type, n->left->type);
                        n->xoffset = 0;
                        n->class = PFUNC;
                        ok = Erv;
                        goto ret;
                }
-               tp = t;
                if(isptr[t->etype] && t->type->etype != TINTER) {
                        t = t->type;
                        if(t == T)
@@ -608,7 +605,7 @@ reswitch:
                        if(lookdot(n, t, 1))
                                yyerror("%N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);
                        else
-                               yyerror("%N undefined (type %T has no field or method %S)", n, tp, n->right->sym);
+                               yyerror("%N undefined (type %T has no field or method %S)", n, n->left->type, n->right->sym);
                        goto error;
                }
                switch(n->op) {
@@ -2167,14 +2164,16 @@ typecheckcomplit(Node **np)
                                        typecheck(&l->right, Erv);
                                        continue;
                                }
+
                                // Sym might have resolved to name in other top-level
                                // package, because of import dot.  Redirect to correct sym
                                // before we do the lookup.
-                               if(s->pkg != localpkg)
+                               if(s->pkg != localpkg && exportname(s->name))
                                        s = lookup(s->name);
+
                                f = lookdot1(s, t, t->type, 0);
                                if(f == nil) {
-                                       yyerror("unknown %T field '%s' in struct literal", t, s->name);
+                                       yyerror("unknown %T field '%S' in struct literal", t, s);
                                        continue;
                                }
                                l->left = newname(s);
index 16a8667ff669bcc1a9c69f120a3f15aa81212730..b5fc357802a40ea70016ba328bc166091b2095f3 100644 (file)
@@ -323,7 +323,7 @@ func (p *gcParser) parseMapType() Type {
        return &Map{Key: key, Elt: elt}
 }
 
-// Name = identifier | "?" .
+// Name = identifier | "?" | ExportedName  .
 //
 func (p *gcParser) parseName() (name string) {
        switch p.tok {
@@ -333,6 +333,9 @@ func (p *gcParser) parseName() (name string) {
        case '?':
                // anonymous
                p.next()
+       case '@':
+               // exported name prefixed with package path
+               _, name = p.parseExportedName()
        default:
                p.error("name expected")
        }
@@ -747,7 +750,7 @@ func (p *gcParser) parseFuncDecl() {
        }
 }
 
-// MethodDecl = "func" Receiver identifier Signature .
+// MethodDecl = "func" Receiver Name Signature .
 // Receiver   = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
 //
 func (p *gcParser) parseMethodDecl() {
@@ -755,7 +758,7 @@ func (p *gcParser) parseMethodDecl() {
        p.expect('(')
        p.parseParameter() // receiver
        p.expect(')')
-       p.expect(scanner.Ident)
+       p.parseName() // unexported method names in imports are qualified with their package.
        p.parseSignature()
        if p.tok == '{' {
                p.parseFuncBody()