To: vim_dev@googlegroups.com Subject: Patch 8.2.2227 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2227 Problem: Vim9: recognizing lambda is too complicated. Solution: Call compile_lambda() and check for NOTDONE. Files: src/vim9compile.c, src/userfunc.c, src/testdir/test_vim9_expr.vim *** ../vim-8.2.2226/src/vim9compile.c 2020-12-27 13:39:44.659044653 +0100 --- src/vim9compile.c 2020-12-27 14:35:03.267064104 +0100 *************** *** 2949,2958 **** --- 2949,2960 ---- /* * 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. */ static int compile_lambda(char_u **arg, cctx_T *cctx) { + int r; typval_T rettv; ufunc_T *ufunc; evalarg_T evalarg; *************** *** 2962,2971 **** evalarg.eval_cctx = cctx; // Get the funcref in "rettv". ! if (get_lambda_tv(arg, &rettv, TRUE, &evalarg) != OK) { clear_evalarg(&evalarg, NULL); ! return FAIL; } // "rettv" will now be a partial referencing the function. --- 2964,2974 ---- evalarg.eval_cctx = cctx; // Get the funcref in "rettv". ! r = get_lambda_tv(arg, &rettv, TRUE, &evalarg); ! if (r != OK) { clear_evalarg(&evalarg, NULL); ! return r; } // "rettv" will now be a partial referencing the function. *************** *** 4001,4026 **** * Lambda: {arg, arg -> expr} * Dictionary: {'key': val, 'key': val} */ ! case '{': { ! char_u *start = skipwhite(*arg + 1); ! char_u *after = start; ! garray_T ga_arg; ! ! // Find out what comes after the arguments. ! ret = get_function_args(&after, '-', NULL, ! &ga_arg, TRUE, NULL, NULL, ! TRUE, NULL, NULL); ! if (ret != FAIL && after[0] == '>' ! && ((after > start + 2 ! && VIM_ISWHITE(after[-2])) ! || after == start + 1) ! && IS_WHITE_OR_NUL(after[1])) ! // TODO: if we go with the "(arg) => expr" syntax ! // remove this ! ret = compile_lambda(arg, cctx); ! else ! ret = compile_dict(arg, cctx, ppconst); ! } break; /* --- 4004,4016 ---- * 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; /* *************** *** 4051,4082 **** * lambda: (arg, arg) => expr * funcref: (arg, arg) => { statement } */ ! case '(': { ! char_u *start = skipwhite(*arg + 1); ! char_u *after = start; ! garray_T ga_arg; ! ! // Find out if "=>" comes after the (). ! ret = get_function_args(&after, ')', NULL, ! &ga_arg, TRUE, NULL, NULL, ! TRUE, NULL, NULL); ! if (ret == OK && VIM_ISWHITE( ! *after == ':' ? after[1] : *after)) ! { ! if (*after == ':') ! // Skip over type in "(arg): type". ! after = skip_type(skipwhite(after + 1), TRUE); ! ! after = skipwhite(after); ! if (after[0] == '=' && after[1] == '>' ! && IS_WHITE_OR_NUL(after[2])) ! { ! ret = compile_lambda(arg, cctx); ! break; ! } ! } ret = compile_parenthesis(arg, cctx, ppconst); - } break; default: ret = NOTDONE; --- 4041,4050 ---- * lambda: (arg, arg) => expr * funcref: (arg, arg) => { statement } */ ! case '(': // if compile_lambda returns NOTDONE then it must be (expr) ! ret = compile_lambda(arg, cctx); ! if (ret == NOTDONE) ret = compile_parenthesis(arg, cctx, ppconst); break; default: ret = NOTDONE; *** ../vim-8.2.2226/src/userfunc.c 2020-12-26 17:43:03.284516767 +0100 --- src/userfunc.c 2020-12-27 14:30:51.651986714 +0100 *************** *** 570,576 **** &varargs, NULL, FALSE, NULL, NULL); if (ret == FAIL || (s = skip_arrow(*arg, equal_arrow, &ret_type, ! equal_arrow ? &white_error : NULL)) == NULL) { if (types_optional) ga_clear_strings(&argtypes); --- 570,576 ---- &varargs, NULL, FALSE, NULL, NULL); if (ret == FAIL || (s = skip_arrow(*arg, equal_arrow, &ret_type, ! equal_arrow || in_vim9script() ? &white_error : NULL)) == NULL) { if (types_optional) ga_clear_strings(&argtypes); *** ../vim-8.2.2226/src/testdir/test_vim9_expr.vim 2020-12-25 21:56:53.412944936 +0100 --- src/testdir/test_vim9_expr.vim 2020-12-27 14:36:02.906845507 +0100 *************** *** 1863,1871 **** END CheckDefAndScriptSuccess(lines) ! CheckDefFailure(["var Ref = {a->a + 1}"], 'E720:') ! CheckDefFailure(["var Ref = {a-> a + 1}"], 'E720:') ! CheckDefFailure(["var Ref = {a ->a + 1}"], 'E720:') CheckDefFailure(["filter([1, 2], {k,v -> 1})"], 'E1069:', 1) # error is in first line of the lambda --- 1863,1871 ---- 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 *************** *** 1964,1976 **** END CheckDefAndScriptSuccess(lines) ! CheckDefFailure(["var Ref = (a)=>a + 1"], 'E1001:') ! CheckDefFailure(["var Ref = (a)=> a + 1"], 'E1001:') ! CheckDefFailure(["var Ref = (a) =>a + 1"], 'E1001:') ! ! 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:') --- 1964,1972 ---- END CheckDefAndScriptSuccess(lines) ! CheckDefAndScriptFailure(["var Ref = (a)=>a + 1"], 'E1004:') ! CheckDefAndScriptFailure(["var Ref = (a)=> a + 1"], 'E1004:') ! CheckDefAndScriptFailure(["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:') *************** *** 2682,2688 **** 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 --- 2678,2684 ---- 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 *** ../vim-8.2.2226/src/version.c 2020-12-27 14:02:23.818275527 +0100 --- src/version.c 2020-12-27 14:36:34.074731272 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2227, /**/ -- The only backup you need is the one that you didn't have time for. (Murphy) /// 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 ///