n = nod(OCLOSURE, N, N);
n->ntype = ntype;
n->funcdepth = funcdepth;
+ n->outerfunc = curfn;
funchdr(n);
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
// 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;
xfunc->closure = func;
func->closure = xfunc;
-
+
func->nbody = nil;
func->list = nil;
func->rlist = nil;
// 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)
// 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)
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;
* 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);
}
* // over all matching imported symbols
* <pkg>.init() (7)
* { <init stmts> } (8)
- * init·<n>() // if any (9)
+ * init.<n>() // if any (9)
* initdone· = 2; (10)
* return (11)
* }
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;
// (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;