comparison src/vim9execute.c @ 20244:23d75968ca5e

patch 8.2.0677: Vim9: no support for closures Commit: https://github.com/vim/vim/commit/c8cd2b34d1027c93fbca90f3cdc8123fe22dfa25 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 1 19:29:08 2020 +0200 patch 8.2.0677: Vim9: no support for closures Problem: Vim9: no support for closures. Solution: Find variables in the outer function scope, so long as the scope exists.
author Bram Moolenaar <Bram@vim.org>
date Fri, 01 May 2020 19:30:04 +0200
parents eaaee0dfa435
children e46e72aaff74
comparison
equal deleted inserted replaced
20243:6e7fd8949651 20244:23d75968ca5e
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; // index in ec_stack: context of ec_dfunc_idx
60
61 garray_T *ec_outer_stack; // stack used for closures
62 int ec_outer_frame; // stack frame in ec_outer_stack
60 63
61 garray_T ec_trystack; // stack of trycmd_T values 64 garray_T ec_trystack; // stack of trycmd_T values
62 int ec_in_catch; // when TRUE in catch or finally block 65 int ec_in_catch; // when TRUE in catch or finally block
63 66
64 int ec_dfunc_idx; // current function index 67 int ec_dfunc_idx; // current function index
227 // Set execution state to the start of the called function. 230 // Set execution state to the start of the called function.
228 ectx->ec_dfunc_idx = cdf_idx; 231 ectx->ec_dfunc_idx = cdf_idx;
229 ectx->ec_instr = dfunc->df_instr; 232 ectx->ec_instr = dfunc->df_instr;
230 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1); 233 estack_push_ufunc(ETYPE_UFUNC, dfunc->df_ufunc, 1);
231 234
235 // used for closures
236 ectx->ec_outer_stack = ufunc->uf_ectx_stack;
237 ectx->ec_outer_frame = ufunc->uf_ectx_frame;
238
232 // Decide where to start execution, handles optional arguments. 239 // Decide where to start execution, handles optional arguments.
233 init_instr_idx(ufunc, argcount, ectx); 240 init_instr_idx(ufunc, argcount, ectx);
234 241
235 return OK; 242 return OK;
236 } 243 }
505 #undef STACK_TV_BOT 512 #undef STACK_TV_BOT
506 #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx) 513 #define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx)
507 514
508 // Get pointer to a local variable on the stack. Negative for arguments. 515 // Get pointer to a local variable on the stack. Negative for arguments.
509 #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame + STACK_FRAME_SIZE + idx) 516 #define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame + STACK_FRAME_SIZE + idx)
517
518 // 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)
510 520
511 CLEAR_FIELD(ectx); 521 CLEAR_FIELD(ectx);
512 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); 522 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
513 if (ga_grow(&ectx.ec_stack, 20) == FAIL) 523 if (ga_grow(&ectx.ec_stack, 20) == FAIL)
514 return FAIL; 524 return FAIL;
781 // load local variable or argument 791 // load local variable or argument
782 case ISN_LOAD: 792 case ISN_LOAD:
783 if (ga_grow(&ectx.ec_stack, 1) == FAIL) 793 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
784 goto failed; 794 goto failed;
785 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); 795 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
796 ++ectx.ec_stack.ga_len;
797 break;
798
799 // load variable or argument from outer scope
800 case ISN_LOADOUTER:
801 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
802 goto failed;
803 copy_tv(STACK_OUT_TV_VAR(iptr->isn_arg.number),
804 STACK_TV_BOT(0));
786 ++ectx.ec_stack.ga_len; 805 ++ectx.ec_stack.ga_len;
787 break; 806 break;
788 807
789 // load v: variable 808 // load v: variable
790 case ISN_LOADV: 809 case ISN_LOADV:
1302 + iptr->isn_arg.number; 1321 + iptr->isn_arg.number;
1303 pt->pt_func = dfunc->df_ufunc; 1322 pt->pt_func = dfunc->df_ufunc;
1304 pt->pt_refcount = 1; 1323 pt->pt_refcount = 1;
1305 ++dfunc->df_ufunc->uf_refcount; 1324 ++dfunc->df_ufunc->uf_refcount;
1306 1325
1326 if (dfunc->df_ufunc->uf_flags & FC_CLOSURE)
1327 {
1328 // Closure needs to find local variables in the current
1329 // stack.
1330 dfunc->df_ufunc->uf_ectx_stack = &ectx.ec_stack;
1331 dfunc->df_ufunc->uf_ectx_frame = ectx.ec_frame;
1332 }
1333
1307 if (ga_grow(&ectx.ec_stack, 1) == FAIL) 1334 if (ga_grow(&ectx.ec_stack, 1) == FAIL)
1308 goto failed; 1335 goto failed;
1309 tv = STACK_TV_BOT(0); 1336 tv = STACK_TV_BOT(0);
1310 ++ectx.ec_stack.ga_len; 1337 ++ectx.ec_stack.ga_len;
1311 tv->vval.v_partial = pt; 1338 tv->vval.v_partial = pt;
1860 case ISN_CHECKTYPE: 1887 case ISN_CHECKTYPE:
1861 { 1888 {
1862 checktype_T *ct = &iptr->isn_arg.type; 1889 checktype_T *ct = &iptr->isn_arg.type;
1863 1890
1864 tv = STACK_TV_BOT(ct->ct_off); 1891 tv = STACK_TV_BOT(ct->ct_off);
1865 if (tv->v_type != ct->ct_type) 1892 // TODO: better type comparison
1893 if (tv->v_type != ct->ct_type
1894 && !((tv->v_type == VAR_PARTIAL
1895 && ct->ct_type == VAR_FUNC)
1896 || (tv->v_type == VAR_FUNC
1897 && ct->ct_type == VAR_PARTIAL)))
1866 { 1898 {
1867 semsg(_("E1029: Expected %s but got %s"), 1899 semsg(_("E1029: Expected %s but got %s"),
1868 vartype_name(ct->ct_type), 1900 vartype_name(ct->ct_type),
1869 vartype_name(tv->v_type)); 1901 vartype_name(tv->v_type));
1870 goto failed; 1902 goto failed;
2027 case ISN_ECHOERR: 2059 case ISN_ECHOERR:
2028 smsg("%4d ECHOERR %lld", current, 2060 smsg("%4d ECHOERR %lld", current,
2029 (long long)(iptr->isn_arg.number)); 2061 (long long)(iptr->isn_arg.number));
2030 break; 2062 break;
2031 case ISN_LOAD: 2063 case ISN_LOAD:
2032 if (iptr->isn_arg.number < 0) 2064 case ISN_LOADOUTER:
2033 smsg("%4d LOAD arg[%lld]", current, 2065 {
2034 (long long)(iptr->isn_arg.number + STACK_FRAME_SIZE)); 2066 char *add = iptr->isn_type == ISN_LOAD ? "" : "OUTER";
2035 else 2067
2036 smsg("%4d LOAD $%lld", current, 2068 if (iptr->isn_arg.number < 0)
2069 smsg("%4d LOAD%s arg[%lld]", current, add,
2070 (long long)(iptr->isn_arg.number
2071 + STACK_FRAME_SIZE));
2072 else
2073 smsg("%4d LOAD%s $%lld", current, add,
2037 (long long)(iptr->isn_arg.number)); 2074 (long long)(iptr->isn_arg.number));
2075 }
2038 break; 2076 break;
2039 case ISN_LOADV: 2077 case ISN_LOADV:
2040 smsg("%4d LOADV v:%s", current, 2078 smsg("%4d LOADV v:%s", current,
2041 get_vim_var_name(iptr->isn_arg.number)); 2079 get_vim_var_name(iptr->isn_arg.number));
2042 break; 2080 break;