To: vim_dev@googlegroups.com Subject: Patch 8.2.0771 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0771 Problem: Vim9: cannot call a compiled closure from not compiled code. Solution: Pass funcexe to call_user_func(). Files: src/userfunc.c, src/vim9execute.c, src/proto/vim9execute.pro, src/eval.c, src/testdir/test_vim9_func.vim *** ../vim-8.2.0770/src/userfunc.c 2020-05-14 22:41:10.229637563 +0200 --- src/userfunc.c 2020-05-16 20:59:58.172798823 +0200 *************** *** 1062,1069 **** int argcount, // nr of args typval_T *argvars, // arguments typval_T *rettv, // return value ! linenr_T firstline, // first line of range ! linenr_T lastline, // last line of range dict_T *selfdict) // Dictionary for "self" { sctx_T save_current_sctx; --- 1062,1068 ---- int argcount, // nr of args typval_T *argvars, // arguments typval_T *rettv, // return value ! funcexe_T *funcexe, // context dict_T *selfdict) // Dictionary for "self" { sctx_T save_current_sctx; *************** *** 1120,1126 **** current_sctx = fp->uf_script_ctx; // Execute the compiled function. ! call_def_function(fp, argcount, argvars, rettv); --depth; current_funccal = fc->caller; --- 1119,1125 ---- current_sctx = fp->uf_script_ctx; // Execute the compiled function. ! call_def_function(fp, argcount, argvars, funcexe->partial, rettv); --depth; current_funccal = fc->caller; *************** *** 1194,1202 **** if ((fp->uf_flags & FC_NOARGS) == 0) { add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline", ! (varnumber_T)firstline); add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline", ! (varnumber_T)lastline); } for (i = 0; i < argcount || i < fp->uf_args.ga_len; ++i) { --- 1193,1201 ---- if ((fp->uf_flags & FC_NOARGS) == 0) { add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline", ! (varnumber_T)funcexe->firstline); add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline", ! (varnumber_T)funcexe->lastline); } for (i = 0; i < argcount || i < fp->uf_args.ga_len; ++i) { *************** *** 1515,1523 **** did_save_redo = TRUE; } ++fp->uf_calls; ! call_user_func(fp, argcount, argvars, rettv, ! funcexe->firstline, funcexe->lastline, ! (fp->uf_flags & FC_DICT) ? selfdict : NULL); if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0) // Function was unreferenced while being used, free it now. func_clear_free(fp, FALSE); --- 1514,1521 ---- did_save_redo = TRUE; } ++fp->uf_calls; ! call_user_func(fp, argcount, argvars, rettv, funcexe, ! (fp->uf_flags & FC_DICT) ? selfdict : NULL); if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0) // Function was unreferenced while being used, free it now. func_clear_free(fp, FALSE); *************** *** 4293,4299 **** if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) return NULL; ! // Search in parent scope which is possible to reference from lambda current_funccal = current_funccal->func->uf_scoped; while (current_funccal != NULL) { --- 4291,4297 ---- if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) return NULL; ! // Search in parent scope, which can be referenced from a lambda. current_funccal = current_funccal->func->uf_scoped; while (current_funccal != NULL) { *** ../vim-8.2.0770/src/vim9execute.c 2020-05-16 15:43:26.694803322 +0200 --- src/vim9execute.c 2020-05-16 21:15:44.650124778 +0200 *************** *** 641,646 **** --- 641,647 ---- ufunc_T *ufunc, int argc_arg, // nr of arguments typval_T *argv, // arguments + partial_T *partial, // optional partial for context typval_T *rettv) // return value { ectx_T ectx; // execution context *************** *** 720,725 **** --- 721,732 ---- ectx.ec_frame_idx = ectx.ec_stack.ga_len; initial_frame_idx = ectx.ec_frame_idx; + if (partial != NULL) + { + ectx.ec_outer_stack = partial->pt_ectx_stack; + ectx.ec_outer_frame = partial->pt_ectx_frame; + } + // dummy frame entries for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) { *************** *** 1468,1474 **** { cpfunc_T *pfunc = &iptr->isn_arg.pfunc; int r; ! typval_T partial; SOURCING_LNUM = iptr->isn_lnum; if (pfunc->cpf_top) --- 1475,1481 ---- { cpfunc_T *pfunc = &iptr->isn_arg.pfunc; int r; ! typval_T partial_tv; SOURCING_LNUM = iptr->isn_lnum; if (pfunc->cpf_top) *************** *** 1480,1491 **** { // Get the funcref from the stack. --ectx.ec_stack.ga_len; ! partial = *STACK_TV_BOT(0); ! tv = &partial; } r = call_partial(tv, pfunc->cpf_argcount, &ectx); ! if (tv == &partial) ! clear_tv(&partial); if (r == FAIL) goto failed; } --- 1487,1498 ---- { // Get the funcref from the stack. --ectx.ec_stack.ga_len; ! partial_tv = *STACK_TV_BOT(0); ! tv = &partial_tv; } r = call_partial(tv, pfunc->cpf_argcount, &ectx); ! if (tv == &partial_tv) ! clear_tv(&partial_tv); if (r == FAIL) goto failed; } *** ../vim-8.2.0770/src/proto/vim9execute.pro 2020-05-02 23:12:54.722410350 +0200 --- src/proto/vim9execute.pro 2020-05-16 21:02:15.800345042 +0200 *************** *** 1,7 **** /* vim9execute.c */ ! int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, typval_T *rettv); void ex_disassemble(exarg_T *eap); int tv2bool(typval_T *tv); int check_not_string(typval_T *tv); - int set_ref_in_dfunc(ufunc_T *ufunc, int copyID); /* vim: set ft=c : */ --- 1,6 ---- /* vim9execute.c */ ! int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, partial_T *partial, typval_T *rettv); void ex_disassemble(exarg_T *eap); int tv2bool(typval_T *tv); int check_not_string(typval_T *tv); /* vim: set ft=c : */ *** ../vim-8.2.0770/src/eval.c 2020-05-15 18:17:24.590759529 +0200 --- src/eval.c 2020-05-16 21:02:37.448273698 +0200 *************** *** 246,252 **** if (partial->pt_func != NULL && partial->pt_func->uf_dfunc_idx >= 0) { ! if (call_def_function(partial->pt_func, argc, argv, rettv) == FAIL) return FAIL; } else --- 246,253 ---- if (partial->pt_func != NULL && partial->pt_func->uf_dfunc_idx >= 0) { ! if (call_def_function(partial->pt_func, argc, argv, ! partial, rettv) == FAIL) return FAIL; } else *** ../vim-8.2.0770/src/testdir/test_vim9_func.vim 2020-05-10 22:53:51.282678776 +0200 --- src/testdir/test_vim9_func.vim 2020-05-16 21:14:11.414401321 +0200 *************** *** 792,796 **** --- 792,806 ---- assert_equal('text!!!', Closure('!!!')) enddef + func GetResult(Ref) + return a:Ref('some') + endfunc + + def Test_call_closure_not_compiled() + let text = 'text' + g:Ref = {s -> s .. text} + assert_equal('sometext', GetResult(g:Ref)) + enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker *** ../vim-8.2.0770/src/version.c 2020-05-16 18:57:48.041181143 +0200 --- src/version.c 2020-05-16 21:19:41.537408820 +0200 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 771, /**/ -- hundred-and-one symptoms of being an internet addict: 111. You and your friends get together regularly on IRC, even though all of you live in the same street. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///