mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.0696: Vim9: nested function does not work properly
Problem: Vim9: nested function does not work properly Solution: Create a function reference. Check argument count.
This commit is contained in:
parent
04b1269783
commit
0e65d3de0a
@ -93,6 +93,9 @@ def Test_nested_function()
|
|||||||
enddef
|
enddef
|
||||||
assert_equal('nested function', Nested('function'))
|
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:')
|
CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
@ -746,6 +746,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
696,
|
||||||
/**/
|
/**/
|
||||||
695,
|
695,
|
||||||
/**/
|
/**/
|
||||||
|
@ -101,7 +101,6 @@ typedef struct {
|
|||||||
int lv_from_outer; // when TRUE using ctx_outer scope
|
int lv_from_outer; // when TRUE using ctx_outer scope
|
||||||
int lv_const; // when TRUE cannot be assigned to
|
int lv_const; // when TRUE cannot be assigned to
|
||||||
int lv_arg; // when TRUE this is an argument
|
int lv_arg; // when TRUE this is an argument
|
||||||
int lv_func_idx; // for nested function
|
|
||||||
} lvar_T;
|
} lvar_T;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1504,7 +1503,24 @@ generate_PCALL(
|
|||||||
if (type->tt_type == VAR_ANY)
|
if (type->tt_type == VAR_ANY)
|
||||||
ret_type = &t_any;
|
ret_type = &t_any;
|
||||||
else if (type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
|
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;
|
ret_type = type->tt_member;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
semsg(_("E1085: Not a callable type: %s"), name);
|
semsg(_("E1085: Not a callable type: %s"), name);
|
||||||
@ -2616,7 +2632,6 @@ compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
|
|||||||
int error = FCERR_NONE;
|
int error = FCERR_NONE;
|
||||||
ufunc_T *ufunc;
|
ufunc_T *ufunc;
|
||||||
int res = FAIL;
|
int res = FAIL;
|
||||||
lvar_T *lvar;
|
|
||||||
|
|
||||||
if (varlen >= sizeof(namebuf))
|
if (varlen >= sizeof(namebuf))
|
||||||
{
|
{
|
||||||
@ -2643,16 +2658,6 @@ compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
|
|||||||
goto theend;
|
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.
|
// If we can find the function by name generate the right call.
|
||||||
ufunc = find_func(name, FALSE, cctx);
|
ufunc = find_func(name, FALSE, cctx);
|
||||||
if (ufunc != NULL)
|
if (ufunc != NULL)
|
||||||
@ -2807,7 +2812,6 @@ compile_list(char_u **arg, cctx_T *cctx)
|
|||||||
static int
|
static int
|
||||||
compile_lambda(char_u **arg, cctx_T *cctx)
|
compile_lambda(char_u **arg, cctx_T *cctx)
|
||||||
{
|
{
|
||||||
garray_T *instr = &cctx->ctx_instr;
|
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
ufunc_T *ufunc;
|
ufunc_T *ufunc;
|
||||||
|
|
||||||
@ -2825,12 +2829,7 @@ compile_lambda(char_u **arg, cctx_T *cctx)
|
|||||||
compile_def_function(ufunc, TRUE, cctx);
|
compile_def_function(ufunc, TRUE, cctx);
|
||||||
|
|
||||||
if (ufunc->uf_dfunc_idx >= 0)
|
if (ufunc->uf_dfunc_idx >= 0)
|
||||||
{
|
return generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
|
||||||
if (ga_grow(instr, 1) == FAIL)
|
|
||||||
return FAIL;
|
|
||||||
generate_FUNCREF(cctx, ufunc->uf_dfunc_idx);
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4103,16 +4102,16 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
|||||||
eap->forceit = FALSE;
|
eap->forceit = FALSE;
|
||||||
ufunc = def_function(eap, name, cctx);
|
ufunc = def_function(eap, name, cctx);
|
||||||
|
|
||||||
if (ufunc == NULL)
|
if (ufunc == NULL || ufunc->uf_dfunc_idx < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Define a local variable for the function, but change the index to -1 to
|
// Define a local variable for the function reference.
|
||||||
// mark it as a function name.
|
|
||||||
lvar = reserve_local(cctx, name_start, name_end - name_start,
|
lvar = reserve_local(cctx, name_start, name_end - name_start,
|
||||||
TRUE, &t_func_unknown);
|
TRUE, ufunc->uf_func_type);
|
||||||
lvar->lv_idx = 0;
|
|
||||||
++cctx->ctx_locals_count; // doesn't count as a local variable
|
if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL
|
||||||
lvar->lv_func_idx = ufunc->uf_dfunc_idx;
|
|| generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL) == FAIL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// TODO: warning for trailing?
|
// TODO: warning for trailing?
|
||||||
return (char_u *)"";
|
return (char_u *)"";
|
||||||
|
@ -206,11 +206,6 @@ call_dfunc(int cdf_idx, int argcount_arg, ectx_T *ectx)
|
|||||||
+ dfunc->df_varcount + dfunc->df_closure_count) == FAIL)
|
+ dfunc->df_varcount + dfunc->df_closure_count) == FAIL)
|
||||||
return 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.
|
// Move the vararg-list to below the missing optional arguments.
|
||||||
if (vararg_count > 0 && arg_to_add > 0)
|
if (vararg_count > 0 && arg_to_add > 0)
|
||||||
*STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
|
*STACK_TV_BOT(arg_to_add - 1) = *STACK_TV_BOT(-1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user