comparison src/vim9compile.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 6f9010b6f7f9
comparison
equal deleted inserted replaced
20246:ef2250432801 20247:e46e72aaff74
113 char_u *ctx_line_start; // start of current line or NULL 113 char_u *ctx_line_start; // start of current line or NULL
114 garray_T ctx_instr; // generated instructions 114 garray_T ctx_instr; // generated instructions
115 115
116 garray_T ctx_locals; // currently visible local variables 116 garray_T ctx_locals; // currently visible local variables
117 int ctx_locals_count; // total number of local variables 117 int ctx_locals_count; // total number of local variables
118
119 int ctx_closure_count; // number of closures created in the
120 // function
118 121
119 garray_T ctx_imports; // imported items 122 garray_T ctx_imports; // imported items
120 123
121 int ctx_skip; // when TRUE skip commands, when FALSE skip 124 int ctx_skip; // when TRUE skip commands, when FALSE skip
122 // commands after "else" 125 // commands after "else"
1252 garray_T *stack = &cctx->ctx_type_stack; 1255 garray_T *stack = &cctx->ctx_type_stack;
1253 1256
1254 RETURN_OK_IF_SKIP(cctx); 1257 RETURN_OK_IF_SKIP(cctx);
1255 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL) 1258 if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
1256 return FAIL; 1259 return FAIL;
1257 isn->isn_arg.number = dfunc_idx; 1260 isn->isn_arg.funcref.fr_func = dfunc_idx;
1261 isn->isn_arg.funcref.fr_var_idx = cctx->ctx_closure_count++;
1258 1262
1259 if (ga_grow(stack, 1) == FAIL) 1263 if (ga_grow(stack, 1) == FAIL)
1260 return FAIL; 1264 return FAIL;
1261 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any; 1265 ((type_T **)stack->ga_data)[stack->ga_len] = &t_func_any;
1262 // TODO: argument and return types 1266 // TODO: argument and return types
6393 + ufunc->uf_dfunc_idx; 6397 + ufunc->uf_dfunc_idx;
6394 dfunc->df_deleted = FALSE; 6398 dfunc->df_deleted = FALSE;
6395 dfunc->df_instr = instr->ga_data; 6399 dfunc->df_instr = instr->ga_data;
6396 dfunc->df_instr_count = instr->ga_len; 6400 dfunc->df_instr_count = instr->ga_len;
6397 dfunc->df_varcount = cctx.ctx_locals_count; 6401 dfunc->df_varcount = cctx.ctx_locals_count;
6402 dfunc->df_closure_count = cctx.ctx_closure_count;
6398 if (cctx.ctx_outer_used) 6403 if (cctx.ctx_outer_used)
6399 ufunc->uf_flags |= FC_CLOSURE; 6404 ufunc->uf_flags |= FC_CLOSURE;
6400 } 6405 }
6401 6406
6402 { 6407 {
6618 { 6623 {
6619 for (idx = 0; idx < dfunc->df_instr_count; ++idx) 6624 for (idx = 0; idx < dfunc->df_instr_count; ++idx)
6620 delete_instr(dfunc->df_instr + idx); 6625 delete_instr(dfunc->df_instr + idx);
6621 VIM_CLEAR(dfunc->df_instr); 6626 VIM_CLEAR(dfunc->df_instr);
6622 } 6627 }
6628 if (dfunc->df_funcstack != NULL)
6629 {
6630 // Decrease the reference count for the context of a closure. If down
6631 // to zero free it and clear the variables on the stack.
6632 if (--dfunc->df_funcstack->fs_refcount == 0)
6633 {
6634 garray_T *gap = &dfunc->df_funcstack->fs_ga;
6635 typval_T *stack = gap->ga_data;
6636 int i;
6637
6638 for (i = 0; i < gap->ga_len; ++i)
6639 clear_tv(stack + i);
6640 ga_clear(gap);
6641 vim_free(dfunc->df_funcstack);
6642 }
6643 dfunc->df_funcstack = NULL;
6644 }
6623 6645
6624 dfunc->df_deleted = TRUE; 6646 dfunc->df_deleted = TRUE;
6625 } 6647 }
6626 6648
6627 /* 6649 /*