# HG changeset patch # User Bram Moolenaar # Date 1609446603 -3600 # Node ID 5807e3958e3898e21dced2fae52a15c9aa00ef57 # Parent 8f2dcc0cfcf602a79ae97b7d32eb95e22ea39700 patch 8.2.2257: Vim9: using -> for lambda is ambiguous Commit: https://github.com/vim/vim/commit/2949cfdbe4335b9abcfeda1be4dfc52090ee1df6 Author: Bram Moolenaar Date: Thu Dec 31 21:28:47 2020 +0100 patch 8.2.2257: Vim9: using -> for lambda is ambiguous Problem: Vim9: using -> for lambda is ambiguous. Solution: Stop supporting ->, must use =>. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -3316,7 +3316,10 @@ eval7( * Lambda: {arg, arg -> expr} * Dictionary: {'key': val, 'key': val} */ - case '{': ret = get_lambda_tv(arg, rettv, in_vim9script(), evalarg); + case '{': if (in_vim9script()) + ret = NOTDONE; + else + ret = get_lambda_tv(arg, rettv, in_vim9script(), evalarg); if (ret == NOTDONE) ret = eval_dict(arg, rettv, evalarg, FALSE); break; @@ -3617,7 +3620,24 @@ eval_lambda( *arg += 2; rettv->v_type = VAR_UNKNOWN; - ret = get_lambda_tv(arg, rettv, FALSE, evalarg); + if (**arg == '{') + { + // ->{lambda}() + ret = get_lambda_tv(arg, rettv, FALSE, evalarg); + } + else + { + // ->(lambda)() + ++*arg; + ret = eval1(arg, rettv, evalarg); + *arg = skipwhite_and_linebreak(*arg, evalarg); + if (**arg != ')') + { + emsg(_(e_missing_close)); + ret = FAIL; + } + ++*arg; + } if (ret != OK) return FAIL; else if (**arg != '(') @@ -5645,8 +5665,8 @@ handle_subscript( *arg = p; if (ret == OK) { - if ((*arg)[2] == '{') - // expr->{lambda}() + if (((*arg)[2] == '{' && !in_vim9script()) || (*arg)[2] == '(') + // expr->{lambda}() or expr->(lambda)() ret = eval_lambda(arg, rettv, evalarg, verbose); else // expr->name() 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 @@ -66,7 +66,7 @@ def Test_assignment() CheckDefFailure(['var x:string'], 'E1069:') CheckDefFailure(['var x:string = "x"'], 'E1069:') CheckDefFailure(['var a:string = "x"'], 'E1069:') - CheckDefFailure(['var lambda = {-> "lambda"}'], 'E704:') + CheckDefFailure(['var lambda = () => "lambda"'], 'E704:') CheckScriptFailure(['var x = "x"'], 'E1124:') var nr: number = 1234 @@ -1032,11 +1032,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_builtin.vim b/src/testdir/test_vim9_builtin.vim --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -231,7 +231,7 @@ def Test_extend_arg_types() assert_equal({a: 1, b: 2}, extend({a: 1, b: 2}, {b: 4}, s:string_keep)) var res: list> - extend(res, map([1, 2], {_, v -> {}})) + extend(res, map([1, 2], (_, v) => ({}))) assert_equal([{}, {}], res) CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list but got number') @@ -254,7 +254,7 @@ enddef def Wrong_dict_key_type(items: list): list - return filter(items, {_, val -> get({[val]: 1}, 'x')}) + return filter(items, (_, val) => get({[val]: 1}, 'x')) enddef def Test_map_function_arg() @@ -313,7 +313,7 @@ def Test_filter_wrong_dict_key_type() enddef def Test_filter_return_type() - var l = filter([1, 2, 3], {-> 1}) + var l = filter([1, 2, 3], () => 1) var res = 0 for n in l res += n @@ -323,7 +323,7 @@ enddef def Test_filter_missing_argument() var dict = {aa: [1], ab: [2], ac: [3], de: [4]} - var res = dict->filter({k -> k =~ 'a' && k !~ 'b'}) + var res = dict->filter((k) => k =~ 'a' && k !~ 'b') res->assert_equal({aa: [1], ac: [3]}) enddef @@ -539,8 +539,8 @@ def Test_nr2char() enddef def Test_readdir() - eval expand('sautest')->readdir({e -> e[0] !=# '.'}) - eval expand('sautest')->readdirex({e -> e.name[0] !=# '.'}) + eval expand('sautest')->readdir((e) => e[0] !=# '.') + eval expand('sautest')->readdirex((e) => e.name[0] !=# '.') enddef def Test_remove_return_type() @@ -566,16 +566,16 @@ def Test_search() setline(1, ['foo', 'bar']) var val = 0 # skip expr returns boolean - search('bar', 'W', 0, 0, {-> val == 1})->assert_equal(2) + search('bar', 'W', 0, 0, () => val == 1)->assert_equal(2) :1 - search('bar', 'W', 0, 0, {-> val == 0})->assert_equal(0) + search('bar', 'W', 0, 0, () => val == 0)->assert_equal(0) # skip expr returns number, only 0 and 1 are accepted :1 - search('bar', 'W', 0, 0, {-> 0})->assert_equal(2) + search('bar', 'W', 0, 0, () => 0)->assert_equal(2) :1 - search('bar', 'W', 0, 0, {-> 1})->assert_equal(0) - assert_fails("search('bar', '', 0, 0, {-> -1})", 'E1023:') - assert_fails("search('bar', '', 0, 0, {-> -1})", 'E1023:') + search('bar', 'W', 0, 0, () => 1)->assert_equal(0) + assert_fails("search('bar', '', 0, 0, () => -1)", 'E1023:') + assert_fails("search('bar', '', 0, 0, () => -1)", 'E1023:') enddef def Test_searchcount() @@ -667,7 +667,7 @@ enddef def Test_submatch() var pat = 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)' - var Rep = {-> range(10)->map({_, v -> submatch(v, true)})->string()} + var Rep = () => range(10)->map((_, v) => submatch(v, true))->string() var actual = substitute('A123456789', pat, Rep, '') var expected = "[['A123456789'], ['1'], ['2'], ['3'], ['4'], ['5'], ['6'], ['7'], ['8'], ['9']]" actual->assert_equal(expected) @@ -703,7 +703,7 @@ def Test_term_start() enddef def Test_timer_paused() - var id = timer_start(50, {-> 0}) + var id = timer_start(50, () => 0) timer_pause(id, true) var info = timer_info(id) info[0]['paused']->assert_equal(1) diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -305,7 +305,7 @@ enddef def Test_skipped_expr_linebreak() if 0 var x = [] - ->map({ -> 0}) + ->map(() => 0) endif enddef @@ -368,7 +368,7 @@ enddef def Test_filter_is_not_modifier() var tags = [{a: 1, b: 2}, {x: 3, y: 4}] - filter(tags, { _, v -> has_key(v, 'x') ? 1 : 0 }) + filter(tags, ( _, v) => has_key(v, 'x') ? 1 : 0 ) assert_equal([{x: 3, y: 4}], tags) enddef diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -896,7 +896,7 @@ def Test_disassemble_channel() enddef def WithLambda(): string - var F = {a -> "X" .. a .. "X"} + var F = (a) => "X" .. a .. "X" return F("x") enddef @@ -904,7 +904,7 @@ def Test_disassemble_lambda() assert_equal("XxX", WithLambda()) var instr = execute('disassemble WithLambda') assert_match('WithLambda\_s*' .. - 'var F = {a -> "X" .. a .. "X"}\_s*' .. + 'var F = (a) => "X" .. a .. "X"\_s*' .. '\d FUNCREF \d\+\_s*' .. '\d STORE $0\_s*' .. 'return F("x")\_s*' .. @@ -929,7 +929,7 @@ def Test_disassemble_lambda() enddef def LambdaWithType(): number - var Ref = {a: number -> a + 10} + var Ref = (a: number) => a + 10 return Ref(g:value) enddef @@ -938,7 +938,7 @@ def Test_disassemble_lambda_with_type() assert_equal(15, LambdaWithType()) var instr = execute('disassemble LambdaWithType') assert_match('LambdaWithType\_s*' .. - 'var Ref = {a: number -> a + 10}\_s*' .. + 'var Ref = (a: number) => a + 10\_s*' .. '\d FUNCREF \d\+\_s*' .. '\d STORE $0\_s*' .. 'return Ref(g:value)\_s*' .. @@ -1541,10 +1541,10 @@ def Test_disassemble_compare() ['{a: 1} is aDict', 'COMPAREDICT is'], ['{a: 1} isnot aDict', 'COMPAREDICT isnot'], - ['{-> 33} == {-> 44}', 'COMPAREFUNC =='], - ['{-> 33} != {-> 44}', 'COMPAREFUNC !='], - ['{-> 33} is {-> 44}', 'COMPAREFUNC is'], - ['{-> 33} isnot {-> 44}', 'COMPAREFUNC isnot'], + ['(() => 33) == (() => 44)', 'COMPAREFUNC =='], + ['(() => 33) != (() => 44)', 'COMPAREFUNC !='], + ['(() => 33) is (() => 44)', 'COMPAREFUNC is'], + ['(() => 33) isnot (() => 44)', 'COMPAREFUNC isnot'], ['77 == g:xx', 'COMPAREANY =='], ['77 != g:xx', 'COMPAREANY !='], 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 @@ -1806,58 +1806,56 @@ def Test_expr7_list_vim9script() enddef def LambdaWithComments(): func - return {x -> + return (x) => # some comment x == 1 # some comment || x == 2 - } enddef def LambdaUsingArg(x: number): func - return {-> + return () => # some comment x == 1 # some comment || x == 2 - } enddef def Test_expr7_lambda() var lines =<< trim END - var La = { -> 'result'} + var La = () => 'result' assert_equal('result', La()) - assert_equal([1, 3, 5], [1, 2, 3]->map({key, val -> key + val})) + assert_equal([1, 3, 5], [1, 2, 3]->map((key, val) => key + val)) # line continuation inside lambda with "cond ? expr : expr" works var ll = range(3) - map(ll, {k, v -> v % 2 ? { + map(ll, (k, v) => v % 2 ? { ['111']: 111 } : {} - }) + ) assert_equal([{}, {111: 111}, {}], ll) ll = range(3) - map(ll, {k, v -> v == 8 || v + map(ll, (k, v) => v == 8 || v == 9 || v % 2 ? 111 : 222 - }) + ) assert_equal([222, 111, 222], ll) ll = range(3) - map(ll, {k, v -> v != 8 && v + map(ll, (k, v) => v != 8 && v != 9 && v % 2 == 0 ? 111 : 222 - }) + ) assert_equal([111, 222, 111], ll) - var dl = [{key: 0}, {key: 22}]->filter({ _, v -> v['key'] }) + var dl = [{key: 0}, {key: 22}]->filter(( _, v) => v['key'] ) assert_equal([{key: 22}], dl) dl = [{key: 12}, {['foo']: 34}] assert_equal([{key: 12}], filter(dl, - {_, v -> has_key(v, 'key') ? v['key'] == 12 : 0})) + (_, v) => has_key(v, 'key') ? v['key'] == 12 : 0)) assert_equal(false, LambdaWithComments()(0)) assert_equal(true, LambdaWithComments()(1)) @@ -1867,33 +1865,31 @@ def Test_expr7_lambda() assert_equal(false, LambdaUsingArg(0)()) assert_equal(true, LambdaUsingArg(1)()) - var res = map([1, 2, 3], {i: number, v: number -> i + v}) + var res = map([1, 2, 3], (i: number, v: number) => i + v) assert_equal([1, 3, 5], res) END CheckDefAndScriptSuccess(lines) - CheckDefFailure(["var Ref = {a->a + 1}"], 'E1004:') - CheckDefFailure(["var Ref = {a-> a + 1}"], 'E1004:') - CheckDefFailure(["var Ref = {a ->a + 1}"], 'E1004:') - - CheckDefFailure(["filter([1, 2], {k,v -> 1})"], 'E1069:', 1) + CheckDefFailure(["var Ref = (a)=>a + 1"], 'E1004:') + CheckDefFailure(["var Ref = (a)=> a + 1"], 'E1004:') + CheckDefFailure(["var Ref = (a) =>a + 1"], 'E1004:') + + CheckDefFailure(["filter([1, 2], (k,v) => 1)"], 'E1069:', 1) # error is in first line of the lambda - CheckDefFailure(["var L = {a -> a + b}"], 'E1001:', 0) - - assert_equal('xxxyyy', 'xxx'->{a, b -> a .. b}('yyy')) - - CheckDefExecFailure(["var s = 'asdf'->{a -> a}('x')"], - 'E1106: One argument too many') - CheckDefExecFailure(["var s = 'asdf'->{a -> a}('x', 'y')"], - '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) + CheckDefFailure(["var L = (a) => a + b"], 'E1001:', 0) + + assert_equal('xxxyyy', 'xxx'->((a, b) => a .. b)('yyy')) + + CheckDefExecFailure(["var s = 'asdf'->((a) => a)('x')"], 'E118:') + CheckDefExecFailure(["var s = 'asdf'->((a) => a)('x', 'y')"], 'E118:') + 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 def NewLambdaWithComments(): func @@ -2002,10 +1998,10 @@ enddef def Test_expr7_lambda_vim9script() var lines =<< trim END vim9script - var v = 10->{a -> + var v = 10->((a) => a + 2 - }() + )() assert_equal(12, v) END CheckScriptSuccess(lines) @@ -2013,9 +2009,9 @@ def Test_expr7_lambda_vim9script() # nested lambda with line breaks lines =<< trim END vim9script - search('"', 'cW', 0, 0, {-> + search('"', 'cW', 0, 0, () => synstack('.', col('.')) - ->map({_, v -> synIDattr(v, 'name')})->len()}) + ->map((_, v) => synIDattr(v, 'name'))->len()) END CheckScriptSuccess(lines) enddef @@ -2089,8 +2085,8 @@ def Test_expr7_dict() CheckDefFailure(["var x = 'a' .. #{a: 1}"], 'E1097:', 3) CheckDefFailure(["var x = {a:8}"], 'E1069:', 1) - CheckDefFailure(["var x = {a : 8}"], 'E1059:', 1) - CheckDefFailure(["var x = {a :8}"], 'E1059:', 1) + CheckDefFailure(["var x = {a : 8}"], 'E1068:', 1) + CheckDefFailure(["var x = {a :8}"], 'E1068:', 1) CheckDefFailure(["var x = {a: 8 , b: 9}"], 'E1068:', 1) CheckDefFailure(["var x = {a: 1,b: 2}"], 'E1069:', 1) @@ -2139,6 +2135,9 @@ def Test_expr7_dict_vim9script() ['two']: 2, } assert_equal({one: 1, two: 2}, d) + + var dd = {k: 123->len()} + assert_equal(3, dd.k) END CheckScriptSuccess(lines) @@ -2174,7 +2173,7 @@ def Test_expr7_dict_vim9script() vim9script var d = {one : 1} END - CheckScriptFailure(lines, 'E1059:', 2) + CheckScriptFailure(lines, 'E1068:', 2) lines =<< trim END vim9script @@ -2629,7 +2628,7 @@ def Test_expr7_not() unlet g:false assert_equal(true, !test_null_partial()) - assert_equal(false, !{-> 'yes'}) + assert_equal(false, !() => 'yes') assert_equal(true, !test_null_dict()) assert_equal(true, !{}) @@ -2668,8 +2667,8 @@ func Test_expr7_fails() call CheckDefFailure(["var x = [1, 2"], "E697:", 2) call CheckDefFailure(["var x = [notfound]"], "E1001:", 1) - call CheckDefFailure(["var x = { -> 123) }"], "E451:", 1) - call CheckDefFailure(["var x = 123->{x -> x + 5) }"], "E451:", 1) + call CheckDefFailure(["var X = () => 123)"], "E488:", 1) + call CheckDefFailure(["var x = 123->((x) => x + 5)"], "E107:", 1) call CheckDefFailure(["var x = ¬exist"], 'E113:', 1) call CheckDefFailure(["&grepprg = [343]"], 'E1012:', 1) @@ -2691,7 +2690,7 @@ func Test_expr7_fails() call CheckDefFailure(["'yes'->", "Echo()"], 'E488: Trailing characters: ->', 1) call CheckDefExecFailure(["[1, 2->len()"], 'E697:', 2) - call CheckDefExecFailure(["{a: 1->len()"], 'E1004:', 1) + call CheckDefExecFailure(["{a: 1->len()"], 'E723:', 2) call CheckDefExecFailure(["{['a']: 1->len()"], 'E723:', 2) endfunc @@ -2725,12 +2724,12 @@ def Test_expr7_trailing() # method call l = [2, 5, 6] - l->map({k, v -> k + v}) + l->map((k, v) => k + v) assert_equal([2, 6, 8], l) # lambda method call l = [2, 5] - l->{l -> add(l, 8)}() + l->((l) => add(l, 8))() assert_equal([2, 5, 8], l) # dict member @@ -2895,8 +2894,8 @@ def Test_expr7_subscript_linebreak() enddef func Test_expr7_trailing_fails() - call CheckDefFailure(['var l = [2]', 'l->{l -> add(l, 8)}'], 'E107:', 2) - call CheckDefFailure(['var l = [2]', 'l->{l -> add(l, 8)} ()'], 'E274:', 2) + call CheckDefFailure(['var l = [2]', 'l->((l) => add(l, 8))'], 'E107:', 2) + call CheckDefFailure(['var l = [2]', 'l->((l) => add(l, 8)) ()'], 'E274:', 2) endfunc func Test_expr_fails() diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -54,7 +54,7 @@ def CallRecursive(n: number): number enddef def CallMapRecursive(l: list): number - return map(l, {_, v -> CallMapRecursive([v])})[0] + return map(l, (_, v) => CallMapRecursive([v]))[0] enddef def Test_funcdepth_error() @@ -310,7 +310,7 @@ def Test_nested_global_function() vim9script def Outer() def g:Inner() - echo map([1, 2, 3], {_, v -> v + 1}) + echo map([1, 2, 3], (_, v) => v + 1) enddef g:Inner() enddef @@ -509,11 +509,11 @@ def Test_call_funcref_wrong_args() enddef def Test_call_lambda_args() - CheckDefFailure(['echo {i -> 0}()'], - 'E119: Not enough arguments for function: {i -> 0}()') + CheckDefFailure(['echo ((i) => 0)()'], + 'E119: Not enough arguments for function: ((i) => 0)()') var lines =<< trim END - var Ref = {x: number, y: number -> x + y} + var Ref = (x: number, y: number) => x + y echo Ref(1, 'x') END CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string') @@ -522,7 +522,7 @@ enddef def Test_lambda_uses_assigned_var() CheckDefSuccess([ 'var x: any = "aaa"' - 'x = filter(["bbb"], {_, v -> v =~ x})']) + 'x = filter(["bbb"], (_, v) => v =~ x)']) enddef " Default arg and varargs @@ -1413,12 +1413,12 @@ enddef def Test_closure_simple() var local = 'some ' - RefFunc({s -> local .. s})->assert_equal('some more') + RefFunc((s) => local .. s)->assert_equal('some more') enddef def MakeRef() var local = 'some ' - g:Ref = {s -> local .. s} + g:Ref = (s) => local .. s enddef def Test_closure_ref_after_return() @@ -1429,8 +1429,8 @@ enddef def MakeTwoRefs() var local = ['some'] - g:Extend = {s -> local->add(s)} - g:Read = {-> local} + g:Extend = (s) => local->add(s) + g:Read = () => local enddef def Test_closure_two_refs() @@ -1467,12 +1467,12 @@ enddef def MakeArgRefs(theArg: string) var local = 'loc_val' - g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s} + g:UseArg = (s) => theArg .. '/' .. local .. '/' .. s enddef def MakeArgRefsVarargs(theArg: string, ...rest: list) var local = 'the_loc' - g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)} + g:UseVararg = (s) => theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest) enddef def Test_closure_using_argument() @@ -1526,7 +1526,7 @@ endfunc def Test_call_closure_not_compiled() var text = 'text' - g:Ref = {s -> s .. text} + g:Ref = (s) => s .. text GetResult(g:Ref)->assert_equal('sometext') enddef @@ -1536,7 +1536,7 @@ def Test_double_closure_fails() def Func() var name = 0 for i in range(2) - timer_start(0, {-> name}) + timer_start(0, () => name) endfor enddef Func() @@ -1549,8 +1549,8 @@ def Test_nested_closure_used() vim9script def Func() var x = 'hello' - var Closure = {-> x} - g:Myclosure = {-> Closure()} + var Closure = () => x + g:Myclosure = () => Closure() enddef Func() assert_equal('hello', g:Myclosure()) @@ -1565,7 +1565,7 @@ def Test_nested_closure_fails() FuncB(0) enddef def FuncB(n: number): list - return map([0], {_, v -> n}) + return map([0], (_, v) => n) enddef FuncA() END @@ -1642,8 +1642,8 @@ def Test_nested_lambda() vim9script def Func() var x = 4 - var Lambda1 = {-> 7} - var Lambda2 = {-> [Lambda1(), x]} + var Lambda1 = () => 7 + var Lambda2 = () => [Lambda1(), x] var res = Lambda2() assert_equal([7, 4], res) enddef @@ -1653,8 +1653,8 @@ def Test_nested_lambda() enddef def Shadowed(): list - var FuncList: list = [{ -> 42}] - return FuncList->map({_, Shadowed -> Shadowed()}) + var FuncList: list = [() => 42] + return FuncList->map((_, Shadowed) => Shadowed()) enddef def Test_lambda_arg_shadows_func() @@ -1676,15 +1676,15 @@ def Test_script_var_in_lambda() var lines =<< trim END vim9script var script = 'test' - assert_equal(['test'], map(['one'], {-> script})) + assert_equal(['test'], map(['one'], () => script)) END CheckScriptSuccess(lines) enddef def Line_continuation_in_lambda(): list var x = range(97, 100) - ->map({_, v -> nr2char(v) - ->toupper()}) + ->map((_, v) => nr2char(v) + ->toupper()) ->reverse() return x enddef @@ -1772,11 +1772,11 @@ def Test_recursive_call() enddef def TreeWalk(dir: string): list - return readdir(dir)->map({_, val -> + return readdir(dir)->map((_, val) => fnamemodify(dir .. '/' .. val, ':p')->isdirectory() ? {[val]: TreeWalk(dir .. '/' .. val)} : val - }) + ) enddef def Test_closure_in_map() @@ -1890,7 +1890,7 @@ def Test_block_scoped_var() var x = ['a', 'b', 'c'] if 1 var y = 'x' - map(x, {-> y}) + map(x, () => y) endif var z = x assert_equal(['x', 'x', 'x'], z) @@ -1922,7 +1922,7 @@ def Test_did_emsg_reset() vim9script au BufWinLeave * # def Func() - popup_menu('', {callback: {-> popup_create('', {})->popup_close()}}) + popup_menu('', {callback: () => popup_create('', {})->popup_close()}) eval [][0] enddef nno call Func() @@ -2014,7 +2014,7 @@ def Test_dict_member_with_silent() var d: dict def Func() try - g:result = map([], {_, v -> {}[v]})->join() .. d[''] + g:result = map([], (_, v) => ({}[v]))->join() .. d[''] catch endtry enddef diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -1162,7 +1162,7 @@ def Run_Test_import_fails_on_command_lin var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', { rows: 6, wait_for_ruler: 0}) - WaitForAssert({-> assert_match('^E1094:', term_getline(buf, 5))}) + WaitForAssert(() => assert_match('^E1094:', term_getline(buf, 5))) delete('XexportCmd.vim') StopVimInTerminal(buf) @@ -3064,7 +3064,7 @@ def Run_Test_define_func_at_command_line # define Afunc() on the command line term_sendkeys(buf, ":def Afunc()\Bfunc()\enddef\") term_sendkeys(buf, ":call CheckAndQuit()\") - WaitForAssert({-> assert_equal(['errors: []'], readfile('Xdidcmd'))}) + WaitForAssert(() => assert_equal(['errors: []'], readfile('Xdidcmd'))) call StopVimInTerminal(buf) delete('XcallFunc') 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 */ /**/ + 2257, +/**/ 2256, /**/ 2255, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2938,7 +2938,7 @@ compile_list(char_u **arg, cctx_T *cctx, } /* - * parse a lambda: "{arg, arg -> expr}" or "(arg, arg) => expr" + * Parse a lambda: "(arg, arg) => expr" * "*arg" points to the '{'. * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda. */ @@ -2988,52 +2988,6 @@ compile_lambda(char_u **arg, cctx_T *cct } /* - * Compile a lamda call: expr->{lambda}(args) - * "arg" points to the "{". - */ - static int -compile_lambda_call(char_u **arg, cctx_T *cctx) -{ - ufunc_T *ufunc; - typval_T rettv; - int argcount = 1; - int ret = FAIL; - - // Get the funcref in "rettv". - if (get_lambda_tv(arg, &rettv, TRUE, &EVALARG_EVALUATE) == FAIL) - return FAIL; - - if (**arg != '(') - { - if (*skipwhite(*arg) == '(') - emsg(_(e_nowhitespace)); - else - semsg(_(e_missing_paren), "lambda"); - clear_tv(&rettv); - return FAIL; - } - - ufunc = rettv.vval.v_partial->pt_func; - ++ufunc->uf_refcount; - clear_tv(&rettv); - ga_init2(&ufunc->uf_type_list, sizeof(type_T *), 10); - - // The function will have one line: "return {expr}". Compile it into - // instructions so that we get any errors right now. - compile_def_function(ufunc, TRUE, cctx); - - // compile the arguments - *arg = skipwhite(*arg + 1); - if (compile_arguments(arg, cctx, &argcount) == OK) - // call the compiled function - ret = generate_CALL(cctx, ufunc, argcount); - - if (ret == FAIL) - func_ptr_unref(ufunc); - return ret; -} - -/* * parse a dict: {key: val, [key]: val} * "*arg" points to the '{'. * ppconst->pp_is_const is set if all item values are a constant. @@ -3602,14 +3556,7 @@ compile_subscript( p += 2; *arg = skipwhite(p); // No line break supported right after "->". - if (**arg == '{') - { - // lambda call: list->{lambda} - // TODO: remove this - if (compile_lambda_call(arg, cctx) == FAIL) - return FAIL; - } - else if (**arg == '(') + if (**arg == '(') { int argcount = 1; char_u *expr; @@ -3631,7 +3578,10 @@ compile_subscript( ++*arg; if (**arg != '(') { - semsg(_(e_missing_paren), *arg); + if (*skipwhite(*arg) == '(') + emsg(_(e_nowhitespace)); + else + semsg(_(e_missing_paren), *arg); return FAIL; } @@ -4005,16 +3955,9 @@ compile_expr7( break; /* - * Lambda: {arg, arg -> expr} * Dictionary: {'key': val, 'key': val} */ - case '{': // Try parsing as a lambda, if NOTDONE is returned it - // must be a dict. - // TODO: if we go with the "(arg) => expr" syntax remove - // this - ret = compile_lambda(arg, cctx); - if (ret == NOTDONE) - ret = compile_dict(arg, cctx, ppconst); + case '{': ret = compile_dict(arg, cctx, ppconst); break; /*