diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c index 0391ece379..9aeac8aba4 100644 --- a/src/cmd/gc/closure.c +++ b/src/cmd/gc/closure.c @@ -19,6 +19,7 @@ closurehdr(Node *ntype) n = nod(OCLOSURE, N, N); n->ntype = ntype; n->funcdepth = funcdepth; + n->outerfunc = curfn; funchdr(n); @@ -124,11 +125,55 @@ typecheckclosure(Node *func, int top) xtop = list(xtop, makeclosure(func)); } +// closurename returns name for OCLOSURE n. +// It is not as simple as it ought to be, because we typecheck nested closures +// starting from the innermost one. So when we check the inner closure, +// we don't yet have name for the outer closure. This function uses recursion +// to generate names all the way up if necessary. +static Sym* +closurename(Node *n) +{ + static int closgen; + char *outer, *prefix; + int gen; + + if(n->sym != S) + return n->sym; + gen = 0; + outer = NULL; + prefix = NULL; + if(n->outerfunc == N) { + // Global closure. + outer = "glob"; + prefix = "func"; + gen = ++closgen; + } else if(n->outerfunc->op == ODCLFUNC) { + // The outermost closure inside of a named function. + outer = n->outerfunc->nname->sym->name; + prefix = "func"; + // Yes, functions can be named _. + // Can't use function closgen in such case, + // because it would lead to name clashes. + if(!isblank(n->outerfunc->nname)) + gen = ++n->outerfunc->closgen; + else + gen = ++closgen; + } else if(n->outerfunc->op == OCLOSURE) { + // Nested closure, recurse. + outer = closurename(n->outerfunc)->name; + prefix = ""; + gen = ++n->outerfunc->closgen; + } else + fatal("closurename called for %hN", n); + snprint(namebuf, sizeof namebuf, "%s.%s%d", outer, prefix, gen); + n->sym = lookup(namebuf); + return n->sym; +} + static Node* makeclosure(Node *func) { Node *xtype, *xfunc; - static int closgen; /* * wrap body in external function @@ -140,8 +185,7 @@ makeclosure(Node *func) // create the function xfunc = nod(ODCLFUNC, N, N); - snprint(namebuf, sizeof namebuf, "func·%.3d", ++closgen); - xfunc->nname = newname(lookup(namebuf)); + xfunc->nname = newname(closurename(func)); xfunc->nname->sym->flags |= SymExported; // disable export xfunc->nname->ntype = xtype; xfunc->nname->defn = xfunc; @@ -158,7 +202,7 @@ makeclosure(Node *func) xfunc->closure = func; func->closure = xfunc; - + func->nbody = nil; func->list = nil; func->rlist = nil; @@ -368,7 +412,7 @@ walkclosure(Node *func, NodeList **init) // and has one float64 argument and no results, // the generated code looks like: // - // clos = &struct{F uintptr; A0 *int; A1 *string}{func·001, &i, &s} + // clos = &struct{.F uintptr; i *int; s *string}{func.1, &i, &s} // // The use of the struct provides type information to the garbage // collector so that it can walk the closure. We could use (in this case) @@ -378,7 +422,7 @@ walkclosure(Node *func, NodeList **init) // same struct type can share the descriptor. typ = nod(OTSTRUCT, N, N); - typ->list = list1(nod(ODCLFIELD, newname(lookup("F")), typenod(types[TUINTPTR]))); + typ->list = list1(nod(ODCLFIELD, newname(lookup(".F")), typenod(types[TUINTPTR]))); for(l=func->cvars; l; l=l->next) { v = l->n; if(v->op == OXXX) @@ -447,12 +491,11 @@ makepartialcall(Node *fn, Type *t0, Node *meth) static Pkg* gopkg; int i, ddd; - // TODO: names are not right rcvrtype = fn->left->type; if(exportname(meth->sym->name)) - p = smprint("%-hT.%s·fm", rcvrtype, meth->sym->name); + p = smprint("(%-hT).%s-fm", rcvrtype, meth->sym->name); else - p = smprint("%-hT.(%-S)·fm", rcvrtype, meth->sym); + p = smprint("(%-hT).(%-S)-fm", rcvrtype, meth->sym); basetype = rcvrtype; if(isptr[rcvrtype->etype]) basetype = basetype->type; diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index c5ef74586d..92584f6c58 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -310,6 +310,8 @@ struct Node NodeList* dcl; // autodcl for this func/closure NodeList* inl; // copy of the body for use in inlining NodeList* inldcl; // copy of dcl for use in inlining + int closgen; + Node* outerfunc; // OLITERAL/OREGISTER Val val; diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c index c769ec27f0..f1484ea1a6 100644 --- a/src/cmd/gc/init.c +++ b/src/cmd/gc/init.c @@ -11,14 +11,14 @@ * it is called by the initialization before * main is run. to make it unique within a * package and also uncallable, the name, - * normally "pkg.init", is altered to "pkg.init·1". + * normally "pkg.init", is altered to "pkg.init.1". */ Sym* renameinit(void) { static int initgen; - snprint(namebuf, sizeof(namebuf), "init·%d", ++initgen); + snprint(namebuf, sizeof(namebuf), "init.%d", ++initgen); return lookup(namebuf); } @@ -35,7 +35,7 @@ renameinit(void) * // over all matching imported symbols * .init() (7) * { } (8) - * init·() // if any (9) + * init.() // if any (9) * initdone· = 2; (10) * return (11) * } @@ -69,8 +69,7 @@ anyinit(NodeList *n) return 1; // is there an explicit init function - snprint(namebuf, sizeof(namebuf), "init·1"); - s = lookup(namebuf); + s = lookup("init.1"); if(s->def != N) return 1; @@ -167,7 +166,7 @@ fninit(NodeList *n) // (9) // could check that it is fn of no args/returns for(i=1;; i++) { - snprint(namebuf, sizeof(namebuf), "init·%d", i); + snprint(namebuf, sizeof(namebuf), "init.%d", i); s = lookup(namebuf); if(s->def == N) break; diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c index 3df78e7f9a..16a869181d 100644 --- a/src/cmd/gc/pgen.c +++ b/src/cmd/gc/pgen.c @@ -180,7 +180,7 @@ compile(Node *fn) dowidth(curfn->type); if(fn->nbody == nil) { - if(pure_go || strncmp(fn->nname->sym->name, "init·", 6) == 0) { + if(pure_go || strncmp(fn->nname->sym->name, "init.", 5) == 0) { yyerror("missing function body", fn); goto ret; }