# HG changeset patch # User Bram Moolenaar # Date 1608906604 -3600 # Node ID 9c5275b1c7638700c7ba8674753b32eff389d26d # Parent 9ca71ad5406be70510ce3d7b8729761137aad582 patch 8.2.2212: Vim9: lambda with => does not work at the script level Commit: https://github.com/vim/vim/commit/c754b4cc98253e1935d3ea5790bc60869c7bc091 Author: Bram Moolenaar Date: Fri Dec 25 15:24:23 2020 +0100 patch 8.2.2212: Vim9: lambda with => does not work at the script level Problem: Vim9: lambda with => does not work at the script level. Solution: Make it work. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -3349,8 +3349,13 @@ eval7( /* * nested expression: (expression). + * lambda: (arg) => expr */ - case '(': { + case '(': ret = NOTDONE; + if (in_vim9script()) + ret = get_lambda_tv(arg, rettv, TRUE, evalarg); + if (ret == NOTDONE) + { *arg = skipwhite_and_linebreak(*arg + 1, evalarg); ret = eval1(arg, rettv, evalarg); // recursive! diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -1027,11 +1027,11 @@ def Test_assign_lambda() # check if assign a lambda to a variable which type is func or any. var lines =<< trim END vim9script - var FuncRef = {->123} + var FuncRef = {-> 123} assert_equal(123, FuncRef()) - var FuncRef_Func: func = {->123} + var FuncRef_Func: func = {-> 123} assert_equal(123, FuncRef_Func()) - var FuncRef_Any: any = {->123} + var FuncRef_Any: any = {-> 123} assert_equal(123, FuncRef_Any()) END CheckScriptSuccess(lines) diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1953,15 +1953,25 @@ def Test_expr7_new_lambda() # Lambda returning a dict var Lmb = () => ({key: 42}) assert_equal({key: 42}, Lmb()) + + var RefOne: func(number): string = (a: number): string => 'x' + var RefTwo: func(number): any = (a: number): any => 'x' + + var Fx = (a) => ({k1: 0, + k2: 1}) + var Fy = (a) => [0, + 1] END - CheckDefSuccess(lines) + CheckDefAndScriptSuccess(lines) CheckDefFailure(["var Ref = (a)=>a + 1"], 'E1001:') CheckDefFailure(["var Ref = (a)=> a + 1"], 'E1001:') CheckDefFailure(["var Ref = (a) =>a + 1"], 'E1001:') - CheckDefSuccess(["var Ref: func(number): string = (a: number): string => 'x'"]) - CheckDefSuccess(["var Ref: func(number): any = (a: number): any => 'x'"]) + CheckScriptFailure(["vim9script", "var Ref = (a)=>a + 1"], 'E1004:') + CheckScriptFailure(["vim9script", "var Ref = (a)=> a + 1"], 'E1004:') + CheckScriptFailure(["vim9script", "var Ref = (a) =>a + 1"], 'E1004:') + CheckDefFailure(["var Ref: func(number): number = (a: number): string => 'x'"], 'E1012:') CheckDefFailure(["var Ref: func(number): string = (a: number): string => 99"], 'E1012:') @@ -1978,11 +1988,9 @@ def Test_expr7_new_lambda() # 'E1106: 2 arguments too many') # CheckDefFailure(["echo 'asdf'->{a -> a}(x)"], 'E1001:', 1) - CheckDefSuccess(['var Fx = (a) => ({k1: 0,', ' k2: 1})']) CheckDefFailure(['var Fx = (a) => ({k1: 0', ' k2: 1})'], 'E722:', 2) CheckDefFailure(['var Fx = (a) => ({k1: 0,', ' k2 1})'], 'E720:', 2) - CheckDefSuccess(['var Fx = (a) => [0,', ' 1]']) CheckDefFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2) enddef diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -461,21 +461,35 @@ register_cfunc(cfunc_T cb, cfunc_free_T /* * Skip over "->" or "=>" after the arguments of a lambda. * If ": type" is found make "ret_type" point to "type". + * If "white_error" is not NULL check for correct use of white space and set + * "white_error" to TRUE if there is an error. * Return NULL if no valid arrow found. */ static char_u * -skip_arrow(char_u *start, int equal_arrow, char_u **ret_type) +skip_arrow( + char_u *start, + int equal_arrow, + char_u **ret_type, + int *white_error) { - char_u *s = start; + char_u *s = start; + char_u *bef = start - 2; // "start" points to > of -> if (equal_arrow) { if (*s == ':') { + if (white_error != NULL && !VIM_ISWHITE(s[1])) + { + *white_error = TRUE; + semsg(_(e_white_space_required_after_str), ":"); + return NULL; + } s = skipwhite(s + 1); *ret_type = s; s = skip_type(s, TRUE); } + bef = s; s = skipwhite(s); if (*s != '=') return NULL; @@ -483,6 +497,14 @@ skip_arrow(char_u *start, int equal_arro } if (*s != '>') return NULL; + if (white_error != NULL && ((!VIM_ISWHITE(*bef) && *bef != '{') + || !IS_WHITE_OR_NUL(s[1]))) + { + *white_error = TRUE; + semsg(_(e_white_space_required_before_and_after_str), + equal_arrow ? "=>" : "->"); + return NULL; + } return skipwhite(s + 1); } @@ -516,6 +538,7 @@ get_lambda_tv( int eval_lavars = FALSE; char_u *tofree = NULL; int equal_arrow = **arg == '('; + int white_error = FALSE; if (equal_arrow && !in_vim9script()) return NOTDONE; @@ -529,7 +552,7 @@ get_lambda_tv( ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL, types_optional ? &argtypes : NULL, types_optional, NULL, NULL, TRUE, NULL, NULL); - if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type) == NULL) + if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL) { if (types_optional) ga_clear_strings(&argtypes); @@ -546,12 +569,14 @@ get_lambda_tv( types_optional ? &argtypes : NULL, types_optional, &varargs, NULL, FALSE, NULL, NULL); if (ret == FAIL - || (*arg = skip_arrow(*arg, equal_arrow, &ret_type)) == NULL) + || (s = skip_arrow(*arg, equal_arrow, &ret_type, + &white_error)) == NULL) { if (types_optional) ga_clear_strings(&argtypes); - return NOTDONE; + return white_error ? FAIL : NOTDONE; } + *arg = s; // Set up a flag for checking local variables and arguments. if (evaluate) @@ -647,8 +672,6 @@ get_lambda_tv( if (register_closure(fp) == FAIL) goto errret; } - else - fp->uf_scoped = NULL; #ifdef FEAT_PROFILE if (prof_def_func()) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2212, +/**/ 2211, /**/ 2210, diff --git a/src/vim9type.c b/src/vim9type.c --- a/src/vim9type.c +++ b/src/vim9type.c @@ -338,6 +338,8 @@ typval2type_int(typval_T *tv, garray_T * if (ufunc->uf_def_status == UF_TO_BE_COMPILED && compile_def_function(ufunc, TRUE, NULL) == FAIL) return NULL; + if (ufunc->uf_func_type == NULL) + set_function_type(ufunc); if (ufunc->uf_func_type != NULL) return ufunc->uf_func_type; }