Skip to content

Commit e462f52

Browse files
committed
patch 8.2.2227: Vim9: recognizing lambda is too complicated
Problem: Vim9: recognizing lambda is too complicated. Solution: Call compile_lambda() and check for NOTDONE.
1 parent 7e3ee78 commit e462f52

4 files changed

Lines changed: 25 additions & 59 deletions

File tree

src/testdir/test_vim9_expr.vim

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,9 +1863,9 @@ def Test_expr7_lambda()
18631863
END
18641864
CheckDefAndScriptSuccess(lines)
18651865

1866-
CheckDefFailure(["var Ref = {a->a + 1}"], 'E720:')
1867-
CheckDefFailure(["var Ref = {a-> a + 1}"], 'E720:')
1868-
CheckDefFailure(["var Ref = {a ->a + 1}"], 'E720:')
1866+
CheckDefFailure(["var Ref = {a->a + 1}"], 'E1004:')
1867+
CheckDefFailure(["var Ref = {a-> a + 1}"], 'E1004:')
1868+
CheckDefFailure(["var Ref = {a ->a + 1}"], 'E1004:')
18691869

18701870
CheckDefFailure(["filter([1, 2], {k,v -> 1})"], 'E1069:', 1)
18711871
# error is in first line of the lambda
@@ -1964,13 +1964,9 @@ def Test_expr7_new_lambda()
19641964
END
19651965
CheckDefAndScriptSuccess(lines)
19661966

1967-
CheckDefFailure(["var Ref = (a)=>a + 1"], 'E1001:')
1968-
CheckDefFailure(["var Ref = (a)=> a + 1"], 'E1001:')
1969-
CheckDefFailure(["var Ref = (a) =>a + 1"], 'E1001:')
1970-
1971-
CheckScriptFailure(["vim9script", "var Ref = (a)=>a + 1"], 'E1004:')
1972-
CheckScriptFailure(["vim9script", "var Ref = (a)=> a + 1"], 'E1004:')
1973-
CheckScriptFailure(["vim9script", "var Ref = (a) =>a + 1"], 'E1004:')
1967+
CheckDefAndScriptFailure(["var Ref = (a)=>a + 1"], 'E1004:')
1968+
CheckDefAndScriptFailure(["var Ref = (a)=> a + 1"], 'E1004:')
1969+
CheckDefAndScriptFailure(["var Ref = (a) =>a + 1"], 'E1004:')
19741970

19751971
CheckDefFailure(["var Ref: func(number): number = (a: number): string => 'x'"], 'E1012:')
19761972
CheckDefFailure(["var Ref: func(number): string = (a: number): string => 99"], 'E1012:')
@@ -2682,7 +2678,7 @@ func Test_expr7_fails()
26822678
call CheckDefFailure(["'yes'->", "Echo()"], 'E488: Trailing characters: ->', 1)
26832679

26842680
call CheckDefExecFailure(["[1, 2->len()"], 'E697:', 2)
2685-
call CheckDefExecFailure(["{a: 1->len()"], 'E723:', 2)
2681+
call CheckDefExecFailure(["{a: 1->len()"], 'E1004:', 1)
26862682
call CheckDefExecFailure(["{['a']: 1->len()"], 'E723:', 2)
26872683
endfunc
26882684

