120
walkclosure(Node *func, NodeList **init)
120
makeclosure(Node *func, NodeList **init, int nowrap)
123
Node *xtype, *v, *addr, *xfunc, *call, *clos;
122
Node *xtype, *v, *addr, *xfunc;
125
124
static int closgen;
156
153
// then a dummy arg where the closure's caller pc sits
157
xtype->list = list(xtype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
155
xtype->list = list(xtype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
159
157
// then the function arguments
160
158
xtype->list = concat(xtype->list, func->list);
176
174
typecheck(&xfunc, Etop);
177
175
closures = list(closures, xfunc);
181
walkclosure(Node *func, NodeList **init)
184
Node *xtype, *xfunc, *call, *clos;
188
* wrap body in external function
189
* with extra closure parameters.
192
// create the function
193
xfunc = makeclosure(func, init, 0);
194
xtype = xfunc->nname->ntype;
179
196
// prepare call of sys.closure that turns external func into func literal value.
180
197
clos = syslook("closure", 1);
182
199
clos->ntype = nod(OTFUNC, N, N);
183
200
in = list1(nod(ODCLFIELD, N, typenod(types[TINT]))); // siz
184
201
in = list(in, nod(ODCLFIELD, N, xtype));
185
203
for(l=func->cvars; l; l=l->next) {
186
204
if(l->n->op == 0)
188
207
in = list(in, nod(ODCLFIELD, N, l->n->heapaddr->ntype));
190
209
clos->ntype->list = in;
212
231
walkcallclosure(Node *n, NodeList **init)
215
NodeList *ll, *cargs;
217
walkexpr(&n->left, init);
218
cargs = n->left // FUNC runtime.closure
221
->next; // skip second
223
n->left = n->left // FUNC runtime.closure
226
->n // AS (to indreg)
227
->right; // argument == the generated function
229
// New arg list for n. First the closure-args, stolen from
230
// runtime.closure's 3rd and following,
232
for (; cargs; cargs = cargs->next)
233
ll = list(ll, cargs->n->right); // cargs->n is the OAS(INDREG, arg)
235
// then an extra zero, to fill the dummy return pointer slot,
237
nodconst(z, types[TUINTPTR], 0);
241
// and finally the original parameter list.
242
n->list = concat(ll, n->list);
233
if (n->op != OCALLFUNC || n->left->op != OCLOSURE) {
234
dump("walkcallclosure", n);
235
fatal("abuse of walkcallclosure");
238
// New arg list for n. First the closure-args
239
// and then the original parameter list.
240
n->list = concat(n->left->enter, n->list);
241
n->left = makeclosure(n->left, init, 1)->nname;
242
dowidth(n->left->type);
243
n->type = getoutargx(n->left->type);
244
// for a single valued function, pull the field type out of the struct
245
if (n->type && n->type->type && !n->type->type->down)
246
n->type = n->type->type->type;