Commit 40b2fe00 authored by Luuk van Dijk's avatar Luuk van Dijk Committed by Russ Cox

gc: changes in export format in preparation of inlining.

Includes minimal change to gcimporter to keep it working,

R=rsc, gri
CC=golang-dev
https://golang.org/cl/5431046
parent 5cb1c82d
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "y.tab.h" #include "y.tab.h"
static void funcargs(Node*); static void funcargs(Node*);
static void funcargs2(Type*);
static int static int
dflag(void) dflag(void)
...@@ -547,13 +548,6 @@ ifacedcl(Node *n) ...@@ -547,13 +548,6 @@ ifacedcl(Node *n)
void void
funchdr(Node *n) 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 // change the declaration context from extern to auto
if(funcdepth == 0 && dclcontext != PEXTERN) if(funcdepth == 0 && dclcontext != PEXTERN)
fatal("funchdr: dclcontext"); fatal("funchdr: dclcontext");
...@@ -564,10 +558,13 @@ funchdr(Node *n) ...@@ -564,10 +558,13 @@ funchdr(Node *n)
n->outer = curfn; n->outer = curfn;
curfn = n; curfn = n;
if(n->nname) if(n->nname)
funcargs(n->nname->ntype); funcargs(n->nname->ntype);
else else if (n->ntype)
funcargs(n->ntype); funcargs(n->ntype);
else
funcargs2(n->type);
} }
static void static void
...@@ -582,11 +579,11 @@ funcargs(Node *nt) ...@@ -582,11 +579,11 @@ funcargs(Node *nt)
// declare the receiver and in arguments. // declare the receiver and in arguments.
// no n->defn because type checking of func header // 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) { if(nt->left != N) {
n = nt->left; n = nt->left;
if(n->op != ODCLFIELD) if(n->op != ODCLFIELD)
fatal("funcargs1 %O", n->op); fatal("funcargs receiver %O", n->op);
if(n->left != N) { if(n->left != N) {
n->left->op = ONAME; n->left->op = ONAME;
n->left->ntype = n->right; n->left->ntype = n->right;
...@@ -596,7 +593,7 @@ funcargs(Node *nt) ...@@ -596,7 +593,7 @@ funcargs(Node *nt)
for(l=nt->list; l; l=l->next) { for(l=nt->list; l; l=l->next) {
n = l->n; n = l->n;
if(n->op != ODCLFIELD) if(n->op != ODCLFIELD)
fatal("funcargs2 %O", n->op); fatal("funcargs in %O", n->op);
if(n->left != N) { if(n->left != N) {
n->left->op = ONAME; n->left->op = ONAME;
n->left->ntype = n->right; n->left->ntype = n->right;
...@@ -609,7 +606,7 @@ funcargs(Node *nt) ...@@ -609,7 +606,7 @@ funcargs(Node *nt)
for(l=nt->rlist; l; l=l->next) { for(l=nt->rlist; l; l=l->next) {
n = l->n; n = l->n;
if(n->op != ODCLFIELD) if(n->op != ODCLFIELD)
fatal("funcargs3 %O", n->op); fatal("funcargs out %O", n->op);
if(n->left != N) { if(n->left != N) {
n->left->op = ONAME; n->left->op = ONAME;
n->left->ntype = n->right; n->left->ntype = n->right;
...@@ -627,6 +624,48 @@ funcargs(Node *nt) ...@@ -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. * finish the body.
* called in auto-declaration context. * called in auto-declaration context.
...@@ -654,7 +693,7 @@ typedcl0(Sym *s) ...@@ -654,7 +693,7 @@ typedcl0(Sym *s)
{ {
Node *n; Node *n;
n = dclname(s); n = newname(s);
n->op = OTYPE; n->op = OTYPE;
declare(n, dclcontext); declare(n, dclcontext);
return n; return n;
...@@ -740,8 +779,6 @@ structfield(Node *n) ...@@ -740,8 +779,6 @@ structfield(Node *n)
f->nname = n->left; f->nname = n->left;
f->embedded = n->embedded; f->embedded = n->embedded;
f->sym = f->nname->sym; f->sym = f->nname->sym;
if(importpkg && !exportname(f->sym->name))
f->sym = pkglookup(f->sym->name, structpkg);
} }
lineno = lno; lineno = lno;
...@@ -778,8 +815,12 @@ tostruct(NodeList *l) ...@@ -778,8 +815,12 @@ tostruct(NodeList *l)
Type *t, *f, **tp; Type *t, *f, **tp;
t = typ(TSTRUCT); t = typ(TSTRUCT);
for(tp = &t->type; l; l=l->next,tp = &(*tp)->down) for(tp = &t->type; l; l=l->next) {
*tp = structfield(l->n); f = structfield(l->n);
*tp = f;
tp = &f->down;
}
for(f=t->type; f && !t->broke; f=f->down) for(f=t->type; f && !t->broke; f=f->down)
if(f->broke) if(f->broke)
...@@ -803,7 +844,7 @@ tofunargs(NodeList *l) ...@@ -803,7 +844,7 @@ tofunargs(NodeList *l)
for(tp = &t->type; l; l=l->next) { for(tp = &t->type; l; l=l->next) {
f = structfield(l->n); f = structfield(l->n);
f->funarg = 1;
// esc.c needs to find f given a PPARAM to add the tag. // esc.c needs to find f given a PPARAM to add the tag.
if(l->n->left && l->n->left->class == PPARAM) if(l->n->left && l->n->left->class == PPARAM)
l->n->left->paramfld = f; l->n->left->paramfld = f;
...@@ -944,7 +985,10 @@ embedded(Sym *s) ...@@ -944,7 +985,10 @@ embedded(Sym *s)
*utfrune(name, CenterDot) = 0; *utfrune(name, CenterDot) = 0;
} }
if(exportname(name) || s->pkg == builtinpkg) // old behaviour, tests pass, but is it correct?
n = newname(lookup(name)); n = newname(lookup(name));
else
n = newname(pkglookup(name, s->pkg));
n = nod(ODCLFIELD, n, oldname(s)); n = nod(ODCLFIELD, n, oldname(s));
n->embedded = 1; n->embedded = 1;
return n; return n;
...@@ -1009,6 +1053,17 @@ checkarglist(NodeList *all, int input) ...@@ -1009,6 +1053,17 @@ checkarglist(NodeList *all, int input)
t = n; t = n;
n = 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) { if(n != N && n->sym == S) {
t = n; t = n;
n = N; n = N;
...@@ -1137,7 +1192,6 @@ methodsym(Sym *nsym, Type *t0, int iface) ...@@ -1137,7 +1192,6 @@ methodsym(Sym *nsym, Type *t0, int iface)
else else
p = smprint("%-hT.%s%s", t0, nsym->name, suffix); p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
s = pkglookup(p, s->pkg); s = pkglookup(p, s->pkg);
//print("methodsym:%s -> %+S\n", p, s);
free(p); free(p);
return s; return s;
...@@ -1174,6 +1228,10 @@ methodname1(Node *n, Node *t) ...@@ -1174,6 +1228,10 @@ methodname1(Node *n, Node *t)
p = smprint("(%s%S).%S", star, t->sym, n->sym); p = smprint("(%s%S).%S", star, t->sym, n->sym);
else else
p = smprint("%S.%S", t->sym, n->sym); p = smprint("%S.%S", t->sym, n->sym);
if(exportname(t->sym->name))
n = newname(lookup(p));
else
n = newname(pkglookup(p, t->sym->pkg)); n = newname(pkglookup(p, t->sym->pkg));
free(p); free(p);
return n; return n;
...@@ -1234,8 +1292,6 @@ addmethod(Sym *sf, Type *t, int local) ...@@ -1234,8 +1292,6 @@ addmethod(Sym *sf, Type *t, int local)
} }
pa = f; pa = f;
if(importpkg && !exportname(sf->name))
sf = pkglookup(sf->name, importpkg);
n = nod(ODCLFIELD, newname(sf), N); n = nod(ODCLFIELD, newname(sf), N);
n->type = t; n->type = t;
...@@ -1258,10 +1314,16 @@ addmethod(Sym *sf, Type *t, int local) ...@@ -1258,10 +1314,16 @@ addmethod(Sym *sf, Type *t, int local)
return; 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) if(d == T)
pa->method = structfield(n); pa->method = f;
else else
d->down = structfield(n); d->down = f;
return; return;
} }
......
...@@ -7,11 +7,9 @@ ...@@ -7,11 +7,9 @@
#include "go.h" #include "go.h"
#include "y.tab.h" #include "y.tab.h"
static void dumpsym(Sym*);
static void dumpexporttype(Type*); static void dumpexporttype(Type*);
static void dumpexportvar(Sym*);
static void dumpexportconst(Sym*);
// Mark n's symbol as exported
void void
exportsym(Node *n) exportsym(Node *n)
{ {
...@@ -27,6 +25,7 @@ exportsym(Node *n) ...@@ -27,6 +25,7 @@ exportsym(Node *n)
exportlist = list(exportlist, n); exportlist = list(exportlist, n);
} }
// Mark n's symbol as package-local
static void static void
packagesym(Node *n) packagesym(Node *n)
{ {
...@@ -178,7 +177,7 @@ dumpexporttype(Type *t) ...@@ -178,7 +177,7 @@ dumpexporttype(Type *t)
Bprint(bout, "\ttype %#S %#lT\n", t->sym, t); Bprint(bout, "\ttype %#S %#lT\n", t->sym, t);
for(i=0; i<n; i++) { for(i=0; i<n; i++) {
f = m[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) ...@@ -200,15 +199,18 @@ dumpsym(Sym *s)
default: default:
yyerror("unexpected export symbol: %O %S", s->def->op, s); yyerror("unexpected export symbol: %O %S", s->def->op, s);
break; break;
case OLITERAL: case OLITERAL:
dumpexportconst(s); dumpexportconst(s);
break; break;
case OTYPE: case OTYPE:
if(s->def->type->etype == TFORW) if(s->def->type->etype == TFORW)
yyerror("export of incomplete type %S", s); yyerror("export of incomplete type %S", s);
else else
dumpexporttype(s->def->type); dumpexporttype(s->def->type);
break; break;
case ONAME: case ONAME:
dumpexportvar(s); dumpexportvar(s);
break; break;
...@@ -286,12 +288,25 @@ pkgtype(Sym *s) ...@@ -286,12 +288,25 @@ pkgtype(Sym *s)
return s->def->type; return s->def->type;
} }
static int void
mypackage(Sym *s) importimport(Sym *s, Strlit *z)
{ {
// we import all definitions for runtime. // Informational: record package name
// lowercase ones can only be used by the compiler. // associated with import path, for use in
return s->pkg == localpkg || s->pkg == runtimepkg; // 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 void
...@@ -299,19 +314,17 @@ importconst(Sym *s, Type *t, Node *n) ...@@ -299,19 +314,17 @@ importconst(Sym *s, Type *t, Node *n)
{ {
Node *n1; Node *n1;
if(!exportname(s->name) && !mypackage(s))
return;
importsym(s, OLITERAL); importsym(s, OLITERAL);
convlit(&n, t); convlit(&n, t);
if(s->def != N) {
// TODO: check if already the same. if(s->def != N) // TODO: check if already the same.
return; return;
}
if(n->op != OLITERAL) { if(n->op != OLITERAL) {
yyerror("expression must be a constant"); yyerror("expression must be a constant");
return; return;
} }
if(n->sym != S) { if(n->sym != S) {
n1 = nod(OXXX, N, N); n1 = nod(OXXX, N, N);
*n1 = *n; *n1 = *n;
...@@ -325,13 +338,10 @@ importconst(Sym *s, Type *t, Node *n) ...@@ -325,13 +338,10 @@ importconst(Sym *s, Type *t, Node *n)
} }
void void
importvar(Sym *s, Type *t, int ctxt) importvar(Sym *s, Type *t)
{ {
Node *n; Node *n;
if(!exportname(s->name) && !initname(s->name) && !mypackage(s))
return;
importsym(s, ONAME); importsym(s, ONAME);
if(s->def != N && s->def->op == ONAME) { if(s->def != N && s->def->op == ONAME) {
if(eqtype(t, s->def->type)) if(eqtype(t, s->def->type))
...@@ -340,7 +350,7 @@ importvar(Sym *s, Type *t, int ctxt) ...@@ -340,7 +350,7 @@ importvar(Sym *s, Type *t, int ctxt)
} }
n = newname(s); n = newname(s);
n->type = t; n->type = t;
declare(n, ctxt); declare(n, PEXTERN);
if(debug['E']) if(debug['E'])
print("import var %S %lT\n", s, t); print("import var %S %lT\n", s, t);
...@@ -351,7 +361,6 @@ importtype(Type *pt, Type *t) ...@@ -351,7 +361,6 @@ importtype(Type *pt, Type *t)
{ {
Node *n; Node *n;
if(pt != T && t != T) {
// override declaration in unsafe.go for Pointer. // override declaration in unsafe.go for Pointer.
// there is no way in Go code to define unsafe.Pointer // there is no way in Go code to define unsafe.Pointer
// so we have to supply it. // so we have to supply it.
...@@ -364,25 +373,13 @@ importtype(Type *pt, Type *t) ...@@ -364,25 +373,13 @@ importtype(Type *pt, Type *t)
if(pt->etype == TFORW) { if(pt->etype == TFORW) {
n = pt->nod; n = pt->nod;
copytype(pt->nod, t); copytype(pt->nod, t);
// unzero nod pt->nod = n; // unzero nod
pt->nod = n;
pt->sym->lastlineno = parserline(); pt->sym->lastlineno = parserline();
declare(n, PEXTERN); declare(n, PEXTERN);
checkwidth(pt); checkwidth(pt);
} else if(!eqtype(pt->orig, t)) } 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); yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t);
}
if(debug['E']) if(debug['E'])
print("import type %T %lT\n", pt, t); print("import type %T %lT\n", pt, t);
} }
void
importmethod(Sym *s, Type *t)
{
checkwidth(t);
addmethod(s, t, 0);
}
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
// %S Sym* Symbols // %S Sym* Symbols
// Flags: +,- #: mode (see below) // Flags: +,- #: mode (see below)
// "%hS" unqualified identifier in any mode // "%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 // %T Type* Types
// Flags: +,- #: mode (see below) // Flags: +,- #: mode (see below)
...@@ -341,6 +341,9 @@ Jconv(Fmt *fp) ...@@ -341,6 +341,9 @@ Jconv(Fmt *fp)
if(n->implicit != 0) if(n->implicit != 0)
fmtprint(fp, " implicit(%d)", n->implicit); fmtprint(fp, " implicit(%d)", n->implicit);
if(n->embedded != 0)
fmtprint(fp, " embedded(%d)", n->embedded);
if(!c && n->used != 0) if(!c && n->used != 0)
fmtprint(fp, " used(%d)", n->used); fmtprint(fp, " used(%d)", n->used);
return 0; return 0;
...@@ -488,7 +491,7 @@ symfmt(Fmt *fp, Sym *s) ...@@ -488,7 +491,7 @@ symfmt(Fmt *fp, Sym *s)
if(s->pkg == localpkg) if(s->pkg == localpkg)
return fmtstrcpy(fp, s->name); return fmtstrcpy(fp, s->name);
// If the name was used by multiple packages, display the full path, // 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, "\"%Z\".%s", s->pkg->path, s->name);
return fmtprint(fp, "%s.%s", s->pkg->name, s->name); return fmtprint(fp, "%s.%s", s->pkg->name, s->name);
case FDbg: case FDbg:
...@@ -502,11 +505,19 @@ symfmt(Fmt *fp, Sym *s) ...@@ -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 // skip leading "type." in method name
p = utfrrune(s->name, '.'); p = utfrrune(s->name, '.');
if(p) 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); return fmtstrcpy(fp, s->name);
...@@ -672,9 +683,9 @@ typefmt(Fmt *fp, Type *t) ...@@ -672,9 +683,9 @@ typefmt(Fmt *fp, Type *t)
fmtstrcpy(fp, "struct {"); fmtstrcpy(fp, "struct {");
for(t1=t->type; t1!=T; t1=t1->down) for(t1=t->type; t1!=T; t1=t1->down)
if(t1->down) if(t1->down)
fmtprint(fp, " %T;", t1); fmtprint(fp, " %lT;", t1);
else else
fmtprint(fp, " %T ", t1); fmtprint(fp, " %lT ", t1);
fmtstrcpy(fp, "}"); fmtstrcpy(fp, "}");
} }
return 0; return 0;
...@@ -682,21 +693,22 @@ typefmt(Fmt *fp, Type *t) ...@@ -682,21 +693,22 @@ typefmt(Fmt *fp, Type *t)
case TFIELD: case TFIELD:
if(!(fp->flags&FmtShort)) { if(!(fp->flags&FmtShort)) {
s = t->sym; s = t->sym;
switch(fmtmode) {
case FErr:
case FExp:
// Take the name from the original, lest we substituted it with .anon%d // Take the name from the original, lest we substituted it with .anon%d
if (t->nname) if (t->nname && (fmtmode == FErr || fmtmode == FExp))
s = t->nname->orig->sym; s = t->nname->orig->sym;
if((s == S || t->embedded)) { 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, "? "); fmtstrcpy(fp, "? ");
break;
}
// fallthrough
default:
if(!(s == S || t->embedded))
fmtprint(fp, "%hS ", s);
} }
} }
...@@ -764,16 +776,8 @@ stmtfmt(Fmt *f, Node *n) ...@@ -764,16 +776,8 @@ stmtfmt(Fmt *f, Node *n)
switch(n->op){ switch(n->op){
case ODCL: case ODCL:
switch(n->left->class) {
case PFUNC:
case PEXTERN:
fmtprint(f, "var %S %T", n->left->sym, n->left->type); fmtprint(f, "var %S %T", n->left->sym, n->left->type);
break; break;
default:
fmtprint(f, "var %hS %T", n->left->sym, n->left->type);
break;
}
break;
case ODCLFIELD: case ODCLFIELD:
if(n->left) if(n->left)
...@@ -931,9 +935,15 @@ static int opprec[] = { ...@@ -931,9 +935,15 @@ static int opprec[] = {
[ORECV] = 8, [ORECV] = 8,
[ORUNESTR] = 8, [ORUNESTR] = 8,
[OTPAREN] = 8, [OTPAREN] = 8,
[OSTRUCTLIT] = 8,
[OMAPLIT] = 8,
[OARRAYLIT] = 8,
[OINDEXMAP] = 8, [OINDEXMAP] = 8,
[OINDEX] = 8, [OINDEX] = 8,
[OSLICE] = 8,
[OSLICESTR] = 8,
[OSLICEARR] = 8,
[ODOTINTER] = 8, [ODOTINTER] = 8,
[ODOTMETH] = 8, [ODOTMETH] = 8,
[ODOTPTR] = 8, [ODOTPTR] = 8,
...@@ -1006,6 +1016,7 @@ static int ...@@ -1006,6 +1016,7 @@ static int
exprfmt(Fmt *f, Node *n, int prec) exprfmt(Fmt *f, Node *n, int prec)
{ {
int nprec; int nprec;
NodeList *l;
while(n && n->implicit) while(n && n->implicit)
n = n->left; n = n->left;
...@@ -1044,15 +1055,6 @@ exprfmt(Fmt *f, Node *n, int prec) ...@@ -1044,15 +1055,6 @@ exprfmt(Fmt *f, Node *n, int prec)
case ONAME: case ONAME:
case OPACK: case OPACK:
case ONONAME: 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); return fmtprint(f, "%S", n->sym);
case OTYPE: case OTYPE:
...@@ -1091,39 +1093,31 @@ exprfmt(Fmt *f, Node *n, int prec) ...@@ -1091,39 +1093,31 @@ exprfmt(Fmt *f, Node *n, int prec)
case OTFUNC: case OTFUNC:
return fmtprint(f, "<func>"); 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: case OCLOSURE:
if(fmtmode == FErr) if(fmtmode == FErr)
return fmtstrcpy(f, "func literal"); 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 return fmtprint(f, "%T { %H }", n->type, n->nbody);
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);
case OCOMPLIT: case OCOMPLIT:
return fmtstrcpy(f, "composite literal"); return fmtstrcpy(f, "composite literal");
case OPTRLIT: case OPTRLIT:
if(fmtmode == FErr) return fmtprint(f, "&%N", n->left);
return fmtprint(f, "&%T literal", n->type->type);
return fmtprint(f, "&%T{ %,H }", n->type->type, n->list); 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 OARRAYLIT:
case OMAPLIT: case OMAPLIT:
case OSTRUCTLIT:
if(fmtmode == FErr) if(fmtmode == FErr)
return fmtprint(f, "%T literal", n->type); return fmtprint(f, "%T literal", n->type);
return fmtprint(f, "%T{ %,H }", n->type, n->list); return fmtprint(f, "%T{ %,H }", n->type, n->list);
...@@ -1211,6 +1205,21 @@ exprfmt(Fmt *f, Node *n, int prec) ...@@ -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, %,H)", n->type, n->list->next);
return fmtprint(f, "make(%T)", n->type); 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 OADD:
case OADDSTR: case OADDSTR:
case OAND: case OAND:
...@@ -1274,7 +1283,6 @@ indent(Fmt *fp) ...@@ -1274,7 +1283,6 @@ indent(Fmt *fp)
{ {
int i; int i;
if(dumpdepth > 1)
fmtstrcpy(fp, "\n"); fmtstrcpy(fp, "\n");
for(i = 0; i < dumpdepth; ++i) for(i = 0; i < dumpdepth; ++i)
fmtstrcpy(fp, ". "); fmtstrcpy(fp, ". ");
...@@ -1324,7 +1332,6 @@ nodedump(Fmt *fp, Node *n) ...@@ -1324,7 +1332,6 @@ nodedump(Fmt *fp, Node *n)
case OTYPE: case OTYPE:
fmtprint(fp, "%O %S type=%T", n->op, n->sym, n->type); fmtprint(fp, "%O %S type=%T", n->op, n->sym, n->type);
if(recur && n->type == T && n->ntype) { if(recur && n->type == T && n->ntype) {
fmtstrcpy(fp, "\n");
indent(fp); indent(fp);
fmtprint(fp, "%O-ntype%N", n->op, n->ntype); fmtprint(fp, "%O-ntype%N", n->op, n->ntype);
} }
...@@ -1384,6 +1391,9 @@ Sconv(Fmt *fp) ...@@ -1384,6 +1391,9 @@ Sconv(Fmt *fp)
if(s == S) if(s == S)
return fmtstrcpy(fp, "<S>"); return fmtstrcpy(fp, "<S>");
if(s->name[0] == '_' && s->name[1] == '\0')
return fmtstrcpy(fp, "_");
sf = fp->flags; sf = fp->flags;
sm = setfmode(&fp->flags); sm = setfmode(&fp->flags);
r = symfmt(fp, s); r = symfmt(fp, s);
......
...@@ -135,7 +135,7 @@ struct Type ...@@ -135,7 +135,7 @@ struct Type
uchar printed; uchar printed;
uchar embedded; // TFIELD embedded type uchar embedded; // TFIELD embedded type
uchar siggen; uchar siggen;
uchar funarg; uchar funarg; // on TSTRUCT and TFIELD
uchar copyany; uchar copyany;
uchar local; // created in this file uchar local; // created in this file
uchar deferwidth; uchar deferwidth;
...@@ -325,9 +325,9 @@ struct NodeList ...@@ -325,9 +325,9 @@ struct NodeList
enum enum
{ {
SymExport = 1<<0, SymExport = 1<<0, // to be exported
SymPackage = 1<<1, SymPackage = 1<<1,
SymExported = 1<<2, SymExported = 1<<2, // already written out by export
SymUniq = 1<<3, SymUniq = 1<<3,
SymSiggen = 1<<4, SymSiggen = 1<<4,
}; };
...@@ -794,7 +794,7 @@ EXTERN NodeList* xtop; ...@@ -794,7 +794,7 @@ EXTERN NodeList* xtop;
EXTERN NodeList* externdcl; EXTERN NodeList* externdcl;
EXTERN NodeList* closures; EXTERN NodeList* closures;
EXTERN NodeList* exportlist; EXTERN NodeList* exportlist;
EXTERN NodeList* typelist; EXTERN NodeList* importlist; // imported functions and methods with inlinable bodies
EXTERN int dclcontext; // PEXTERN/PAUTO EXTERN int dclcontext; // PEXTERN/PAUTO
EXTERN int incannedimport; EXTERN int incannedimport;
EXTERN int statuniqgen; // name generator for static temps EXTERN int statuniqgen; // name generator for static temps
...@@ -951,10 +951,10 @@ void dumpexport(void); ...@@ -951,10 +951,10 @@ void dumpexport(void);
int exportname(char *s); int exportname(char *s);
void exportsym(Node *n); void exportsym(Node *n);
void importconst(Sym *s, Type *t, Node *n); void importconst(Sym *s, Type *t, Node *n);
void importmethod(Sym *s, Type *t); void importimport(Sym *s, Strlit *z);
Sym* importsym(Sym *s, int op); Sym* importsym(Sym *s, int op);
void importtype(Type *pt, Type *t); void importtype(Type *pt, Type *t);
void importvar(Sym *s, Type *t, int ctxt); void importvar(Sym *s, Type *t);
Type* pkgtype(Sym *s); Type* pkgtype(Sym *s);
/* /*
...@@ -983,7 +983,7 @@ Node* temp(Type*); ...@@ -983,7 +983,7 @@ Node* temp(Type*);
* init.c * init.c
*/ */
void fninit(NodeList *n); void fninit(NodeList *n);
Node* renameinit(Node *n); Sym* renameinit(void);
/* /*
* lex.c * lex.c
......
...@@ -56,7 +56,7 @@ static void fixlbrace(int); ...@@ -56,7 +56,7 @@ static void fixlbrace(int);
%type <node> case caseblock %type <node> case caseblock
%type <node> compound_stmt dotname embed expr complitexpr %type <node> compound_stmt dotname embed expr complitexpr
%type <node> expr_or_type %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> for_body for_header for_stmt if_header if_stmt else non_dcl_stmt
%type <node> interfacedcl keyval labelname name %type <node> interfacedcl keyval labelname name
%type <node> name_or_type non_expr_type %type <node> name_or_type non_expr_type
...@@ -80,8 +80,8 @@ static void fixlbrace(int); ...@@ -80,8 +80,8 @@ static void fixlbrace(int);
%type <sym> hidden_importsym hidden_pkg_importsym %type <sym> hidden_importsym hidden_pkg_importsym
%type <node> hidden_constant hidden_literal hidden_dcl %type <node> hidden_constant hidden_literal hidden_funarg
%type <node> hidden_interfacedcl hidden_structdcl hidden_opt_sym %type <node> hidden_interfacedcl hidden_structdcl
%type <list> hidden_funres %type <list> hidden_funres
%type <list> ohidden_funres %type <list> ohidden_funres
...@@ -235,7 +235,7 @@ import_here: ...@@ -235,7 +235,7 @@ import_here:
} }
import_package: import_package:
LPACKAGE sym import_safety ';' LPACKAGE LNAME import_safety ';'
{ {
if(importpkg->name == nil) { if(importpkg->name == nil) {
importpkg->name = $2->name; importpkg->name = $2->name;
...@@ -1004,7 +1004,17 @@ onew_name: ...@@ -1004,7 +1004,17 @@ onew_name:
sym: sym:
LNAME LNAME
{
$$ = $1;
// during imports, unqualified non-exported identifiers are from builtinpkg
if(importpkg != nil && !exportname($1->name))
$$ = pkglookup($1->name, builtinpkg);
}
| hidden_importsym | hidden_importsym
| '?'
{
$$ = S;
}
hidden_importsym: hidden_importsym:
'@' LLITERAL '.' LNAME '@' LLITERAL '.' LNAME
...@@ -1186,38 +1196,43 @@ xfndcl: ...@@ -1186,38 +1196,43 @@ xfndcl:
} }
fndcl: fndcl:
dcl_name '(' oarg_type_list_ocomma ')' fnres sym '(' oarg_type_list_ocomma ')' fnres
{ {
Node *n; Node *t;
$$ = N;
$3 = checkarglist($3, 1); $3 = checkarglist($3, 1);
$$ = nod(ODCLFUNC, N, N);
$$->nname = $1; if(strcmp($1->name, "init") == 0) {
n = nod(OTFUNC, N, N); $1 = renameinit();
n->list = $3;
n->rlist = $5;
if(strcmp($1->sym->name, "init") == 0) {
$$->nname = renameinit($1);
if($3 != nil || $5 != nil) if($3 != nil || $5 != nil)
yyerror("func init must have no arguments and no return values"); 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) if($3 != nil || $5 != nil)
yyerror("func main must have no arguments and no return values"); 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($$); funchdr($$);
} }
| '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres | '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
{ {
Node *rcvr, *t; Node *rcvr, *t;
Node *name;
name = newname($4); $$ = N;
$2 = checkarglist($2, 0); $2 = checkarglist($2, 0);
$6 = checkarglist($6, 1); $6 = checkarglist($6, 1);
$$ = N;
if($2 == nil) { if($2 == nil) {
yyerror("method has no receiver"); yyerror("method has no receiver");
break; break;
...@@ -1234,13 +1249,51 @@ fndcl: ...@@ -1234,13 +1249,51 @@ fndcl:
if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN)) if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN))
yyerror("cannot parenthesize receiver type"); yyerror("cannot parenthesize receiver type");
$$ = nod(ODCLFUNC, N, N);
$$->nname = methodname1(name, rcvr->right);
t = nod(OTFUNC, rcvr, N); t = nod(OTFUNC, rcvr, N);
t->list = $6; t->list = $6;
t->rlist = $8; t->rlist = $8;
$$ = nod(ODCLFUNC, N, N);
$$->shortname = newname($4);
$$->nname = methodname1($$->shortname, rcvr->right);
$$->nname->defn = $$;
$$->nname->ntype = t; $$->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($$); funchdr($$);
} }
...@@ -1709,31 +1762,16 @@ oliteral: ...@@ -1709,31 +1762,16 @@ oliteral:
| LLITERAL | LLITERAL
/* /*
* import syntax from header of * import syntax from package header
* an output package
*/ */
hidden_import: hidden_import:
LIMPORT sym LLITERAL ';' LIMPORT LNAME LLITERAL ';'
{ {
// Informational: record package name importimport($2, $3.u.sval);
// 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();
}
} }
| LVAR hidden_pkg_importsym hidden_type ';' | LVAR hidden_pkg_importsym hidden_type ';'
{ {
importvar($2, $3, PEXTERN); importvar($2, $3);
} }
| LCONST hidden_pkg_importsym '=' hidden_constant ';' | LCONST hidden_pkg_importsym '=' hidden_constant ';'
{ {
...@@ -1747,17 +1785,24 @@ hidden_import: ...@@ -1747,17 +1785,24 @@ hidden_import:
{ {
importtype($2, $3); 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 ';'
{
if($3->next != nil || $3->n->op != ODCLFIELD) {
yyerror("bad receiver in method");
YYERROR;
} }
importmethod($5, functype($3->n, $7, $9));
hidden_pkg_importsym:
hidden_importsym
{
$$ = $1;
structpkg = $$->pkg;
} }
hidden_pkgtype: hidden_pkgtype:
...@@ -1767,6 +1812,10 @@ hidden_pkgtype: ...@@ -1767,6 +1812,10 @@ hidden_pkgtype:
importsym($1, OTYPE); importsym($1, OTYPE);
} }
/*
* importing types
*/
hidden_type: hidden_type:
hidden_type_misc hidden_type_misc
| hidden_type_recv_chan | hidden_type_recv_chan
...@@ -1848,53 +1897,46 @@ hidden_type_func: ...@@ -1848,53 +1897,46 @@ hidden_type_func:
$$ = functype(nil, $3, $5); $$ = functype(nil, $3, $5);
} }
hidden_opt_sym: hidden_funarg:
sym sym hidden_type oliteral
{
$$ = newname($1);
}
| '?'
{
$$ = N;
}
hidden_dcl:
hidden_opt_sym hidden_type oliteral
{ {
$$ = nod(ODCLFIELD, $1, typenod($2)); $$ = nod(ODCLFIELD, N, typenod($2));
if($1)
$$->left = newname($1);
$$->val = $3; $$->val = $3;
} }
| hidden_opt_sym LDDD hidden_type oliteral | sym LDDD hidden_type oliteral
{ {
Type *t; Type *t;
t = typ(TARRAY); t = typ(TARRAY);
t->bound = -1; t->bound = -1;
t->type = $3; t->type = $3;
$$ = nod(ODCLFIELD, $1, typenod(t));
$$ = nod(ODCLFIELD, N, typenod(t));
if($1)
$$->left = newname($1);
$$->isddd = 1; $$->isddd = 1;
$$->val = $4; $$->val = $4;
} }
hidden_structdcl: hidden_structdcl:
sym hidden_type oliteral sym hidden_type oliteral
{
$$ = nod(ODCLFIELD, newname($1), typenod($2));
$$->val = $3;
}
| '?' hidden_type oliteral
{ {
Sym *s; Sym *s;
if($1 != S) {
$$ = nod(ODCLFIELD, newname($1), typenod($2));
$$->val = $3;
} else {
s = $2->sym; s = $2->sym;
if(s == S && isptr[$2->etype]) if(s == S && isptr[$2->etype])
s = $2->type->sym; s = $2->type->sym;
if(s && s->pkg == builtinpkg)
s = lookup(s->name);
$$ = embedded(s); $$ = embedded(s);
$$->right = typenod($2); $$->right = typenod($2);
$$->val = $3; $$->val = $3;
} }
}
hidden_interfacedcl: hidden_interfacedcl:
sym '(' ohidden_funarg_list ')' ohidden_funres sym '(' ohidden_funarg_list ')' ohidden_funres
...@@ -1918,6 +1960,10 @@ hidden_funres: ...@@ -1918,6 +1960,10 @@ hidden_funres:
$$ = list1(nod(ODCLFIELD, N, typenod($1))); $$ = list1(nod(ODCLFIELD, N, typenod($1)));
} }
/*
* importing constants
*/
hidden_literal: hidden_literal:
LLITERAL LLITERAL
{ {
...@@ -1951,22 +1997,15 @@ hidden_constant: ...@@ -1951,22 +1997,15 @@ hidden_constant:
$$ = nodcplxlit($2->val, $4->val); $$ = nodcplxlit($2->val, $4->val);
} }
hidden_pkg_importsym:
hidden_importsym
{
$$ = $1;
structpkg = $$->pkg;
}
hidden_import_list: hidden_import_list:
| hidden_import_list hidden_import | hidden_import_list hidden_import
hidden_funarg_list: hidden_funarg_list:
hidden_dcl hidden_funarg
{ {
$$ = list1($1); $$ = list1($1);
} }
| hidden_funarg_list ',' hidden_dcl | hidden_funarg_list ',' hidden_funarg
{ {
$$ = list($1, $3); $$ = list($1, $3);
} }
......
...@@ -13,21 +13,13 @@ ...@@ -13,21 +13,13 @@
* package and also uncallable, the name, * package and also uncallable, the name,
* normally "pkg.init", is altered to "pkg.init·1". * normally "pkg.init", is altered to "pkg.init·1".
*/ */
Node* Sym*
renameinit(Node *n) renameinit(void)
{ {
Sym *s;
static int initgen; 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); snprint(namebuf, sizeof(namebuf), "init·%d", ++initgen);
s = lookup(namebuf); return lookup(namebuf);
return newname(s);
} }
/* /*
...@@ -125,7 +117,9 @@ fninit(NodeList *n) ...@@ -125,7 +117,9 @@ fninit(NodeList *n)
fn = nod(ODCLFUNC, N, N); fn = nod(ODCLFUNC, N, N);
initsym = lookup(namebuf); initsym = lookup(namebuf);
fn->nname = newname(initsym); fn->nname = newname(initsym);
fn->nname->defn = fn;
fn->nname->ntype = nod(OTFUNC, N, N); fn->nname->ntype = nod(OTFUNC, N, N);
declare(fn->nname, PFUNC);
funchdr(fn); funchdr(fn);
// (3) // (3)
......
...@@ -334,11 +334,11 @@ main(int argc, char *argv[]) ...@@ -334,11 +334,11 @@ main(int argc, char *argv[])
if(nsavederrors+nerrors) if(nsavederrors+nerrors)
errorexit(); errorexit();
// Phase 3b: escape analysis. // Phase 4: escape analysis.
if(!debug['N']) if(!debug['N'])
escapes(); escapes();
// Phase 4: Compile function bodies. // Phase 5: Compile top level functions.
for(l=xtop; l; l=l->next) for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC) if(l->n->op == ODCLFUNC)
funccompile(l->n, 0); funccompile(l->n, 0);
...@@ -346,16 +346,15 @@ main(int argc, char *argv[]) ...@@ -346,16 +346,15 @@ main(int argc, char *argv[])
if(nsavederrors+nerrors == 0) if(nsavederrors+nerrors == 0)
fninit(xtop); fninit(xtop);
// Phase 4b: Compile all closures. // Phase 5b: Compile all closures.
while(closures) { while(closures) {
l = closures; l = closures;
closures = nil; closures = nil;
for(; l; l=l->next) { for(; l; l=l->next)
funccompile(l->n, 1); funccompile(l->n, 1);
} }
}
// Phase 5: check external declarations. // Phase 6: check external declarations.
for(l=externdcl; l; l=l->next) for(l=externdcl; l; l=l->next)
if(l->n->op == ONAME) if(l->n->op == ONAME)
typecheck(&l->n, Erv); typecheck(&l->n, Erv);
...@@ -1710,6 +1709,7 @@ lexinit(void) ...@@ -1710,6 +1709,7 @@ lexinit(void)
Sym *s, *s1; Sym *s, *s1;
Type *t; Type *t;
int etype; int etype;
Val v;
/* /*
* initialize basic types array * initialize basic types array
...@@ -1738,6 +1738,16 @@ lexinit(void) ...@@ -1738,6 +1738,16 @@ lexinit(void)
s1->def = typenod(t); s1->def = typenod(t);
continue; 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. // logically, the type of a string literal.
...@@ -1765,6 +1775,19 @@ lexinit(void) ...@@ -1765,6 +1775,19 @@ lexinit(void)
types[TBLANK] = typ(TBLANK); types[TBLANK] = typ(TBLANK);
s->def->type = types[TBLANK]; s->def->type = types[TBLANK];
nblank = s->def; 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 static void
...@@ -1875,7 +1898,6 @@ lexfini(void) ...@@ -1875,7 +1898,6 @@ lexfini(void)
if(s->def == N) if(s->def == N)
s->def = typenod(runetype); s->def = typenod(runetype);
types[TNIL] = typ(TNIL);
s = lookup("nil"); s = lookup("nil");
if(s->def == N) { if(s->def == N) {
v.ctype = CTNIL; v.ctype = CTNIL;
......
...@@ -2287,8 +2287,6 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) ...@@ -2287,8 +2287,6 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
in = structargs(getinarg(method->type), 1); in = structargs(getinarg(method->type), 1);
out = structargs(getoutarg(method->type), 0); out = structargs(getoutarg(method->type), 0);
fn = nod(ODCLFUNC, N, N);
fn->nname = newname(newnam);
t = nod(OTFUNC, N, N); t = nod(OTFUNC, N, N);
l = list1(this); l = list1(this);
if(iface && rcvr->width < types[tptr]->width) { if(iface && rcvr->width < types[tptr]->width) {
...@@ -2305,7 +2303,12 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) ...@@ -2305,7 +2303,12 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
} }
t->list = concat(l, in); t->list = concat(l, in);
t->rlist = out; t->rlist = out;
fn = nod(ODCLFUNC, N, N);
fn->nname = newname(newnam);
fn->nname->defn = fn;
fn->nname->ntype = t; fn->nname->ntype = t;
declare(fn->nname, PFUNC);
funchdr(fn); funchdr(fn);
// arg list // arg list
......
...@@ -43,7 +43,7 @@ resolve(Node *n) ...@@ -43,7 +43,7 @@ resolve(Node *n)
{ {
Node *r; 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) if(r->op != OIOTA)
n = r; n = r;
else if(n->iota >= 0) else if(n->iota >= 0)
...@@ -114,7 +114,6 @@ typecheck(Node **np, int top) ...@@ -114,7 +114,6 @@ typecheck(Node **np, int top)
NodeList *args; NodeList *args;
int lno, ok, ntop; int lno, ok, ntop;
Type *t, *tp, *ft, *missing, *have; Type *t, *tp, *ft, *missing, *have;
Sym *sym;
Val v; Val v;
char *why; char *why;
...@@ -567,15 +566,14 @@ reswitch: ...@@ -567,15 +566,14 @@ reswitch:
case ODOT: case ODOT:
typecheck(&n->left, Erv|Etype); typecheck(&n->left, Erv|Etype);
defaultlit(&n->left, T); defaultlit(&n->left, T);
l = n->left; if((t = n->left->type) == T)
if((t = l->type) == T)
goto error; goto error;
if(n->right->op != ONAME) { if(n->right->op != ONAME) {
yyerror("rhs of . must be a name"); // impossible yyerror("rhs of . must be a name"); // impossible
goto error; goto error;
} }
sym = n->right->sym;
if(l->op == OTYPE) { if(n->left->op == OTYPE) {
if(!looktypedot(n, t, 0)) { if(!looktypedot(n, t, 0)) {
if(looktypedot(n, t, 1)) if(looktypedot(n, t, 1))
yyerror("%N undefined (cannot refer to unexported method %S)", n, n->right->sym); yyerror("%N undefined (cannot refer to unexported method %S)", n, n->right->sym);
...@@ -584,19 +582,18 @@ reswitch: ...@@ -584,19 +582,18 @@ reswitch:
goto error; goto error;
} }
if(n->type->etype != TFUNC || n->type->thistuple != 1) { 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; n->type = T;
goto error; goto error;
} }
n->op = ONAME; n->op = ONAME;
n->sym = methodsym(sym, l->type, 0); n->sym = n->right->sym;
n->type = methodfunc(n->type, l->type); n->type = methodfunc(n->type, n->left->type);
n->xoffset = 0; n->xoffset = 0;
n->class = PFUNC; n->class = PFUNC;
ok = Erv; ok = Erv;
goto ret; goto ret;
} }
tp = t;
if(isptr[t->etype] && t->type->etype != TINTER) { if(isptr[t->etype] && t->type->etype != TINTER) {
t = t->type; t = t->type;
if(t == T) if(t == T)
...@@ -608,7 +605,7 @@ reswitch: ...@@ -608,7 +605,7 @@ reswitch:
if(lookdot(n, t, 1)) if(lookdot(n, t, 1))
yyerror("%N undefined (cannot refer to unexported field or method %S)", n, n->right->sym); yyerror("%N undefined (cannot refer to unexported field or method %S)", n, n->right->sym);
else 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; goto error;
} }
switch(n->op) { switch(n->op) {
...@@ -2167,14 +2164,16 @@ typecheckcomplit(Node **np) ...@@ -2167,14 +2164,16 @@ typecheckcomplit(Node **np)
typecheck(&l->right, Erv); typecheck(&l->right, Erv);
continue; continue;
} }
// Sym might have resolved to name in other top-level // Sym might have resolved to name in other top-level
// package, because of import dot. Redirect to correct sym // package, because of import dot. Redirect to correct sym
// before we do the lookup. // before we do the lookup.
if(s->pkg != localpkg) if(s->pkg != localpkg && exportname(s->name))
s = lookup(s->name); s = lookup(s->name);
f = lookdot1(s, t, t->type, 0); f = lookdot1(s, t, t->type, 0);
if(f == nil) { 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; continue;
} }
l->left = newname(s); l->left = newname(s);
......
...@@ -323,7 +323,7 @@ func (p *gcParser) parseMapType() Type { ...@@ -323,7 +323,7 @@ func (p *gcParser) parseMapType() Type {
return &Map{Key: key, Elt: elt} return &Map{Key: key, Elt: elt}
} }
// Name = identifier | "?" . // Name = identifier | "?" | ExportedName .
// //
func (p *gcParser) parseName() (name string) { func (p *gcParser) parseName() (name string) {
switch p.tok { switch p.tok {
...@@ -333,6 +333,9 @@ func (p *gcParser) parseName() (name string) { ...@@ -333,6 +333,9 @@ func (p *gcParser) parseName() (name string) {
case '?': case '?':
// anonymous // anonymous
p.next() p.next()
case '@':
// exported name prefixed with package path
_, name = p.parseExportedName()
default: default:
p.error("name expected") p.error("name expected")
} }
...@@ -747,7 +750,7 @@ func (p *gcParser) parseFuncDecl() { ...@@ -747,7 +750,7 @@ func (p *gcParser) parseFuncDecl() {
} }
} }
// MethodDecl = "func" Receiver identifier Signature . // MethodDecl = "func" Receiver Name Signature .
// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ]. // Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
// //
func (p *gcParser) parseMethodDecl() { func (p *gcParser) parseMethodDecl() {
...@@ -755,7 +758,7 @@ func (p *gcParser) parseMethodDecl() { ...@@ -755,7 +758,7 @@ func (p *gcParser) parseMethodDecl() {
p.expect('(') p.expect('(')
p.parseParameter() // receiver p.parseParameter() // receiver
p.expect(')') p.expect(')')
p.expect(scanner.Ident) p.parseName() // unexported method names in imports are qualified with their package.
p.parseSignature() p.parseSignature()
if p.tok == '{' { if p.tok == '{' {
p.parseFuncBody() p.parseFuncBody()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment