comparison src/vim9execute.c @ 20247:e46e72aaff74 v8.2.0679

patch 8.2.0679: Vim9: incomplete support for closures Commit: https://github.com/vim/vim/commit/bf67ea1af05cbb30cd8f0b665fb567c0dca79796 Author: Bram Moolenaar <Bram@vim.org> Date: Sat May 2 17:52:42 2020 +0200 patch 8.2.0679: Vim9: incomplete support for closures Problem: Vim9: incomplete support for closures. Solution: At the end of a function copy arguments and local variables if they are still used by a referenced closure.
author Bram Moolenaar <Bram@vim.org>
date Sat, 02 May 2020 18:00:04 +0200
parents 23d75968ca5e
children aac52c32a91f
comparison
equal deleted inserted replaced
20246:ef2250432801 20247:e46e72aaff74
22 22
23 #include "vim9.h" 23 #include "vim9.h"
24 24
25 // Structure put on ec_trystack when ISN_TRY is encountered. 25 // Structure put on ec_trystack when ISN_TRY is encountered.
26 typedef struct { 26 typedef struct {
27 int tcd_frame; // ec_frame when ISN_TRY was encountered 27 int tcd_frame_idx; // ec_frame_idx when ISN_TRY was encountered
28 int tcd_catch_idx; // instruction of the first catch 28 int tcd_catch_idx; // instruction of the first catch
29 int tcd_finally_idx; // instruction of the finally block 29 int tcd_finally_idx; // instruction of the finally block
30 int tcd_caught; // catch block entered 30 int tcd_caught; // catch block entered
31 int tcd_return; // when TRUE return from end of :finally 31 int tcd_return; // when TRUE return from end of :finally
32 } trycmd_T; 32 } trycmd_T;
54 /* 54 /*
55 * Execution context. 55 * Execution context.
56 */ 56 */
57 typedef struct { 57 typedef struct {
58 garray_T ec_stack; // stack of typval_T values 58 garray_T ec_stack; // stack of typval_T values
59 int ec_frame; // index in ec_stack: context of ec_dfunc_idx 59 int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx
60 60
61 garray_T *ec_outer_stack; // stack used for closures 61 garray_T *ec_outer_stack; // stack used for closures
62 int ec_outer_frame; // stack frame in ec_outer_stack 62 int ec_outer_frame; // stack frame in ec_outer_stack
63 63
64 garray_T ec_trystack; // stack of trycmd_T values 64 garray_T ec_trystack; // stack of trycmd_T values
200 if (arg_to_add < 0) 200 if (arg_to_add < 0)
201 { 201 {
202 iemsg("Argument count wrong?"); 202 iemsg("Argument count wrong?");
203 return FAIL; 203 return FAIL;
204 } 204 }
205 if (ga_grow(&ectx->ec_stack, arg_to_add + 3 + dfunc->df_varcount) == FAIL) 205 if (ga_grow(&ectx->ec_stack, arg_to_add + 3
206 + dfunc->df_varcount + dfunc->df_closure_count) == FAIL)
206 return FAIL; 207 return FAIL;
207 208
208 // Move the vararg-list to below the missing optional arguments. 209 // Move the vararg-list to below the missing optional arguments.
209 if (vararg_count > 0 && arg_to_add > 0) 210 if (vararg_count > 0 && arg_to_add > 0)
210 *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1); 211 *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
213 for (idx = 0; idx < arg_to_add; ++idx) 214 for (idx = 0; idx < arg_to_add; ++idx)
214 STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN; 215 STACK_TV_BOT(idx - vararg_count)->v_type = VAR_UNKNOWN;
215 ectx->ec_stack.ga_len += arg_to_add; 216 ectx->ec_stack.ga_len += arg_to_add;
216 217
217 // Store current execution state in stack frame for ISN_RETURN. 218 // Store current execution state in stack frame for ISN_RETURN.
218 // TODO: If the actual number of arguments doesn't match what the called
219 // function expects things go bad.
220 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx; 219 STACK_TV_BOT(0)->vval.v_number = ectx->ec_dfunc_idx;
221 STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx; 220 STACK_TV_BOT(1)->vval.v_number = ectx->ec_iidx;
222 STACK_TV_BOT(2)->vval.v_number = ectx->ec_frame; 221 STACK_TV_BOT(2)->vval.v_number = ectx->ec_frame_idx;
223 ectx->ec_frame = ectx->ec_stack.ga_len; 222 ectx->ec_frame_idx = ectx->ec_stack.ga_len;
224 223
225 // Initialize local variables 224 // Initialize local variables
226 for (idx = 0; idx < dfunc->df_varcount; ++idx) 225 for (idx = 0; idx < dfunc->df_varcount + dfunc->df_closure_count; ++idx)
227 STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN; 226 STACK_TV_BOT(STACK_FRAME_SIZE + idx)->v_type = VAR_UNKNOWN;
228 ectx->ec_stack.ga_len += STACK_FRAME_SIZE + dfunc->df_varcount; 227 ectx->ec_stack.ga_len += STACK_FRAME_SIZE
228 + dfunc->df_varcount + dfunc->df_closure_count;
229 229
230 // Set execution state to the start of the called function. 230 // Set execution state to the start of the called function.
231 ectx->ec_dfunc_idx = cdf_idx; 231 ectx->ec_dfunc_idx = cdf_idx;
232 ectx->ec_instr = dfunc->df_instr; 232 ectx->ec_instr = dfunc->df_instr;
233 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1); 233 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1);
234 234
235 // used for closures 235 // used for closures
236 ectx->ec_outer_stack = ufunc->uf_ectx_stack; 236 ectx->ec_outer_stack = dfunc->df_ectx_stack;
237 ectx->ec_outer_frame = ufunc->uf_ectx_frame; 237 ectx->ec_outer_frame = dfunc->df_ectx_frame;
238 238
239 // Decide where to start execution, handles optional arguments. 239 // Decide where to start execution, handles optional arguments.
240 init_instr_idx(ufunc, argcount, ectx); 240 init_instr_idx(ufunc, argcount, ectx);
241 241
242 return OK; 242 return OK;
243 } 243 }
244 244
245 // Get pointer to item in the stack. 245 // Get pointer to item in the stack.
246 #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx) 246 #define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx)
247
248 /*
249 * Used when returning from a function: Check if any closure is still
250 * referenced. If so then move the arguments and variables to a separate piece
251 * of stack to be used when the closure is called.
252 * When "free_arguments" is TRUE the arguments are to be freed.
253 * Returns FAIL when out of memory.
254 */
255 static int
256 handle_closure_in_use(ectx_T *ectx, int free_arguments)
257 {
258 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
259 + ectx->ec_dfunc_idx;
260 int argcount = ufunc_argcount(dfunc->df_ufunc);
261 int top = ectx->ec_frame_idx - argcount;
262 int idx;
263 typval_T *tv;
264 int closure_in_use = FALSE;
265
266 // Check if any created closure is still in use.
267 for (idx = 0; idx < dfunc->df_closure_count; ++idx)
268 {
269 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE
270 + dfunc->df_varcount + idx);
271 if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial->pt_refcount > 1)
272 closure_in_use = TRUE;
273 }
274
275 if (closure_in_use)
276 {
277 funcstack_T *funcstack = ALLOC_CLEAR_ONE(funcstack_T);
278 typval_T *stack;
279
280 // A closure is using the arguments and/or local variables.
281 // Move them to the called function.
282 if (funcstack == NULL)
283 return FAIL;
284 funcstack->fs_ga.ga_len = argcount + STACK_FRAME_SIZE
285 + dfunc->df_varcount;
286 stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len);
287 funcstack->fs_ga.ga_data = stack;
288 if (stack == NULL)
289 {
290 vim_free(funcstack);
291 return FAIL;
292 }
293
294 // Move or copy the arguments.
295 for (idx = 0; idx < argcount; ++idx)
296 {
297 tv = STACK_TV(top + idx);
298 if (free_arguments)
299 {
300 *(stack + idx) = *tv;
301 tv->v_type = VAR_UNKNOWN;
302 }
303 else
304 copy_tv(tv, stack + idx);
305 }
306 // Move the local variables.
307 for (idx = 0; idx < dfunc->df_varcount; ++idx)
308 {
309 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx);
310 *(stack + argcount + STACK_FRAME_SIZE + idx) = *tv;
311 tv->v_type = VAR_UNKNOWN;
312 }
313
314 for (idx = 0; idx < dfunc->df_closure_count; ++idx)
315 {
316 tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE
317 + dfunc->df_varcount + idx);
318 if (tv->v_type == VAR_PARTIAL
319 && tv->vval.v_partial->pt_refcount > 1)
320 {
321 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data)
322 + tv->vval.v_partial->pt_func->uf_dfunc_idx;
323 ++funcstack->fs_refcount;
324 pt_dfunc->df_funcstack = funcstack;
325 pt_dfunc->df_ectx_stack = &funcstack->fs_ga;
326 pt_dfunc->df_ectx_frame = ectx->ec_frame_idx - top;
327 }
328 }
329 }
330
331 return OK;
332 }
247 333
248 /* 334 /*
249 * Return from the current function. 335 * Return from the current function.
250 */ 336 */
251 static void 337 static int
252 func_return(ectx_T *ectx) 338 func_return(ectx_T *ectx)
253 { 339 {
254 int idx; 340 int idx;
255 dfunc_T *dfunc; 341 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
256 int top; 342 + ectx->ec_dfunc_idx;
343 int argcount = ufunc_argcount(dfunc->df_ufunc);
344 int top = ectx->ec_frame_idx - argcount;
257 345
258 // execution context goes one level up 346 // execution context goes one level up
259 estack_pop(); 347 estack_pop();
260 348
261 // Clear the local variables and temporary values, but not 349 if (handle_closure_in_use(ectx, TRUE) == FAIL)
262 // the return value. 350 return FAIL;
263 for (idx = ectx->ec_frame + STACK_FRAME_SIZE; 351
352 // Clear the arguments.
353 for (idx = top; idx < ectx->ec_frame_idx; ++idx)
354 clear_tv(STACK_TV(idx));
355
356 // Clear local variables and temp values, but not the return value.
357 for (idx = ectx->ec_frame_idx + STACK_FRAME_SIZE;
264 idx < ectx->ec_stack.ga_len - 1; ++idx) 358 idx < ectx->ec_stack.ga_len - 1; ++idx)
265 clear_tv(STACK_TV(idx)); 359 clear_tv(STACK_TV(idx));
266 360
267 // Clear the arguments.
268 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
269 top = ectx->ec_frame - ufunc_argcount(dfunc->df_ufunc);
270 for (idx = top; idx < ectx->ec_frame; ++idx)
271 clear_tv(STACK_TV(idx));
272
273 // Restore the previous frame. 361 // Restore the previous frame.
274 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame)->vval.v_number; 362 ectx->ec_dfunc_idx = STACK_TV(ectx->ec_frame_idx)->vval.v_number;
275 ectx->ec_iidx = STACK_TV(ectx->ec_frame + 1)->vval.v_number; 363 ectx->ec_iidx = STACK_TV(ectx->ec_frame_idx + 1)->vval.v_number;
276 ectx->ec_frame = STACK_TV(ectx->ec_frame + 2)->vval.v_number; 364 ectx->ec_frame_idx = STACK_TV(ectx->ec_frame_idx + 2)->vval.v_number;
277 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; 365 dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx;
278 ectx->ec_instr = dfunc->df_instr; 366 ectx->ec_instr = dfunc->df_instr;
279 367
280 // Reset the stack to the position before the call, move the return value 368 // Reset the stack to the position before the call, move the return value
281 // to the top of the stack. 369 // to the top of the stack.
282 idx = ectx->ec_stack.ga_len - 1; 370 idx = ectx->ec_stack.ga_len - 1;
283 ectx->ec_stack.ga_len = top + 1; 371 ectx->ec_stack.ga_len = top + 1;
284 *STACK_TV_BOT(-1) = *STACK_TV(idx); 372 *STACK_TV_BOT(-1) = *STACK_TV(idx);
373
374 return OK;
285 } 375 }
286 376
287 #undef STACK_TV 377 #undef STACK_TV
288 378
289 /* 379 /*
496 typval_T *argv, // arguments 586 typval_T *argv, // arguments
497 typval_T *rettv) // return value 587 typval_T *rettv) // return value
498 { 588 {
499 ectx_T ectx; // execution context 589 ectx_T ectx; // execution context
500 int argc = argc_arg; 590 int argc = argc_arg;
501 int initial_frame_ptr; 591 int initial_frame_idx;
502 typval_T *tv; 592 typval_T *tv;
503 int idx; 593 int idx;
504 int ret = FAIL; 594 int ret = FAIL;
505 int defcount = ufunc->uf_args.ga_len - argc; 595 int defcount = ufunc->uf_args.ga_len - argc;
506 int save_sc_version = current_sctx.sc_version; 596 int save_sc_version = current_sctx.sc_version;
511 // Get pointer to item at the bottom of the stack, -1 is the bottom. 601 // Get pointer to item at the bottom of the stack, -1 is the bottom.
512 #undef STACK_TV_BOT 602 #undef STACK_TV_BOT
513 #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx) 603 #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
514 604
515 // Get pointer to a local variable on the stack. Negative for arguments. 605 // Get pointer to a local variable on the stack. Negative for arguments.
516 #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame + STACK_FRAME_SIZE + idx) 606 #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx)
517 607
518 // Like STACK_TV_VAR but use the outer scope 608 // Like STACK_TV_VAR but use the outer scope
519 #define STACK_OUT_TV_VAR(idx) (((typval_T *)ectx.ec_outer_stack->ga_data) + ectx.ec_outer_frame + STACK_FRAME_SIZE + idx) 609 #define STACK_OUT_TV_VAR(idx) (((typval_T *)ectx.ec_outer_stack->ga_data) + ectx.ec_outer_frame + STACK_FRAME_SIZE + idx)
520 610
521 CLEAR_FIELD(ectx); 611 CLEAR_FIELD(ectx);
560 } 650 }
561 if (ufunc->uf_va_name != NULL) 651 if (ufunc->uf_va_name != NULL)
562 ++ectx.ec_stack.ga_len; 652 ++ectx.ec_stack.ga_len;
563 653
564 // Frame pointer points to just after arguments. 654 // Frame pointer points to just after arguments.
565 ectx.ec_frame = ectx.ec_stack.ga_len; 655 ectx.ec_frame_idx = ectx.ec_stack.ga_len;
566 initial_frame_ptr = ectx.ec_frame; 656 initial_frame_idx = ectx.ec_frame_idx;
567 657
568 // dummy frame entries 658 // dummy frame entries
569 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) 659 for (idx = 0; idx < STACK_FRAME_SIZE; ++idx)
570 { 660 {
571 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; 661 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN;
572 ++ectx.ec_stack.ga_len; 662 ++ectx.ec_stack.ga_len;
573 } 663 }
574 664
575 { 665 {
576 // Reserve space for local variables. 666 // Reserve space for local variables and closure references.
577 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 667 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
578 + ufunc->uf_dfunc_idx; 668 + ufunc->uf_dfunc_idx;
579 669 int count = dfunc->df_varcount + dfunc->df_closure_count;
580 for (idx = 0; idx < dfunc->df_varcount; ++idx) 670
671 for (idx = 0; idx < count; ++idx)
581 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; 672 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
582 ectx.ec_stack.ga_len += dfunc->df_varcount; 673 ectx.ec_stack.ga_len += count;
583 674
584 ectx.ec_instr = dfunc->df_instr; 675 ectx.ec_instr = dfunc->df_instr;
585 } 676 }
586 677
587 // Commands behave like vim9script. 678 // Commands behave like vim9script.
621 712
622 // An exception jumps to the first catch, finally, or returns from 713 // An exception jumps to the first catch, finally, or returns from
623 // the current function. 714 // the current function.
624 if (trystack->ga_len > 0) 715 if (trystack->ga_len > 0)
625 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; 716 trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1;
626 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame) 717 if (trycmd != NULL && trycmd->tcd_frame_idx == ectx.ec_frame_idx)
627 { 718 {
628 // jump to ":catch" or ":finally" 719 // jump to ":catch" or ":finally"
629 ectx.ec_in_catch = TRUE; 720 ectx.ec_in_catch = TRUE;
630 ectx.ec_iidx = trycmd->tcd_catch_idx; 721 ectx.ec_iidx = trycmd->tcd_catch_idx;
631 } 722 }
632 else 723 else
633 { 724 {
634 // not inside try or need to return from current functions. 725 // not inside try or need to return from current functions.
635 if (ectx.ec_frame == initial_frame_ptr) 726 if (ectx.ec_frame_idx == initial_frame_idx)
636 { 727 {
637 // At the toplevel we are done. Push a dummy return value. 728 // At the toplevel we are done. Push a dummy return value.
638 if (ga_grow(&ectx.ec_stack, 1) == FAIL) 729 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
639 goto failed; 730 goto failed;
640 tv = STACK_TV_BOT(0); 731 tv = STACK_TV_BOT(0);
641 tv->v_type = VAR_NUMBER; 732 tv->v_type = VAR_NUMBER;
642 tv->vval.v_number = 0; 733 tv->vval.v_number = 0;
643 ++ectx.ec_stack.ga_len; 734 ++ectx.ec_stack.ga_len;
644 need_rethrow = TRUE; 735 need_rethrow = TRUE;
736 if (handle_closure_in_use(&ectx, FALSE) == FAIL)
737 goto failed;
645 goto done; 738 goto done;
646 } 739 }
647 740
648 func_return(&ectx); 741 if (func_return(&ectx) == FAIL)
742 goto failed;
649 } 743 }
650 continue; 744 continue;
651 } 745 }
652 746
653 iptr = &ectx.ec_instr[ectx.ec_iidx++]; 747 iptr = &ectx.ec_instr[ectx.ec_iidx++];
1071 default: // Cannot reach here 1165 default: // Cannot reach here
1072 goto failed; 1166 goto failed;
1073 } 1167 }
1074 1168
1075 --ectx.ec_stack.ga_len; 1169 --ectx.ec_stack.ga_len;
1076 di = find_var_in_ht(ht, 0, 1170 di = find_var_in_ht(ht, 0, iptr->isn_arg.string + 2, TRUE);
1077 iptr->isn_arg.string + 2, TRUE);
1078 if (di == NULL) 1171 if (di == NULL)
1079 store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); 1172 store_var(iptr->isn_arg.string, STACK_TV_BOT(0));
1080 else 1173 else
1081 { 1174 {
1082 clear_tv(&di->di_tv); 1175 clear_tv(&di->di_tv);
1287 trycmd_T *trycmd = NULL; 1380 trycmd_T *trycmd = NULL;
1288 1381
1289 if (trystack->ga_len > 0) 1382 if (trystack->ga_len > 0)
1290 trycmd = ((trycmd_T *)trystack->ga_data) 1383 trycmd = ((trycmd_T *)trystack->ga_data)
1291 + trystack->ga_len - 1; 1384 + trystack->ga_len - 1;
1292 if (trycmd != NULL && trycmd->tcd_frame == ectx.ec_frame 1385 if (trycmd != NULL
1386 && trycmd->tcd_frame_idx == ectx.ec_frame_idx
1293 && trycmd->tcd_finally_idx != 0) 1387 && trycmd->tcd_finally_idx != 0)
1294 { 1388 {
1295 // jump to ":finally" 1389 // jump to ":finally"
1296 ectx.ec_iidx = trycmd->tcd_finally_idx; 1390 ectx.ec_iidx = trycmd->tcd_finally_idx;
1297 trycmd->tcd_return = TRUE; 1391 trycmd->tcd_return = TRUE;
1298 } 1392 }
1299 else 1393 else
1300 { 1394 {
1301 // Restore previous function. If the frame pointer 1395 // Restore previous function. If the frame pointer
1302 // is zero then there is none and we are done. 1396 // is zero then there is none and we are done.
1303 if (ectx.ec_frame == initial_frame_ptr) 1397 if (ectx.ec_frame_idx == initial_frame_idx)
1398 {
1399 if (handle_closure_in_use(&ectx, FALSE) == FAIL)
1400 goto failed;
1304 goto done; 1401 goto done;
1305 1402 }
1306 func_return(&ectx); 1403
1404 if (func_return(&ectx) == FAIL)
1405 goto failed;
1307 } 1406 }
1308 } 1407 }
1309 break; 1408 break;
1310 1409
1311 // push a function reference to a compiled function 1410 // push a function reference to a compiled function
1312 case ISN_FUNCREF: 1411 case ISN_FUNCREF:
1313 { 1412 {
1314 partial_T *pt = NULL; 1413 partial_T *pt = NULL;
1315 dfunc_T *dfunc; 1414 dfunc_T *pt_dfunc;
1316 1415
1317 pt = ALLOC_CLEAR_ONE(partial_T); 1416 pt = ALLOC_CLEAR_ONE(partial_T);
1318 if (pt == NULL) 1417 if (pt == NULL)
1319 goto failed; 1418 goto failed;
1320 dfunc = ((dfunc_T *)def_functions.ga_data) 1419 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1321 + iptr->isn_arg.number; 1420 {
1322 pt->pt_func = dfunc->df_ufunc; 1421 vim_free(pt);
1422 goto failed;
1423 }
1424 pt_dfunc = ((dfunc_T *)def_functions.ga_data)
1425 + iptr->isn_arg.funcref.fr_func;
1426 pt->pt_func = pt_dfunc->df_ufunc;
1323 pt->pt_refcount = 1; 1427 pt->pt_refcount = 1;
1324 ++dfunc->df_ufunc->uf_refcount; 1428 ++pt_dfunc->df_ufunc->uf_refcount;
1325 1429
1326 if (dfunc->df_ufunc->uf_flags & FC_CLOSURE) 1430 if (pt_dfunc->df_ufunc->uf_flags & FC_CLOSURE)
1327 { 1431 {
1328 // Closure needs to find local variables in the current 1432 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
1329 // stack. 1433 + ectx.ec_dfunc_idx;
1330 dfunc->df_ufunc->uf_ectx_stack = &ectx.ec_stack; 1434
1331 dfunc->df_ufunc->uf_ectx_frame = ectx.ec_frame; 1435 // The closure needs to find arguments and local
1332 } 1436 // variables in the current stack.
1333 1437 pt_dfunc->df_ectx_stack = &ectx.ec_stack;
1334 if (ga_grow(&ectx.ec_stack, 1) == FAIL) 1438 pt_dfunc->df_ectx_frame = ectx.ec_frame_idx;
1335 goto failed; 1439
1440 // If this function returns and the closure is still
1441 // used, we need to make a copy of the context
1442 // (arguments and local variables). Store a reference
1443 // to the partial so we can handle that.
1444 ++pt->pt_refcount;
1445 tv = STACK_TV_VAR(dfunc->df_varcount
1446 + iptr->isn_arg.funcref.fr_var_idx);
1447 if (tv->v_type == VAR_PARTIAL)
1448 {
1449 // TODO: use a garray_T on ectx.
1450 emsg("Multiple closures not supported yet");
1451 goto failed;
1452 }
1453 tv->v_type = VAR_PARTIAL;
1454 tv->vval.v_partial = pt;
1455 }
1456
1336 tv = STACK_TV_BOT(0); 1457 tv = STACK_TV_BOT(0);
1337 ++ectx.ec_stack.ga_len; 1458 ++ectx.ec_stack.ga_len;
1338 tv->vval.v_partial = pt; 1459 tv->vval.v_partial = pt;
1339 tv->v_type = VAR_PARTIAL; 1460 tv->v_type = VAR_PARTIAL;
1340 } 1461 }
1408 goto failed; 1529 goto failed;
1409 trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data) 1530 trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data)
1410 + ectx.ec_trystack.ga_len; 1531 + ectx.ec_trystack.ga_len;
1411 ++ectx.ec_trystack.ga_len; 1532 ++ectx.ec_trystack.ga_len;
1412 ++trylevel; 1533 ++trylevel;
1413 trycmd->tcd_frame = ectx.ec_frame; 1534 trycmd->tcd_frame_idx = ectx.ec_frame_idx;
1414 trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch; 1535 trycmd->tcd_catch_idx = iptr->isn_arg.try.try_catch;
1415 trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally; 1536 trycmd->tcd_finally_idx = iptr->isn_arg.try.try_finally;
1416 trycmd->tcd_caught = FALSE; 1537 trycmd->tcd_caught = FALSE;
1417 } 1538 }
1418 break; 1539 break;
1470 1591
1471 if (trycmd->tcd_return) 1592 if (trycmd->tcd_return)
1472 { 1593 {
1473 // Restore previous function. If the frame pointer 1594 // Restore previous function. If the frame pointer
1474 // is zero then there is none and we are done. 1595 // is zero then there is none and we are done.
1475 if (ectx.ec_frame == initial_frame_ptr) 1596 if (ectx.ec_frame_idx == initial_frame_idx)
1597 {
1598 if (handle_closure_in_use(&ectx, FALSE) == FAIL)
1599 goto failed;
1476 goto done; 1600 goto done;
1477 1601 }
1478 func_return(&ectx); 1602
1603 if (func_return(&ectx) == FAIL)
1604 goto failed;
1479 } 1605 }
1480 } 1606 }
1481 } 1607 }
1482 break; 1608 break;
1483 1609
1947 tv->v_type = VAR_UNKNOWN; 2073 tv->v_type = VAR_UNKNOWN;
1948 ret = OK; 2074 ret = OK;
1949 2075
1950 failed: 2076 failed:
1951 // When failed need to unwind the call stack. 2077 // When failed need to unwind the call stack.
1952 while (ectx.ec_frame != initial_frame_ptr) 2078 while (ectx.ec_frame_idx != initial_frame_idx)
1953 func_return(&ectx); 2079 func_return(&ectx);
1954 failed_early: 2080 failed_early:
1955 current_sctx.sc_version = save_sc_version; 2081 current_sctx.sc_version = save_sc_version;
2082
2083 // Free all local variables, but not arguments.
1956 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx) 2084 for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
1957 clear_tv(STACK_TV(idx)); 2085 clear_tv(STACK_TV(idx));
2086
1958 vim_free(ectx.ec_stack.ga_data); 2087 vim_free(ectx.ec_stack.ga_data);
1959 vim_free(ectx.ec_trystack.ga_data); 2088 vim_free(ectx.ec_trystack.ga_data);
1960 return ret; 2089 return ret;
1961 } 2090 }
1962 2091
2307 smsg("%4d RETURN", current); 2436 smsg("%4d RETURN", current);
2308 break; 2437 break;
2309 case ISN_FUNCREF: 2438 case ISN_FUNCREF:
2310 { 2439 {
2311 dfunc_T *df = ((dfunc_T *)def_functions.ga_data) 2440 dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
2312 + iptr->isn_arg.number; 2441 + iptr->isn_arg.funcref.fr_func;
2313 2442
2314 smsg("%4d FUNCREF %s", current, df->df_ufunc->uf_name); 2443 smsg("%4d FUNCREF %s $%d", current, df->df_ufunc->uf_name,
2444 iptr->isn_arg.funcref.fr_var_idx + df->df_varcount);
2315 } 2445 }
2316 break; 2446 break;
2317 2447
2318 case ISN_JUMP: 2448 case ISN_JUMP:
2319 { 2449 {