mirror of
https://github.com/vim/vim.git
synced 2025-11-14 23:04:02 -05:00
patch 9.1.1882: Vim9: Not able to use a lambda with :defer
Problem: Vim9: Not able to use a lambda with :defer
(Maxim Kim)
Solution: Add support for this (Yegappan Lakshmanan)
fixes: #18626
closes: #18643
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
58ab3438b7
commit
21ef3c6e59
@@ -1,4 +1,4 @@
|
|||||||
*userfunc.txt* For Vim version 9.1. Last change: 2025 Oct 12
|
*userfunc.txt* For Vim version 9.1. Last change: 2025 Oct 27
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -449,6 +449,15 @@ or altering execution outside of deferred functions.
|
|||||||
No range is accepted. The function can be a partial with extra arguments, but
|
No range is accepted. The function can be a partial with extra arguments, but
|
||||||
not with a dictionary. *E1300*
|
not with a dictionary. *E1300*
|
||||||
|
|
||||||
|
In a |:def| function, a lambda can be used with |:defer|. Example: >
|
||||||
|
|
||||||
|
def Fn()
|
||||||
|
set lazyredraw
|
||||||
|
defer () => {
|
||||||
|
set lazyredraw&
|
||||||
|
}()
|
||||||
|
enddef
|
||||||
|
<
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
4. Automatically loading functions ~
|
4. Automatically loading functions ~
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ int compile_load(char_u **arg, size_t namelen, char_u *end_arg, cctx_T *cctx, in
|
|||||||
int compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, ca_special_T special_fn);
|
int compile_arguments(char_u **arg, cctx_T *cctx, int *argcount, ca_special_T special_fn);
|
||||||
char_u *to_name_end(char_u *arg, int use_namespace);
|
char_u *to_name_end(char_u *arg, int use_namespace);
|
||||||
char_u *to_name_const_end(char_u *arg);
|
char_u *to_name_const_end(char_u *arg);
|
||||||
|
int compile_lambda(char_u **arg, cctx_T *cctx);
|
||||||
int get_lambda_tv_and_compile(char_u **arg, typval_T *rettv, int types_optional, evalarg_T *evalarg);
|
int get_lambda_tv_and_compile(char_u **arg, typval_T *rettv, int types_optional, evalarg_T *evalarg);
|
||||||
exprtype_T get_compare_type(char_u *p, int *len, int *type_is);
|
exprtype_T get_compare_type(char_u *p, int *len, int *type_is);
|
||||||
void skip_expr_cctx(char_u **arg, cctx_T *cctx);
|
void skip_expr_cctx(char_u **arg, cctx_T *cctx);
|
||||||
|
|||||||
@@ -5249,6 +5249,102 @@ def Test_defer_lambda_funcref()
|
|||||||
v9.CheckSourceSuccess(lines)
|
v9.CheckSourceSuccess(lines)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
" Test for using defer with a lambda and a command block
|
||||||
|
def Test_defer_lambda_func()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
var result = ''
|
||||||
|
def Foo()
|
||||||
|
result = 'xxx'
|
||||||
|
defer (a: number, b: string): number => {
|
||||||
|
result = $'{a}:{b}'
|
||||||
|
return 0
|
||||||
|
}(10, 'aaa')
|
||||||
|
result = 'yyy'
|
||||||
|
enddef
|
||||||
|
Foo()
|
||||||
|
assert_equal('10:aaa', result)
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
# Error: argument type mismatch
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Foo()
|
||||||
|
defer (a: number, b: string): number => {
|
||||||
|
return 0
|
||||||
|
}(10, 20)
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected string but got number', 1)
|
||||||
|
|
||||||
|
# Error: not enough arguments
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Foo()
|
||||||
|
defer (a: number) => {
|
||||||
|
}()
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E119: Not enough arguments for function: (a: number) => {', 1)
|
||||||
|
|
||||||
|
# Error: too many arguments
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Foo()
|
||||||
|
defer () => {
|
||||||
|
}(10)
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E118: Too many arguments for function: () => {', 1)
|
||||||
|
|
||||||
|
# Error: invalid command in command-block
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Foo()
|
||||||
|
defer () => {
|
||||||
|
xxx
|
||||||
|
}()
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E476: Invalid command: xxx', 1)
|
||||||
|
|
||||||
|
# Error: missing return
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Foo()
|
||||||
|
defer (): number => {
|
||||||
|
}()
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E1027: Missing return statement', 1)
|
||||||
|
|
||||||
|
# Error: missing lambda body
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Foo()
|
||||||
|
defer (a: number): number
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E1028: Compiling :def function failed', 1)
|
||||||
|
|
||||||
|
# Error: invalid lambda syntax
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Foo()
|
||||||
|
defer (
|
||||||
|
enddef
|
||||||
|
defcompile
|
||||||
|
END
|
||||||
|
v9.CheckScriptFailure(lines, 'E1028: Compiling :def function failed', 1)
|
||||||
|
enddef
|
||||||
|
|
||||||
" Test for using an non-existing type in a "for" statement.
|
" Test for using an non-existing type in a "for" statement.
|
||||||
def Test_invalid_type_in_for()
|
def Test_invalid_type_in_for()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
|
|||||||
@@ -729,6 +729,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 */
|
||||||
|
/**/
|
||||||
|
1882,
|
||||||
/**/
|
/**/
|
||||||
1881,
|
1881,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
@@ -2040,25 +2040,35 @@ compile_defer(char_u *arg_start, cctx_T *cctx)
|
|||||||
int argcount = 0;
|
int argcount = 0;
|
||||||
int defer_var_idx;
|
int defer_var_idx;
|
||||||
type_T *type = NULL;
|
type_T *type = NULL;
|
||||||
int func_idx;
|
int func_idx = -1;
|
||||||
|
|
||||||
// Get a funcref for the function name.
|
if (*arg == '(')
|
||||||
// TODO: better way to find the "(".
|
|
||||||
paren = vim_strchr(arg, '(');
|
|
||||||
if (paren == NULL)
|
|
||||||
{
|
{
|
||||||
semsg(_(e_missing_parenthesis_str), arg);
|
// a lambda function
|
||||||
return NULL;
|
if (compile_lambda(&arg, cctx) != OK)
|
||||||
|
return NULL;
|
||||||
|
paren = arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get a funcref for the function name.
|
||||||
|
// TODO: better way to find the "(".
|
||||||
|
paren = vim_strchr(arg, '(');
|
||||||
|
if (paren == NULL)
|
||||||
|
{
|
||||||
|
semsg(_(e_missing_parenthesis_str), arg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*paren = NUL;
|
||||||
|
func_idx = find_internal_func(arg);
|
||||||
|
if (func_idx >= 0)
|
||||||
|
// TODO: better type
|
||||||
|
generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
|
||||||
|
&t_func_any, FALSE);
|
||||||
|
else if (compile_expr0(&arg, cctx) == FAIL)
|
||||||
|
return NULL;
|
||||||
|
*paren = '(';
|
||||||
}
|
}
|
||||||
*paren = NUL;
|
|
||||||
func_idx = find_internal_func(arg);
|
|
||||||
if (func_idx >= 0)
|
|
||||||
// TODO: better type
|
|
||||||
generate_PUSHFUNC(cctx, (char_u *)internal_func_name(func_idx),
|
|
||||||
&t_func_any, FALSE);
|
|
||||||
else if (compile_expr0(&arg, cctx) == FAIL)
|
|
||||||
return NULL;
|
|
||||||
*paren = '(';
|
|
||||||
|
|
||||||
// check for function type
|
// check for function type
|
||||||
if (cctx->ctx_skip != SKIP_YES)
|
if (cctx->ctx_skip != SKIP_YES)
|
||||||
|
|||||||
@@ -1747,7 +1747,7 @@ compile_tuple(
|
|||||||
* "*arg" points to the '('.
|
* "*arg" points to the '('.
|
||||||
* Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
|
* Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
compile_lambda(char_u **arg, cctx_T *cctx)
|
compile_lambda(char_u **arg, cctx_T *cctx)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|||||||
Reference in New Issue
Block a user