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 -- 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 ///