]> granicus.if.org Git - vim/commitdiff
patch 8.2.0771: Vim9: cannot call a compiled closure from not compiled code v8.2.0771
authorBram Moolenaar <Bram@vim.org>
Sat, 16 May 2020 19:20:12 +0000 (21:20 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 16 May 2020 19:20:12 +0000 (21:20 +0200)
Problem:    Vim9: cannot call a compiled closure from not compiled code.
Solution:   Pass funcexe to call_user_func().

src/eval.c
src/proto/vim9execute.pro
src/testdir/test_vim9_func.vim
src/userfunc.c
src/version.c
src/vim9execute.c

index 77359dccaa0ba4c36f3223b9d5b96e59c1365f21..dbc10c1b69c097323601f65665dd63e09c43da8e 100644 (file)
@@ -246,7 +246,8 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
 
        if (partial->pt_func != NULL && partial->pt_func->uf_dfunc_idx >= 0)
        {
-           if (call_def_function(partial->pt_func, argc, argv, rettv) == FAIL)
+           if (call_def_function(partial->pt_func, argc, argv,
+                                                      partial, rettv) == FAIL)
                return FAIL;
        }
        else
index 578fe81e1ba27214a203fd4fdb2ed271fca76968..eac8979afc523e063e5fd8c8cb263808340e5282 100644 (file)
@@ -1,7 +1,6 @@
 /* vim9execute.c */
-int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, typval_T *rettv);
+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);
-int set_ref_in_dfunc(ufunc_T *ufunc, int copyID);
 /* vim: set ft=c : */
index c74b4a4510c37317a89ba85e40a2fdf62ec4c64f..100d86aa667b6f91d8c96b975b8903c387f176b4 100644 (file)
@@ -792,5 +792,15 @@ def Test_nested_closure()
   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
index b3c4f900a1c5094b12ea16f8497b50452064b0d5..99c45b3e76311c1b6623e1c25a3e5ead293f7797 100644 (file)
@@ -1062,8 +1062,7 @@ call_user_func(
     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
+    funcexe_T  *funcexe,       // context
     dict_T     *selfdict)      // Dictionary for "self"
 {
     sctx_T     save_current_sctx;
@@ -1120,7 +1119,7 @@ call_user_func(
        current_sctx = fp->uf_script_ctx;
 
        // Execute the compiled function.
-       call_def_function(fp, argcount, argvars, rettv);
+       call_def_function(fp, argcount, argvars, funcexe->partial, rettv);
        --depth;
        current_funccal = fc->caller;
 
@@ -1194,9 +1193,9 @@ call_user_func(
     if ((fp->uf_flags & FC_NOARGS) == 0)
     {
        add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "firstline",
-                                                     (varnumber_T)firstline);
+                                             (varnumber_T)funcexe->firstline);
        add_nr_var(&fc->l_avars, &fc->fixvar[fixvar_idx++].var, "lastline",
-                                                      (varnumber_T)lastline);
+                                              (varnumber_T)funcexe->lastline);
     }
     for (i = 0; i < argcount || i < fp->uf_args.ga_len; ++i)
     {
@@ -1515,9 +1514,8 @@ call_user_func_check(
            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);
+       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,7 +4291,7 @@ find_hi_in_scoped_ht(char_u *name, hashtab_T **pht)
     if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL)
       return NULL;
 
-    // Search in parent scope which is possible to reference from lambda
+    // Search in parent scope, which can be referenced from a lambda.
     current_funccal = current_funccal->func->uf_scoped;
     while (current_funccal != NULL)
     {
index 277650488c6f7f235c940fe482077d349ae8d9b7..c369a716060b28164f6a4238b5b4ce7b03660205 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    771,
 /**/
     770,
 /**/
index c910dbc96bdeed277aef41bfae78782f5e022f5a..fe6adda601c6f6afad31aa974188e3beb0ebfa5f 100644 (file)
@@ -641,6 +641,7 @@ call_def_function(
     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,6 +721,12 @@ call_def_function(
     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,7 +1475,7 @@ call_def_function(
                {
                    cpfunc_T    *pfunc = &iptr->isn_arg.pfunc;
                    int         r;
-                   typval_T    partial;
+                   typval_T    partial_tv;
 
                    SOURCING_LNUM = iptr->isn_lnum;
                    if (pfunc->cpf_top)
@@ -1480,12 +1487,12 @@ call_def_function(
                    {
                        // Get the funcref from the stack.
                        --ectx.ec_stack.ga_len;
-                       partial = *STACK_TV_BOT(0);
-                       tv = &partial;
+                       partial_tv = *STACK_TV_BOT(0);
+                       tv = &partial_tv;
                    }
                    r = call_partial(tv, pfunc->cpf_argcount, &ectx);
-                   if (tv == &partial)
-                       clear_tv(&partial);
+                   if (tv == &partial_tv)
+                       clear_tv(&partial_tv);
                    if (r == FAIL)
                        goto failed;
                }