Patch 8.2.0693
Problem:    Closure using argument not tested.
Solution:   Add a test, make it work.
Files:      src/vim9compile.c, src/testdir/test_vim9_func.vim


*** ../vim-8.2.0692/src/vim9compile.c   2020-05-03 15:47:29.989697193 +0200
--- src/vim9compile.c   2020-05-03 22:24:09.820259941 +0200
***************
*** 186,222 ****
  }
  
  /*
!  * Lookup an argument in the current function.
!  * Returns the argument index or -1 if not found.
   */
      static int
! lookup_arg(char_u *name, size_t len, cctx_T *cctx)
  {
      int           idx;
  
      if (len == 0)
!       return -1;
      for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
      {
        char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
  
!       if (STRNCMP(name, arg, len) == 0 && STRLEN(arg) == len)
!           return idx;
      }
-     return -1;
- }
  
! /*
!  * Lookup a vararg argument in the current function.
!  * Returns TRUE if there is a match.
!  */
!     static int
! lookup_vararg(char_u *name, size_t len, cctx_T *cctx)
! {
!     char_u  *va_name = cctx->ctx_ufunc->uf_va_name;
  
!     return len > 0 && va_name != NULL
!                && STRNCMP(name, va_name, len) == 0 && STRLEN(va_name) == len;
  }
  
  /*
--- 186,259 ----
  }
  
  /*
!  * Lookup an argument in the current function and an enclosing function.
!  * Returns the argument index in "idxp"
!  * Returns the argument type in "type"
!  * Sets "gen_load_outer" to TRUE if found in outer scope.
!  * Returns OK when found, FAIL otherwise.
   */
      static int
! lookup_arg(
!       char_u  *name,
!       size_t  len,
!       int     *idxp,
!       type_T  **type,
!       int     *gen_load_outer,
!       cctx_T  *cctx)
  {
      int           idx;
+     char_u  *va_name;
  
      if (len == 0)
!       return FAIL;
      for (idx = 0; idx < cctx->ctx_ufunc->uf_args.ga_len; ++idx)
      {
        char_u *arg = FUNCARG(cctx->ctx_ufunc, idx);
  
!       if (STRNCMP(name, arg, len) == 0 && arg[len] == NUL)
!       {
!           if (idxp != NULL)
!           {
!               // Arguments are located above the frame pointer.  One further
!               // if there is a vararg argument
!               *idxp = idx - (cctx->ctx_ufunc->uf_args.ga_len
!                                                           + STACK_FRAME_SIZE)
!                             + (cctx->ctx_ufunc->uf_va_name != NULL ? -1 : 0);
! 
!               if (cctx->ctx_ufunc->uf_arg_types != NULL)
!                   *type = cctx->ctx_ufunc->uf_arg_types[idx];
!               else
!                   *type = &t_any;
!           }
!           return OK;
!       }
      }
  
!     va_name = cctx->ctx_ufunc->uf_va_name;
!     if (va_name != NULL
!                   && STRNCMP(name, va_name, len) == 0 && va_name[len] == NUL)
!     {
!       if (idxp != NULL)
!       {
!           // varargs is always the last argument
!           *idxp = -STACK_FRAME_SIZE - 1;
!           *type = cctx->ctx_ufunc->uf_va_type;
!       }
!       return OK;
!     }
! 
!     if (cctx->ctx_outer != NULL)
!     {
!       // Lookup the name for an argument of the outer function.
!       if (lookup_arg(name, len, idxp, type, gen_load_outer, cctx->ctx_outer)
!                                                                        == OK)
!       {
!           *gen_load_outer = TRUE;
!           return OK;
!       }
!     }
  
!     return FAIL;
  }
  
  /*
***************
*** 1584,1590 ****
  {
      lvar_T  *lvar;
  
!     if (lookup_arg(name, len, cctx) >= 0 || lookup_vararg(name, len, cctx))
      {
        emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
        return NULL;
--- 1621,1627 ----
  {
      lvar_T  *lvar;
  
!     if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK)
      {
        emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
        return NULL;
***************
*** 2452,2477 ****
        if (name == NULL)
            return FAIL;
  
!       idx = lookup_arg(*arg, len, cctx);
!       if (idx >= 0)
!       {
!           if (cctx->ctx_ufunc->uf_arg_types != NULL)
!               type = cctx->ctx_ufunc->uf_arg_types[idx];
!           else
!               type = &t_any;
! 
!           // Arguments are located above the frame pointer.
!           idx -= cctx->ctx_ufunc->uf_args.ga_len + STACK_FRAME_SIZE;
!           if (cctx->ctx_ufunc->uf_va_name != NULL)
!               --idx;
!           gen_load = TRUE;
!       }
!       else if (lookup_vararg(*arg, len, cctx))
        {
!           // varargs is always the last argument
!           idx = -STACK_FRAME_SIZE - 1;
!           type = cctx->ctx_ufunc->uf_va_type;
!           gen_load = TRUE;
        }
        else
        {
--- 2489,2498 ----
        if (name == NULL)
            return FAIL;
  
!       if (lookup_arg(*arg, len, &idx, &type, &gen_load_outer, cctx) == OK)
        {
!           if (!gen_load_outer)
!               gen_load = TRUE;
        }
        else
        {
*** ../vim-8.2.0692/src/testdir/test_vim9_func.vim      2020-05-03 
15:38:12.987700652 +0200
--- src/testdir/test_vim9_func.vim      2020-05-03 22:28:44.471145390 +0200
***************
*** 700,704 ****
--- 700,725 ----
    unlet g:Read
  enddef
  
+ def MakeArgRefs(theArg: string)
+   let local = 'loc_val'
+   g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s}
+ enddef
+ 
+ def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
+   let local = 'the_loc'
+   g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)}
+ enddef
+ 
+ def Test_closure_using_argument()
+   MakeArgRefs('arg_val')
+   assert_equal('arg_val/loc_val/call_val', g:UseArg('call_val'))
+ 
+   MakeArgRefsVarargs('arg_val', 'one', 'two')
+   assert_equal('arg_val/the_loc/call_val/one two', g:UseVararg('call_val'))
+ 
+   unlet g:UseArg
+   unlet g:UseVararg
+ enddef
+ 
  
  " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
*** ../vim-8.2.0692/src/version.c       2020-05-03 18:21:00.849749313 +0200
--- src/version.c       2020-05-03 22:25:50.527841388 +0200
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     693,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
39. You move into a new house and decide to Netscape before you landscape.

 /// 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/202005032031.043KVRJv005963%40masaka.moolenaar.net.

Raspunde prin e-mail lui