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 -- [email protected] -- 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    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202012271343.0BRDhuen4131093%40masaka.moolenaar.net.

Raspunde prin e-mail lui