src/userfunc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ get_lambda_tv(
570570
&varargs, NULL, FALSE, NULL, NULL);
571571
if (ret == FAIL
572572
|| (s = skip_arrow(*arg, equal_arrow, &ret_type,
573-
equal_arrow ? &white_error : NULL)) == NULL)
573+
equal_arrow || in_vim9script() ? &white_error : NULL)) == NULL)
574574
{
575575
if (types_optional)
576576
ga_clear_strings(&argtypes);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2227,
753755
/**/
754756
2226,
755757
/**/

src/vim9compile.c

Lines changed: 15 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,10 +2949,12 @@ compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
29492949
/*
29502950
* parse a lambda: "{arg, arg -> expr}" or "(arg, arg) => expr"
29512951
* "*arg" points to the '{'.
2952+
* Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda.
29522953
*/
29532954
static int
29542955
compile_lambda(char_u **arg, cctx_T *cctx)
29552956
{
2957+
int r;
29562958
typval_T rettv;
29572959
ufunc_T *ufunc;
29582960
evalarg_T evalarg;
@@ -2962,10 +2964,11 @@ compile_lambda(char_u **arg, cctx_T *cctx)
29622964
evalarg.eval_cctx = cctx;
29632965

29642966
// Get the funcref in "rettv".
2965-
if (get_lambda_tv(arg, &rettv, TRUE, &evalarg) != OK)
2967+
r = get_lambda_tv(arg, &rettv, TRUE, &evalarg);
2968+
if (r != OK)
29662969
{
29672970
clear_evalarg(&evalarg, NULL);
2968-
return FAIL;
2971+
return r;
29692972
}
29702973

29712974
// "rettv" will now be a partial referencing the function.
@@ -4001,26 +4004,13 @@ compile_expr7(
40014004
* Lambda: {arg, arg -> expr}
40024005
* Dictionary: {'key': val, 'key': val}
40034006
*/
4004-
case '{': {
4005-
char_u *start = skipwhite(*arg + 1);
4006-
char_u *after = start;
4007-
garray_T ga_arg;
4008-
4009-
// Find out what comes after the arguments.
4010-
ret = get_function_args(&after, '-', NULL,
4011-
&ga_arg, TRUE, NULL, NULL,
4012-
TRUE, NULL, NULL);
4013-
if (ret != FAIL && after[0] == '>'
4014-
&& ((after > start + 2
4015-
&& VIM_ISWHITE(after[-2]))
4016-
|| after == start + 1)
4017-
&& IS_WHITE_OR_NUL(after[1]))
4018-
// TODO: if we go with the "(arg) => expr" syntax
4019-
// remove this
4020-
ret = compile_lambda(arg, cctx);
4021-
else
4022-
ret = compile_dict(arg, cctx, ppconst);
4023-
}
4007+
case '{': // Try parsing as a lambda, if NOTDONE is returned it
4008+
// must be a dict.
4009+
// TODO: if we go with the "(arg) => expr" syntax remove
4010+
// this
4011+
ret = compile_lambda(arg, cctx);
4012+
if (ret == NOTDONE)
4013+
ret = compile_dict(arg, cctx, ppconst);
40244014
break;
40254015

40264016
/*
@@ -4051,32 +4041,10 @@ compile_expr7(
40514041
* lambda: (arg, arg) => expr
40524042
* funcref: (arg, arg) => { statement }
40534043
*/
4054-
case '(': {
4055-
char_u *start = skipwhite(*arg + 1);
4056-
char_u *after = start;
4057-
garray_T ga_arg;
4058-
4059-
// Find out if "=>" comes after the ().
4060-
ret = get_function_args(&after, ')', NULL,
4061-
&ga_arg, TRUE, NULL, NULL,
4062-
TRUE, NULL, NULL);
4063-
if (ret == OK && VIM_ISWHITE(
4064-
*after == ':' ? after[1] : *after))
4065-
{
4066-
if (*after == ':')
4067-
// Skip over type in "(arg): type".
4068-
after = skip_type(skipwhite(after + 1), TRUE);
4069-
4070-
after = skipwhite(after);
4071-
if (after[0] == '=' && after[1] == '>'
4072-
&& IS_WHITE_OR_NUL(after[2]))
4073-
{
4074-
ret = compile_lambda(arg, cctx);
4075-
break;
4076-
}
4077-
}
4044+
case '(': // if compile_lambda returns NOTDONE then it must be (expr)
4045+
ret = compile_lambda(arg, cctx);
4046+
if (ret == NOTDONE)
40784047
ret = compile_parenthesis(arg, cctx, ppconst);
4079-
}
40804048
break;
40814049

40824050
default: ret = NOTDONE;

0 commit comments

Comments
 (0)