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 -- Br...@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 ///