]> granicus.if.org Git - vim/commitdiff
patch 8.2.0564: Vim9: calling a def function from non-vim9 may fail v8.2.0564
authorBram Moolenaar <Bram@vim.org>
Sun, 12 Apr 2020 20:22:31 +0000 (22:22 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 12 Apr 2020 20:22:31 +0000 (22:22 +0200)
Problem:    Vim9: calling a def function from non-vim9 may fail.
Solution:   Convert varargs to a list.

src/testdir/test_vim9_func.vim
src/version.c
src/vim9execute.c

index 38d7c5a5a026a213de745744d9c67d4a414e14bd..c98acc906d3c6e11f09179f6335eee99c559048e 100644 (file)
@@ -576,6 +576,13 @@ def Test_multiline()
   assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
 enddef
 
+func Test_multiline_not_vim9()
+  call assert_equal('text1234', MultiLine('text'))
+  call assert_equal('text777', MultiLine('text', 777))
+  call assert_equal('text777one', MultiLine('text', 777, 'one'))
+  call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
+endfunc
+
 
 " When using CheckScriptFailure() for the below test, E1010 is generated instead
 " of E1056.
index d43c9d578793abdba108fcf43de371ba162ddfc2..7b40fa4cb64b827a1aaa75c6c5cc9d9ab241eef0 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    564,
 /**/
     563,
 /**/
index f8fb061f8401a99bfdb5d52dfbb66839f497574a..4ac760e66d4fcb30c74fb15b6c3452eec37c715b 100644 (file)
@@ -477,11 +477,12 @@ call_eval_func(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
     int
 call_def_function(
     ufunc_T    *ufunc,
-    int                argc,           // nr of arguments
+    int                argc_arg,       // nr of arguments
     typval_T   *argv,          // arguments
     typval_T   *rettv)         // return value
 {
     ectx_T     ectx;           // execution context
+    int                argc = argc_arg;
     int                initial_frame_ptr;
     typval_T   *tv;
     int                idx;
@@ -512,13 +513,34 @@ call_def_function(
        copy_tv(&argv[idx], STACK_TV_BOT(0));
        ++ectx.ec_stack.ga_len;
     }
+
+    // Turn varargs into a list.  Empty list if no args.
+    if (ufunc->uf_va_name != NULL)
+    {
+       int vararg_count = argc - ufunc->uf_args.ga_len;
+
+       if (vararg_count < 0)
+           vararg_count = 0;
+       else
+           argc -= vararg_count;
+       if (exe_newlist(vararg_count, &ectx) == FAIL)
+           goto failed;
+       if (defcount > 0)
+           // Move varargs list to below missing default arguments.
+           *STACK_TV_BOT(defcount- 1) = *STACK_TV_BOT(-1);
+       --ectx.ec_stack.ga_len;
+    }
+
     // Make space for omitted arguments, will store default value below.
+    // Any varargs list goes after them.
     if (defcount > 0)
        for (idx = 0; idx < defcount; ++idx)
        {
            STACK_TV_BOT(0)->v_type = VAR_UNKNOWN;
            ++ectx.ec_stack.ga_len;
        }
+    if (ufunc->uf_va_name != NULL)
+           ++ectx.ec_stack.ga_len;
 
     // Frame pointer points to just after arguments.
     ectx.ec_frame = ectx.ec_stack.ga_len;