]> granicus.if.org Git - vim/commitdiff
patch 8.2.2212: Vim9: lambda with => does not work at the script level v8.2.2212
authorBram Moolenaar <Bram@vim.org>
Fri, 25 Dec 2020 14:24:23 +0000 (15:24 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 25 Dec 2020 14:24:23 +0000 (15:24 +0100)
Problem:    Vim9: lambda with => does not work at the script level.
Solution:   Make it work.

src/eval.c
src/testdir/test_vim9_assign.vim
src/testdir/test_vim9_expr.vim
src/userfunc.c
src/version.c
src/vim9type.c

index e3a3592c8cb3cbf54b20d13d4986d6d6307f4c94..df5b8427db89b28b86f746ab8586c3774ca2c232 100644 (file)
@@ -3349,8 +3349,13 @@ eval7(
 
     /*
      * nested expression: (expression).
+     * lambda: (arg) => expr
      */
-    case '(':  {
+    case '(':  ret = NOTDONE;
+               if (in_vim9script())
+                   ret = get_lambda_tv(arg, rettv, TRUE, evalarg);
+               if (ret == NOTDONE)
+               {
                    *arg = skipwhite_and_linebreak(*arg + 1, evalarg);
                    ret = eval1(arg, rettv, evalarg);   // recursive!
 
index d5e1b333783b18ca3e4bab668df0e14c60d71d52..ea344fe631f2883260c01b8b6a4c1a518e9e71b4 100644 (file)
@@ -1027,11 +1027,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)
index c48172997495458ad4b04c75ff26bf52ac1e8846..73fdb98fceb1c57860be36bf07dacbe71c3fdb47 100644 (file)
@@ -1953,15 +1953,25 @@ def Test_expr7_new_lambda()
       # Lambda returning a dict
       var Lmb = () => ({key: 42})
       assert_equal({key: 42}, Lmb())
+
+      var RefOne: func(number): string = (a: number): string => 'x'
+      var RefTwo: func(number): any = (a: number): any => 'x'
+
+      var Fx = (a) => ({k1: 0,
+                         k2: 1})
+      var Fy = (a) => [0,
+                       1]
   END
-  CheckDefSuccess(lines)
+  CheckDefAndScriptSuccess(lines)
 
   CheckDefFailure(["var Ref = (a)=>a + 1"], 'E1001:')
   CheckDefFailure(["var Ref = (a)=> a + 1"], 'E1001:')
   CheckDefFailure(["var Ref = (a) =>a + 1"], 'E1001:')
 
-  CheckDefSuccess(["var Ref: func(number): string = (a: number): string => 'x'"])
-  CheckDefSuccess(["var Ref: func(number): any = (a: number): any => 'x'"])
+  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:')
 
@@ -1978,11 +1988,9 @@ def Test_expr7_new_lambda()
 #        '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
 
index 5ba90ae830881db02d03210e4ba503caf2cc65d6..ea6fa10d8bce41fa6085a619f6065e6da41f7410 100644 (file)
@@ -461,21 +461,35 @@ register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
 /*
  * Skip over "->" or "=>" after the arguments of a lambda.
  * If ": type" is found make "ret_type" point to "type".
+ * If "white_error" is not NULL check for correct use of white space and set
+ * "white_error" to TRUE if there is an error.
  * Return NULL if no valid arrow found.
  */
     static char_u *
-skip_arrow(char_u *start, int equal_arrow, char_u **ret_type)
+skip_arrow(
+       char_u  *start,
+       int     equal_arrow,
+       char_u  **ret_type,
+       int     *white_error)
 {
-    char_u *s = start;
+    char_u  *s = start;
+    char_u  *bef = start - 2; // "start" points to > of ->
 
     if (equal_arrow)
     {
        if (*s == ':')
        {
+           if (white_error != NULL && !VIM_ISWHITE(s[1]))
+           {
+               *white_error = TRUE;
+               semsg(_(e_white_space_required_after_str), ":");
+               return NULL;
+           }
            s = skipwhite(s + 1);
            *ret_type = s;
            s = skip_type(s, TRUE);
        }
+       bef = s;
        s = skipwhite(s);
        if (*s != '=')
            return NULL;
@@ -483,6 +497,14 @@ skip_arrow(char_u *start, int equal_arrow, char_u **ret_type)
     }
     if (*s != '>')
        return NULL;
+    if (white_error != NULL && ((!VIM_ISWHITE(*bef) && *bef != '{')
+               || !IS_WHITE_OR_NUL(s[1])))
+    {
+       *white_error = TRUE;
+       semsg(_(e_white_space_required_before_and_after_str),
+                                                   equal_arrow ? "=>" : "->");
+       return NULL;
+    }
     return skipwhite(s + 1);
 }
 
@@ -516,6 +538,7 @@ get_lambda_tv(
     int                eval_lavars = FALSE;
     char_u     *tofree = NULL;
     int                equal_arrow = **arg == '(';
+    int                white_error = FALSE;
 
     if (equal_arrow && !in_vim9script())
        return NOTDONE;
@@ -529,7 +552,7 @@ get_lambda_tv(
     ret = get_function_args(&s, equal_arrow ? ')' : '-', NULL,
            types_optional ? &argtypes : NULL, types_optional,
                                                 NULL, NULL, TRUE, NULL, NULL);
-    if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type) == NULL)
+    if (ret == FAIL || skip_arrow(s, equal_arrow, &ret_type, NULL) == NULL)
     {
        if (types_optional)
            ga_clear_strings(&argtypes);
@@ -546,12 +569,14 @@ get_lambda_tv(
            types_optional ? &argtypes : NULL, types_optional,
                                            &varargs, NULL, FALSE, NULL, NULL);
     if (ret == FAIL
-                 || (*arg = skip_arrow(*arg, equal_arrow, &ret_type)) == NULL)
+                 || (s = skip_arrow(*arg, equal_arrow, &ret_type,
+                                                       &white_error)) == NULL)
     {
        if (types_optional)
            ga_clear_strings(&argtypes);
-       return NOTDONE;
+       return white_error ? FAIL : NOTDONE;
     }
+    *arg = s;
 
     // Set up a flag for checking local variables and arguments.
     if (evaluate)
@@ -647,8 +672,6 @@ get_lambda_tv(
            if (register_closure(fp) == FAIL)
                goto errret;
        }
-       else
-           fp->uf_scoped = NULL;
 
 #ifdef FEAT_PROFILE
        if (prof_def_func())
index 762e912631e6431d6db7dfd12dcbda5fb92a335e..75a1e4b2d0f9ccace75f228e9594c6b90888c5cc 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2212,
 /**/
     2211,
 /**/
index 7d8df695f494817d1acf70efee3cead0b3144820..6ea362cb7d473edc3d70a5c992717e91fe74520e 100644 (file)
@@ -338,6 +338,8 @@ typval2type_int(typval_T *tv, garray_T *type_gap)
            if (ufunc->uf_def_status == UF_TO_BE_COMPILED
                            && compile_def_function(ufunc, TRUE, NULL) == FAIL)
                return NULL;
+           if (ufunc->uf_func_type == NULL)
+               set_function_type(ufunc);
            if (ufunc->uf_func_type != NULL)
                return ufunc->uf_func_type;
        }