Patch 8.2.0528
Problem:    Vim9: function arguments insufficiently tested.
Solution:   Check types.  Add more tests.  Fix function with varargs only.
Files:      src/vim9compile.c, src/userfunc.c, src/testdir/test_vim9_func.vim


*** ../vim-8.2.0527/src/vim9compile.c   2020-04-07 20:53:35.218912046 +0200
--- src/vim9compile.c   2020-04-07 21:58:16.747087832 +0200
***************
*** 130,135 ****
--- 130,137 ----
  static int compile_expr2(char_u **arg,  cctx_T *cctx);
  static int compile_expr3(char_u **arg,  cctx_T *cctx);
  static void delete_def_function_contents(dfunc_T *dfunc);
+ static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
+ static int check_type(type_T *expected, type_T *actual, int give_msg);
  
  /*
   * Lookup variable "name" in the local scope and return the index.
***************
*** 1240,1245 ****
--- 1242,1273 ----
        return FAIL;
      }
  
+     if (ufunc->uf_dfunc_idx >= 0)
+     {
+       int             i;
+ 
+       for (i = 0; i < argcount; ++i)
+       {
+           type_T *expected;
+           type_T *actual;
+ 
+           if (i < regular_args)
+           {
+               if (ufunc->uf_arg_types == NULL)
+                   continue;
+               expected = ufunc->uf_arg_types[i];
+           }
+           else
+               expected = ufunc->uf_va_type->tt_member;
+           actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i];
+           if (check_type(expected, actual, FALSE) == FAIL)
+           {
+               arg_type_mismatch(expected, actual, i + 1);
+               return FAIL;
+           }
+       }
+     }
+ 
      // Turn varargs into a list.
      if (ufunc->uf_va_name != NULL)
      {
***************
*** 2402,2407 ****
--- 2430,2447 ----
      vim_free(tofree1);
      vim_free(tofree2);
  }
+ 
+     static void
+ arg_type_mismatch(type_T *expected, type_T *actual, int argidx)
+ {
+     char *tofree1, *tofree2;
+ 
+     semsg(_("E1013: argument %d: type mismatch, expected %s but got %s"),
+           argidx,
+           type_name(expected, &tofree1), type_name(actual, &tofree2));
+     vim_free(tofree1);
+     vim_free(tofree2);
+ }
  
  /*
   * Check if the expected and actual types match.
*** ../vim-8.2.0527/src/userfunc.c      2020-04-06 22:12:57.141652839 +0200
--- src/userfunc.c      2020-04-07 21:23:21.803935303 +0200
***************
*** 3020,3026 ****
  
      if (eap->cmdidx == CMD_def)
      {
!       int lnum_save = SOURCING_LNUM;
  
        // error messages are for the first function line
        SOURCING_LNUM = sourcing_lnum_top;
--- 3020,3026 ----
  
      if (eap->cmdidx == CMD_def)
      {
!       int     lnum_save = SOURCING_LNUM;
  
        // error messages are for the first function line
        SOURCING_LNUM = sourcing_lnum_top;
***************
*** 3034,3040 ****
            // and uf_va_type.
            int len = argtypes.ga_len - (varargs ? 1 : 0);
  
!           fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len);
            if (fp->uf_arg_types != NULL)
            {
                int     i;
--- 3034,3041 ----
            // and uf_va_type.
            int len = argtypes.ga_len - (varargs ? 1 : 0);
  
!           if (len > 0)
!               fp->uf_arg_types = ALLOC_CLEAR_MULT(type_T *, len);
            if (fp->uf_arg_types != NULL)
            {
                int     i;
*** ../vim-8.2.0527/src/testdir/test_vim9_func.vim      2020-04-07 
20:53:35.218912046 +0200
--- src/testdir/test_vim9_func.vim      2020-04-07 21:49:25.593250238 +0200
***************
*** 130,135 ****
--- 130,148 ----
    assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
  enddef
  
+ " Only varargs
+ def MyVarargsOnly(...args: list<string>): string
+   return join(args, ',')
+ enddef
+ 
+ def Test_call_varargs_only()
+   assert_equal('', MyVarargsOnly())
+   assert_equal('one', MyVarargsOnly('one'))
+   assert_equal('one,two', MyVarargsOnly('one', 'two'))
+   call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type 
mismatch, expected string but got number')
+   call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type 
mismatch, expected string but got number')
+ enddef
+ 
  def Test_using_var_as_arg()
    call writefile(['def Func(x: number)',  'let x = 234', 'enddef'], 'Xdef')
    call assert_fails('so Xdef', 'E1006:')
*** ../vim-8.2.0527/src/version.c       2020-04-07 20:53:35.218912046 +0200
--- src/version.c       2020-04-07 22:03:07.101926072 +0200
***************
*** 740,741 ****
--- 740,743 ----
  {   /* Add new patch number below this line */
+ /**/
+     528,
  /**/

-- 
Females are strictly forbidden to appear unshaven in public.
                [real standing law in New Mexico, United States of America]

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202004072005.037K5ZSM027071%40masaka.moolenaar.net.

Raspunde prin e-mail lui