]> granicus.if.org Git - vim/commitdiff
patch 8.2.2227: Vim9: recognizing lambda is too complicated v8.2.2227
authorBram Moolenaar <Bram@vim.org>
Sun, 27 Dec 2020 13:43:30 +0000 (14:43 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 27 Dec 2020 13:43:30 +0000 (14:43 +0100)
Problem:    Vim9: recognizing lambda is too complicated.
Solution:   Call compile_lambda() and check for NOTDONE.

src/testdir/test_vim9_expr.vim
src/userfunc.c
src/version.c
src/vim9compile.c

index e4f7f2d10d1b6de80e2a1929ba46387949be982e..9373db20457141924837598a19cf9802a19c7820 100644 (file)
@@ -1863,9 +1863,9 @@ def Test_expr7_lambda()
   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(["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,13 +1964,9 @@ def Test_expr7_new_lambda()
   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:')
+  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,7 +2678,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()"], 'E723:', 2)
+  call CheckDefExecFailure(["{a: 1->len()"], 'E1004:', 1)
   call CheckDefExecFailure(["{['a']: 1->len()"], 'E723:', 2)
 endfunc
 
index e496bce90a2d446715dcaacfbe6c78cfa69998d6..2e93f3ee466815d2a73dd81fd3bb6209fb39d2f7 100644 (file)
@@ -570,7 +570,7 @@ get_lambda_tv(
                                            &varargs, NULL, FALSE, NULL, NULL);
     if (ret == FAIL
                  || (s = skip_arrow(*arg, equal_arrow, &ret_type,
-                                  equal_arrow ? &white_error : NULL)) == NULL)
+               equal_arrow || in_vim9script() ? &white_error : NULL)) == NULL)
     {
        if (types_optional)
            ga_clear_strings(&argtypes);
index 989a7d9b0cb9fe502058a8dd778983c6f5fff9e0..f9216ced87c1fd4c3b3a65ad941e41b5d2d0f1f8 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2227,
 /**/
     2226,
 /**/
index bd530b1e942572d8e5bb17f39d9abbdf8ac629b5..6a4e62730a6d5d3b9e422e808795d15d03f12597 100644 (file)
@@ -2949,10 +2949,12 @@ compile_list(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
 /*
  * 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,10 +2964,11 @@ compile_lambda(char_u **arg, cctx_T *cctx)
     evalarg.eval_cctx = cctx;
 
     // Get the funcref in "rettv".
-    if (get_lambda_tv(arg, &rettv, TRUE, &evalarg) != OK)
+    r = get_lambda_tv(arg, &rettv, TRUE, &evalarg);
+    if (r != OK)
     {
        clear_evalarg(&evalarg, NULL);
-       return FAIL;
+       return r;
     }
 
     // "rettv" will now be a partial referencing the function.
@@ -4001,26 +4004,13 @@ compile_expr7(
         * 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);
-                   }
+       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,32 +4041,10 @@ compile_expr7(
         * 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;
-                           }
-                       }
+       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;