To: vim_dev@googlegroups.com Subject: Patch 8.2.2257 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2257 Problem: Vim9: using -> for lambda is ambiguous. Solution: Stop supporting ->, must use =>. Files: src/eval.c, src/vim9compile.c, src/testdir/test_vim9_assign.vim, src/testdir/test_vim9_builtin.vim, src/testdir/test_vim9_cmd.vim, src/testdir/test_vim9_disassemble.vim, src/testdir/test_vim9_expr.vim, src/testdir/test_vim9_func.vim, src/testdir/test_vim9_script.vim *** ../vim-8.2.2256/src/eval.c 2020-12-30 21:16:27.727686851 +0100 --- src/eval.c 2020-12-31 21:18:44.197465563 +0100 *************** *** 3316,3322 **** * Lambda: {arg, arg -> expr} * Dictionary: {'key': val, 'key': val} */ ! case '{': ret = get_lambda_tv(arg, rettv, in_vim9script(), evalarg); if (ret == NOTDONE) ret = eval_dict(arg, rettv, evalarg, FALSE); break; --- 3316,3325 ---- * Lambda: {arg, arg -> expr} * Dictionary: {'key': val, 'key': val} */ ! 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,3623 **** *arg += 2; rettv->v_type = VAR_UNKNOWN; ! ret = get_lambda_tv(arg, rettv, FALSE, evalarg); if (ret != OK) return FAIL; else if (**arg != '(') --- 3620,3643 ---- *arg += 2; rettv->v_type = VAR_UNKNOWN; ! 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,5652 **** *arg = p; if (ret == OK) { ! if ((*arg)[2] == '{') ! // expr->{lambda}() ret = eval_lambda(arg, rettv, evalarg, verbose); else // expr->name() --- 5665,5672 ---- *arg = p; if (ret == OK) { ! if (((*arg)[2] == '{' && !in_vim9script()) || (*arg)[2] == '(') ! // expr->{lambda}() or expr->(lambda)() ret = eval_lambda(arg, rettv, evalarg, verbose); else // expr->name() *** ../vim-8.2.2256/src/vim9compile.c 2020-12-31 17:40:57.536087870 +0100 --- src/vim9compile.c 2020-12-31 19:52:38.426638262 +0100 *************** *** 2938,2944 **** } /* ! * parse a lambda: "{arg, arg -> expr}" or "(arg, arg) => expr" * "*arg" points to the '{'. * Returns OK/FAIL when a lambda is recognized, NOTDONE if it's not a lambda. */ --- 2938,2944 ---- } /* ! * 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,3039 **** } /* - * 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. --- 2988,2993 ---- *************** *** 3602,3615 **** 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 == '(') { int argcount = 1; char_u *expr; --- 3556,3562 ---- p += 2; *arg = skipwhite(p); // No line break supported right after "->". ! if (**arg == '(') { int argcount = 1; char_u *expr; *************** *** 3631,3637 **** ++*arg; if (**arg != '(') { ! semsg(_(e_missing_paren), *arg); return FAIL; } --- 3578,3587 ---- ++*arg; if (**arg != '(') { ! if (*skipwhite(*arg) == '(') ! emsg(_(e_nowhitespace)); ! else ! semsg(_(e_missing_paren), *arg); return FAIL; } *************** *** 4005,4020 **** 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); break; /* --- 3955,3963 ---- break; /* * Dictionary: {'key': val, 'key': val} */ ! case '{': ret = compile_dict(arg, cctx, ppconst); break; /* *** ../vim-8.2.2256/src/testdir/test_vim9_assign.vim 2020-12-31 17:40:57.536087870 +0100 --- src/testdir/test_vim9_assign.vim 2020-12-31 21:10:21.731523671 +0100 *************** *** 66,72 **** CheckDefFailure(['var x:string'], 'E1069:') CheckDefFailure(['var x:string = "x"'], 'E1069:') CheckDefFailure(['var a:string = "x"'], 'E1069:') ! CheckDefFailure(['var lambda = {-> "lambda"}'], 'E704:') CheckScriptFailure(['var x = "x"'], 'E1124:') var nr: number = 1234 --- 66,72 ---- CheckDefFailure(['var x:string'], 'E1069:') CheckDefFailure(['var x:string = "x"'], 'E1069:') CheckDefFailure(['var a:string = "x"'], 'E1069:') ! CheckDefFailure(['var lambda = () => "lambda"'], 'E704:') CheckScriptFailure(['var x = "x"'], 'E1124:') var nr: number = 1234 *************** *** 1032,1042 **** # check if assign a lambda to a variable which type is func or any. var lines =<< trim END vim9script ! var FuncRef = {-> 123} assert_equal(123, FuncRef()) ! var FuncRef_Func: func = {-> 123} assert_equal(123, FuncRef_Func()) ! var FuncRef_Any: any = {-> 123} assert_equal(123, FuncRef_Any()) END CheckScriptSuccess(lines) --- 1032,1042 ---- # check if assign a lambda to a variable which type is func or any. var lines =<< trim END vim9script ! var FuncRef = () => 123 assert_equal(123, FuncRef()) ! var FuncRef_Func: func = () => 123 assert_equal(123, FuncRef_Func()) ! var FuncRef_Any: any = () => 123 assert_equal(123, FuncRef_Any()) END CheckScriptSuccess(lines) *** ../vim-8.2.2256/src/testdir/test_vim9_builtin.vim 2020-12-29 20:25:16.470694750 +0100 --- src/testdir/test_vim9_builtin.vim 2020-12-31 19:14:38.022330888 +0100 *************** *** 231,237 **** 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 -> {}})) assert_equal([{}, {}], res) CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list but got number') --- 231,237 ---- 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) => ({}))) assert_equal([{}, {}], res) CheckDefFailure(['extend([1, 2], 3)'], 'E1013: Argument 2: type mismatch, expected list but got number') *************** *** 254,260 **** def Wrong_dict_key_type(items: list): list ! return filter(items, {_, val -> get({[val]: 1}, 'x')}) enddef def Test_map_function_arg() --- 254,260 ---- def Wrong_dict_key_type(items: list): list ! return filter(items, (_, val) => get({[val]: 1}, 'x')) enddef def Test_map_function_arg() *************** *** 313,319 **** enddef def Test_filter_return_type() ! var l = filter([1, 2, 3], {-> 1}) var res = 0 for n in l res += n --- 313,319 ---- enddef def Test_filter_return_type() ! var l = filter([1, 2, 3], () => 1) var res = 0 for n in l res += n *************** *** 323,329 **** def Test_filter_missing_argument() var dict = {aa: [1], ab: [2], ac: [3], de: [4]} ! var res = dict->filter({k -> k =~ 'a' && k !~ 'b'}) res->assert_equal({aa: [1], ac: [3]}) enddef --- 323,329 ---- def Test_filter_missing_argument() var dict = {aa: [1], ab: [2], ac: [3], de: [4]} ! var res = dict->filter((k) => k =~ 'a' && k !~ 'b') res->assert_equal({aa: [1], ac: [3]}) enddef *************** *** 539,546 **** enddef def Test_readdir() ! eval expand('sautest')->readdir({e -> e[0] !=# '.'}) ! eval expand('sautest')->readdirex({e -> e.name[0] !=# '.'}) enddef def Test_remove_return_type() --- 539,546 ---- enddef def Test_readdir() ! eval expand('sautest')->readdir((e) => e[0] !=# '.') ! eval expand('sautest')->readdirex((e) => e.name[0] !=# '.') enddef def Test_remove_return_type() *************** *** 566,581 **** setline(1, ['foo', 'bar']) var val = 0 # skip expr returns boolean ! search('bar', 'W', 0, 0, {-> val == 1})->assert_equal(2) :1 ! 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) :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:') enddef def Test_searchcount() --- 566,581 ---- setline(1, ['foo', 'bar']) var val = 0 # skip expr returns boolean ! search('bar', 'W', 0, 0, () => val == 1)->assert_equal(2) :1 ! 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) :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:') enddef def Test_searchcount() *************** *** 667,673 **** def Test_submatch() var pat = 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)' ! 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) --- 667,673 ---- def Test_submatch() var pat = 'A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)' ! 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,709 **** enddef def Test_timer_paused() ! var id = timer_start(50, {-> 0}) timer_pause(id, true) var info = timer_info(id) info[0]['paused']->assert_equal(1) --- 703,709 ---- enddef def Test_timer_paused() ! var id = timer_start(50, () => 0) timer_pause(id, true) var info = timer_info(id) info[0]['paused']->assert_equal(1) *** ../vim-8.2.2256/src/testdir/test_vim9_cmd.vim 2020-12-31 17:40:57.536087870 +0100 --- src/testdir/test_vim9_cmd.vim 2020-12-31 21:11:31.523220547 +0100 *************** *** 305,311 **** def Test_skipped_expr_linebreak() if 0 var x = [] ! ->map({ -> 0}) endif enddef --- 305,311 ---- def Test_skipped_expr_linebreak() if 0 var x = [] ! ->map(() => 0) endif enddef *************** *** 368,374 **** 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 }) assert_equal([{x: 3, y: 4}], tags) enddef --- 368,374 ---- 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 ) assert_equal([{x: 3, y: 4}], tags) enddef *** ../vim-8.2.2256/src/testdir/test_vim9_disassemble.vim 2020-12-30 20:39:17.454007601 +0100 --- src/testdir/test_vim9_disassemble.vim 2020-12-31 20:34:12.503267306 +0100 *************** *** 896,902 **** enddef def WithLambda(): string ! var F = {a -> "X" .. a .. "X"} return F("x") enddef --- 896,902 ---- enddef def WithLambda(): string ! var F = (a) => "X" .. a .. "X" return F("x") enddef *************** *** 904,910 **** assert_equal("XxX", WithLambda()) var instr = execute('disassemble WithLambda') assert_match('WithLambda\_s*' .. ! 'var F = {a -> "X" .. a .. "X"}\_s*' .. '\d FUNCREF \d\+\_s*' .. '\d STORE $0\_s*' .. 'return F("x")\_s*' .. --- 904,910 ---- assert_equal("XxX", WithLambda()) var instr = execute('disassemble WithLambda') assert_match('WithLambda\_s*' .. ! 'var F = (a) => "X" .. a .. "X"\_s*' .. '\d FUNCREF \d\+\_s*' .. '\d STORE $0\_s*' .. 'return F("x")\_s*' .. *************** *** 929,935 **** enddef def LambdaWithType(): number ! var Ref = {a: number -> a + 10} return Ref(g:value) enddef --- 929,935 ---- enddef def LambdaWithType(): number ! var Ref = (a: number) => a + 10 return Ref(g:value) enddef *************** *** 938,944 **** assert_equal(15, LambdaWithType()) var instr = execute('disassemble LambdaWithType') assert_match('LambdaWithType\_s*' .. ! 'var Ref = {a: number -> a + 10}\_s*' .. '\d FUNCREF \d\+\_s*' .. '\d STORE $0\_s*' .. 'return Ref(g:value)\_s*' .. --- 938,944 ---- assert_equal(15, LambdaWithType()) var instr = execute('disassemble LambdaWithType') assert_match('LambdaWithType\_s*' .. ! 'var Ref = (a: number) => a + 10\_s*' .. '\d FUNCREF \d\+\_s*' .. '\d STORE $0\_s*' .. 'return Ref(g:value)\_s*' .. *************** *** 1541,1550 **** ['{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'], ['77 == g:xx', 'COMPAREANY =='], ['77 != g:xx', 'COMPAREANY !='], --- 1541,1550 ---- ['{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'], ['77 == g:xx', 'COMPAREANY =='], ['77 != g:xx', 'COMPAREANY !='], *** ../vim-8.2.2256/src/testdir/test_vim9_expr.vim 2020-12-31 13:31:20.521507996 +0100 --- src/testdir/test_vim9_expr.vim 2020-12-31 21:14:13.210543297 +0100 *************** *** 1806,1863 **** enddef def LambdaWithComments(): func ! return {x -> # some comment x == 1 # some comment || x == 2 - } enddef def LambdaUsingArg(x: number): func ! return {-> # some comment x == 1 # some comment || x == 2 - } enddef def Test_expr7_lambda() var lines =<< trim END ! var La = { -> 'result'} assert_equal('result', La()) ! 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 ? { ['111']: 111 } : {} ! }) assert_equal([{}, {111: 111}, {}], ll) ll = range(3) ! 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 != 9 && v % 2 == 0 ? 111 : 222 ! }) assert_equal([111, 222, 111], ll) ! 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})) assert_equal(false, LambdaWithComments()(0)) assert_equal(true, LambdaWithComments()(1)) --- 1806,1861 ---- enddef def LambdaWithComments(): func ! return (x) => # some comment x == 1 # some comment || x == 2 enddef def LambdaUsingArg(x: number): func ! return () => # some comment x == 1 # some comment || x == 2 enddef def Test_expr7_lambda() var lines =<< trim END ! var La = () => 'result' assert_equal('result', La()) ! 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 ? { ['111']: 111 } : {} ! ) assert_equal([{}, {111: 111}, {}], ll) ll = range(3) ! 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 != 9 && v % 2 == 0 ? 111 : 222 ! ) assert_equal([111, 222, 111], ll) ! 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)) assert_equal(false, LambdaWithComments()(0)) assert_equal(true, LambdaWithComments()(1)) *************** *** 1867,1899 **** assert_equal(false, LambdaUsingArg(0)()) assert_equal(true, LambdaUsingArg(1)()) ! 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) # 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) enddef def NewLambdaWithComments(): func --- 1865,1895 ---- assert_equal(false, LambdaUsingArg(0)()) assert_equal(true, LambdaUsingArg(1)()) ! 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) # 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')"], '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,2011 **** def Test_expr7_lambda_vim9script() var lines =<< trim END vim9script ! var v = 10->{a -> a + 2 ! }() assert_equal(12, v) END CheckScriptSuccess(lines) --- 1998,2007 ---- def Test_expr7_lambda_vim9script() var lines =<< trim END vim9script ! var v = 10->((a) => a + 2 ! )() assert_equal(12, v) END CheckScriptSuccess(lines) *************** *** 2013,2021 **** # nested lambda with line breaks lines =<< trim END vim9script ! search('"', 'cW', 0, 0, {-> synstack('.', col('.')) ! ->map({_, v -> synIDattr(v, 'name')})->len()}) END CheckScriptSuccess(lines) enddef --- 2009,2017 ---- # nested lambda with line breaks lines =<< trim END vim9script ! search('"', 'cW', 0, 0, () => synstack('.', col('.')) ! ->map((_, v) => synIDattr(v, 'name'))->len()) END CheckScriptSuccess(lines) enddef *************** *** 2089,2096 **** 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 , b: 9}"], 'E1068:', 1) CheckDefFailure(["var x = {a: 1,b: 2}"], 'E1069:', 1) --- 2085,2092 ---- CheckDefFailure(["var x = 'a' .. #{a: 1}"], 'E1097:', 3) CheckDefFailure(["var x = {a:8}"], 'E1069:', 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,2144 **** --- 2135,2143 ---- ['two']: 2, } assert_equal({one: 1, two: 2}, d) + + var dd = {k: 123->len()} + assert_equal(3, dd.k) END CheckScriptSuccess(lines) *************** *** 2174,2180 **** vim9script var d = {one : 1} END ! CheckScriptFailure(lines, 'E1059:', 2) lines =<< trim END vim9script --- 2173,2179 ---- vim9script var d = {one : 1} END ! CheckScriptFailure(lines, 'E1068:', 2) lines =<< trim END vim9script *************** *** 2629,2635 **** unlet g:false assert_equal(true, !test_null_partial()) ! assert_equal(false, !{-> 'yes'}) assert_equal(true, !test_null_dict()) assert_equal(true, !{}) --- 2628,2634 ---- unlet g:false assert_equal(true, !test_null_partial()) ! assert_equal(false, !() => 'yes') assert_equal(true, !test_null_dict()) assert_equal(true, !{}) *************** *** 2668,2675 **** 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 = ¬exist"], 'E113:', 1) call CheckDefFailure(["&grepprg = [343]"], 'E1012:', 1) --- 2667,2674 ---- call CheckDefFailure(["var x = [1, 2"], "E697:", 2) call CheckDefFailure(["var x = [notfound]"], "E1001:", 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,2697 **** 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) endfunc --- 2690,2696 ---- call CheckDefFailure(["'yes'->", "Echo()"], 'E488: Trailing characters: ->', 1) call CheckDefExecFailure(["[1, 2->len()"], 'E697:', 2) ! call CheckDefExecFailure(["{a: 1->len()"], 'E723:', 2) call CheckDefExecFailure(["{['a']: 1->len()"], 'E723:', 2) endfunc *************** *** 2725,2736 **** # method call l = [2, 5, 6] ! l->map({k, v -> k + v}) assert_equal([2, 6, 8], l) # lambda method call l = [2, 5] ! l->{l -> add(l, 8)}() assert_equal([2, 5, 8], l) # dict member --- 2724,2735 ---- # method call l = [2, 5, 6] ! l->map((k, v) => k + v) assert_equal([2, 6, 8], l) # lambda method call l = [2, 5] ! l->((l) => add(l, 8))() assert_equal([2, 5, 8], l) # dict member *************** *** 2895,2902 **** 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) endfunc func Test_expr_fails() --- 2894,2901 ---- 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) endfunc func Test_expr_fails() *** ../vim-8.2.2256/src/testdir/test_vim9_func.vim 2020-12-31 18:28:13.706927452 +0100 --- src/testdir/test_vim9_func.vim 2020-12-31 20:28:50.536278664 +0100 *************** *** 54,60 **** enddef def CallMapRecursive(l: list): number ! return map(l, {_, v -> CallMapRecursive([v])})[0] enddef def Test_funcdepth_error() --- 54,60 ---- enddef def CallMapRecursive(l: list): number ! return map(l, (_, v) => CallMapRecursive([v]))[0] enddef def Test_funcdepth_error() *************** *** 310,316 **** vim9script def Outer() def g:Inner() ! echo map([1, 2, 3], {_, v -> v + 1}) enddef g:Inner() enddef --- 310,316 ---- vim9script def Outer() def g:Inner() ! echo map([1, 2, 3], (_, v) => v + 1) enddef g:Inner() enddef *************** *** 509,519 **** enddef def Test_call_lambda_args() ! CheckDefFailure(['echo {i -> 0}()'], ! 'E119: Not enough arguments for function: {i -> 0}()') var lines =<< trim END ! 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') --- 509,519 ---- enddef def Test_call_lambda_args() ! CheckDefFailure(['echo ((i) => 0)()'], ! 'E119: Not enough arguments for function: ((i) => 0)()') var lines =<< trim END ! 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,528 **** def Test_lambda_uses_assigned_var() CheckDefSuccess([ 'var x: any = "aaa"' ! 'x = filter(["bbb"], {_, v -> v =~ x})']) enddef " Default arg and varargs --- 522,528 ---- def Test_lambda_uses_assigned_var() CheckDefSuccess([ 'var x: any = "aaa"' ! 'x = filter(["bbb"], (_, v) => v =~ x)']) enddef " Default arg and varargs *************** *** 1413,1424 **** def Test_closure_simple() var local = 'some ' ! RefFunc({s -> local .. s})->assert_equal('some more') enddef def MakeRef() var local = 'some ' ! g:Ref = {s -> local .. s} enddef def Test_closure_ref_after_return() --- 1413,1424 ---- def Test_closure_simple() var local = 'some ' ! RefFunc((s) => local .. s)->assert_equal('some more') enddef def MakeRef() var local = 'some ' ! g:Ref = (s) => local .. s enddef def Test_closure_ref_after_return() *************** *** 1429,1436 **** def MakeTwoRefs() var local = ['some'] ! g:Extend = {s -> local->add(s)} ! g:Read = {-> local} enddef def Test_closure_two_refs() --- 1429,1436 ---- def MakeTwoRefs() var local = ['some'] ! g:Extend = (s) => local->add(s) ! g:Read = () => local enddef def Test_closure_two_refs() *************** *** 1467,1478 **** def MakeArgRefs(theArg: string) var local = 'loc_val' ! 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)} enddef def Test_closure_using_argument() --- 1467,1478 ---- def MakeArgRefs(theArg: string) var local = 'loc_val' ! 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) enddef def Test_closure_using_argument() *************** *** 1526,1532 **** def Test_call_closure_not_compiled() var text = 'text' ! g:Ref = {s -> s .. text} GetResult(g:Ref)->assert_equal('sometext') enddef --- 1526,1532 ---- def Test_call_closure_not_compiled() var text = 'text' ! g:Ref = (s) => s .. text GetResult(g:Ref)->assert_equal('sometext') enddef *************** *** 1536,1542 **** def Func() var name = 0 for i in range(2) ! timer_start(0, {-> name}) endfor enddef Func() --- 1536,1542 ---- def Func() var name = 0 for i in range(2) ! timer_start(0, () => name) endfor enddef Func() *************** *** 1549,1556 **** vim9script def Func() var x = 'hello' ! var Closure = {-> x} ! g:Myclosure = {-> Closure()} enddef Func() assert_equal('hello', g:Myclosure()) --- 1549,1556 ---- vim9script def Func() var x = 'hello' ! var Closure = () => x ! g:Myclosure = () => Closure() enddef Func() assert_equal('hello', g:Myclosure()) *************** *** 1565,1571 **** FuncB(0) enddef def FuncB(n: number): list ! return map([0], {_, v -> n}) enddef FuncA() END --- 1565,1571 ---- FuncB(0) enddef def FuncB(n: number): list ! return map([0], (_, v) => n) enddef FuncA() END *************** *** 1642,1649 **** vim9script def Func() var x = 4 ! var Lambda1 = {-> 7} ! var Lambda2 = {-> [Lambda1(), x]} var res = Lambda2() assert_equal([7, 4], res) enddef --- 1642,1649 ---- vim9script def Func() var x = 4 ! var Lambda1 = () => 7 ! var Lambda2 = () => [Lambda1(), x] var res = Lambda2() assert_equal([7, 4], res) enddef *************** *** 1653,1660 **** enddef def Shadowed(): list ! var FuncList: list = [{ -> 42}] ! return FuncList->map({_, Shadowed -> Shadowed()}) enddef def Test_lambda_arg_shadows_func() --- 1653,1660 ---- enddef def Shadowed(): list ! var FuncList: list = [() => 42] ! return FuncList->map((_, Shadowed) => Shadowed()) enddef def Test_lambda_arg_shadows_func() *************** *** 1676,1690 **** var lines =<< trim END vim9script var script = 'test' ! 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()}) ->reverse() return x enddef --- 1676,1690 ---- var lines =<< trim END vim9script var script = 'test' ! 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()) ->reverse() return x enddef *************** *** 1772,1782 **** enddef def TreeWalk(dir: string): list ! return readdir(dir)->map({_, val -> fnamemodify(dir .. '/' .. val, ':p')->isdirectory() ? {[val]: TreeWalk(dir .. '/' .. val)} : val ! }) enddef def Test_closure_in_map() --- 1772,1782 ---- enddef def TreeWalk(dir: string): list ! return readdir(dir)->map((_, val) => fnamemodify(dir .. '/' .. val, ':p')->isdirectory() ? {[val]: TreeWalk(dir .. '/' .. val)} : val ! ) enddef def Test_closure_in_map() *************** *** 1890,1896 **** var x = ['a', 'b', 'c'] if 1 var y = 'x' ! map(x, {-> y}) endif var z = x assert_equal(['x', 'x', 'x'], z) --- 1890,1896 ---- var x = ['a', 'b', 'c'] if 1 var y = 'x' ! map(x, () => y) endif var z = x assert_equal(['x', 'x', 'x'], z) *************** *** 1922,1928 **** vim9script au BufWinLeave * # def Func() ! popup_menu('', {callback: {-> popup_create('', {})->popup_close()}}) eval [][0] enddef nno call Func() --- 1922,1928 ---- vim9script au BufWinLeave * # def Func() ! popup_menu('', {callback: () => popup_create('', {})->popup_close()}) eval [][0] enddef nno call Func() *************** *** 2014,2020 **** var d: dict def Func() try ! g:result = map([], {_, v -> {}[v]})->join() .. d[''] catch endtry enddef --- 2014,2020 ---- var d: dict def Func() try ! g:result = map([], (_, v) => ({}[v]))->join() .. d[''] catch endtry enddef *** ../vim-8.2.2256/src/testdir/test_vim9_script.vim 2020-12-27 13:39:44.659044653 +0100 --- src/testdir/test_vim9_script.vim 2020-12-31 20:37:33.182636132 +0100 *************** *** 1162,1168 **** var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', { rows: 6, wait_for_ruler: 0}) ! WaitForAssert({-> assert_match('^E1094:', term_getline(buf, 5))}) delete('XexportCmd.vim') StopVimInTerminal(buf) --- 1162,1168 ---- var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', { rows: 6, wait_for_ruler: 0}) ! WaitForAssert(() => assert_match('^E1094:', term_getline(buf, 5))) delete('XexportCmd.vim') StopVimInTerminal(buf) *************** *** 3064,3070 **** # define Afunc() on the command line term_sendkeys(buf, ":def Afunc()\Bfunc()\enddef\") term_sendkeys(buf, ":call CheckAndQuit()\") ! WaitForAssert({-> assert_equal(['errors: []'], readfile('Xdidcmd'))}) call StopVimInTerminal(buf) delete('XcallFunc') --- 3064,3070 ---- # define Afunc() on the command line term_sendkeys(buf, ":def Afunc()\Bfunc()\enddef\") term_sendkeys(buf, ":call CheckAndQuit()\") ! WaitForAssert(() => assert_equal(['errors: []'], readfile('Xdidcmd'))) call StopVimInTerminal(buf) delete('XcallFunc') *** ../vim-8.2.2256/src/version.c 2020-12-31 18:28:13.706927452 +0100 --- src/version.c 2020-12-31 21:26:22.375737009 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2257, /**/ -- hundred-and-one symptoms of being an internet addict: 60. As your car crashes through the guardrail on a mountain road, your first instinct is to search for the "back" button. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///