To: vim_dev@googlegroups.com Subject: Patch 8.2.0696 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0696 Problem: Vim9: nested function does not work properly Solution: Create a function reference. Check argument count. Files: src/vim9compile.c, src/vim9execute.c, src/testdir/test_vim9_func.vim *** ../vim-8.2.0695/src/vim9compile.c 2020-05-04 23:24:41.118072992 +0200 --- src/vim9compile.c 2020-05-05 17:46:15.566982624 +0200 *************** *** 101,107 **** int lv_from_outer; // when TRUE using ctx_outer scope int lv_const; // when TRUE cannot be assigned to int lv_arg; // when TRUE this is an argument - int lv_func_idx; // for nested function } lvar_T; /* --- 101,106 ---- *************** *** 1504,1510 **** --- 1503,1526 ---- if (type->tt_type == VAR_ANY) ret_type = &t_any; else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL) + { + if (type->tt_argcount != -1) + { + int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; + + if (argcount < type->tt_min_argcount - varargs) + { + semsg(_(e_toofewarg), "[reference]"); + return FAIL; + } + if (!varargs && argcount > type->tt_argcount) + { + semsg(_(e_toomanyarg), "[reference]"); + return FAIL; + } + } ret_type = type->tt_member; + } else { semsg(_("E1085: Not a callable type: %s"), name); *************** *** 2616,2622 **** int error = FCERR_NONE; ufunc_T *ufunc; int res = FAIL; - lvar_T *lvar; if (varlen >= sizeof(namebuf)) { --- 2632,2637 ---- *************** *** 2643,2658 **** goto theend; } - // Check if the name is a nested function. - lvar = lookup_local(namebuf, varlen, cctx); - if (lvar != NULL && lvar->lv_func_idx > 0) - { - dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) - + lvar->lv_func_idx; - res = generate_CALL(cctx, dfunc->df_ufunc, argcount); - goto theend; - } - // If we can find the function by name generate the right call. ufunc = find_func(name, FALSE, cctx); if (ufunc != NULL) --- 2658,2663 ---- *************** *** 2807,2813 **** static int compile_lambda(char_u **arg, cctx_T *cctx) { - garray_T *instr = &cctx->ctx_instr; typval_T rettv; ufunc_T *ufunc; --- 2812,2817 ---- *************** *** 2825,2836 **** compile_def_function(ufunc, TRUE, cctx); if (ufunc->uf_dfunc_idx >= 0) ! { ! if (ga_grow(instr, 1) == FAIL) ! return FAIL; ! generate_FUNCREF(cctx, ufunc->uf_dfunc_idx); ! return OK; ! } return FAIL; } --- 2829,2835 ---- compile_def_function(ufunc, TRUE, cctx); if (ufunc->uf_dfunc_idx >= 0) ! return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx); return FAIL; } *************** *** 4103,4118 **** eap->forceit = FALSE; ufunc = def_function(eap, name, cctx); ! if (ufunc == NULL) return NULL; ! // Define a local variable for the function, but change the index to -1 to ! // mark it as a function name. lvar = reserve_local(cctx, name_start, name_end - name_start, ! TRUE, &t_func_unknown); ! lvar->lv_idx = 0; ! ++cctx->ctx_locals_count; // doesn't count as a local variable ! lvar->lv_func_idx = ufunc->uf_dfunc_idx; // TODO: warning for trailing? return (char_u *)""; --- 4102,4117 ---- eap->forceit = FALSE; ufunc = def_function(eap, name, cctx); ! if (ufunc == NULL || ufunc->uf_dfunc_idx < 0) return NULL; ! // Define a local variable for the function reference. lvar = reserve_local(cctx, name_start, name_end - name_start, ! TRUE, ufunc->uf_func_type); ! ! if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL ! || generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL) == FAIL) ! return NULL; // TODO: warning for trailing? return (char_u *)""; *** ../vim-8.2.0695/src/vim9execute.c 2020-05-04 23:24:41.118072992 +0200 --- src/vim9execute.c 2020-05-05 17:16:19.069126797 +0200 *************** *** 206,216 **** + dfunc->df_varcount + dfunc->df_closure_count) == FAIL) return FAIL; - // Closure may need the function context where it was defined. - // TODO: assuming current context. - ectx->ec_outer_stack = &ectx->ec_stack; - ectx->ec_outer_frame = ectx->ec_frame_idx; - // Move the vararg-list to below the missing optional arguments. if (vararg_count > 0 && arg_to_add > 0) *STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1); --- 206,211 ---- *** ../vim-8.2.0695/src/testdir/test_vim9_func.vim 2020-05-04 23:24:41.118072992 +0200 --- src/testdir/test_vim9_func.vim 2020-05-05 17:43:00.611655864 +0200 *************** *** 93,98 **** --- 93,101 ---- enddef assert_equal('nested function', Nested('function')) + CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:') + CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:') + CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:') enddef *** ../vim-8.2.0695/src/version.c 2020-05-04 23:24:41.118072992 +0200 --- src/version.c 2020-05-05 17:18:52.380801707 +0200 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 696, /**/ -- hundred-and-one symptoms of being an internet addict: 47. You are so familiar with the WWW that you find the search engines useless. /// 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 ///