To: vim_dev@googlegroups.com Subject: Patch 8.2.0693 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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) + 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 -- Bram@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 ///