Patch 8.2.2219
Problem:    Vim9: method call with expression not supported.
Solution:   Implement expr->(expr)().
Files:      src/vim9compile.c, src/testdir/test_vim9_expr.vim


*** ../vim-8.2.2218/src/vim9compile.c   2020-12-25 19:25:41.742706213 +0100
--- src/vim9compile.c   2020-12-25 21:46:03.877525095 +0100
***************
*** 2817,2825 ****
            && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
      {
        garray_T    *stack = &cctx->ctx_type_stack;
!       type_T      *type;
  
-       type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
        res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
        goto theend;
      }
--- 2817,2824 ----
            && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
      {
        garray_T    *stack = &cctx->ctx_type_stack;
!       type_T      *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
  
        res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
        goto theend;
      }
***************
*** 3430,3435 ****
--- 3429,3447 ----
  }
  
  /*
+  * Skip over an expression, ignoring most errors.
+  */
+     static void
+ skip_expr_cctx(char_u **arg, cctx_T *cctx)
+ {
+     evalarg_T evalarg;
+ 
+     CLEAR_FIELD(evalarg);
+     evalarg.eval_cctx = cctx;
+     skip_expr(arg, &evalarg);
+ }
+ 
+ /*
   * Compile code to apply '-', '+' and '!'.
   * When "numeric_only" is TRUE do not apply '!'.
   */
***************
*** 3488,3493 ****
--- 3500,3537 ----
  }
  
  /*
+  * Compile "(expression)": recursive!
+  * Return FAIL/OK.
+  */
+     static int
+ compile_parenthesis(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
+ {
+     int ret;
+ 
+     *arg = skipwhite(*arg + 1);
+     if (ppconst->pp_used <= PPSIZE - 10)
+     {
+       ret = compile_expr1(arg, cctx, ppconst);
+     }
+     else
+     {
+       // Not enough space in ppconst, flush constants.
+       if (generate_ppconst(cctx, ppconst) == FAIL)
+           return FAIL;
+       ret = compile_expr0(arg, cctx);
+     }
+     *arg = skipwhite(*arg);
+     if (**arg == ')')
+       ++*arg;
+     else if (ret == OK)
+     {
+       emsg(_(e_missing_close));
+       ret = FAIL;
+     }
+     return ret;
+ }
+ 
+ /*
   * Compile whatever comes after "name" or "name()".
   * Advances "*arg" only when something was recognized.
   */
***************
*** 3572,3581 ****
            }
            else if (**arg == '(')
            {
!               // Funcref call:  list->(Refs[2])()
!               // or lambda:     list->((arg) => expr)()
!               // TODO: make this work
!               if (compile_lambda_call(arg, cctx) == FAIL)
                    return FAIL;
            }
            else
--- 3616,3657 ----
            }
            else if (**arg == '(')
            {
!               int         argcount = 1;
!               char_u      *expr;
!               garray_T    *stack;
!               type_T      *type;
! 
!               // Funcref call:  list->(Refs[2])(arg)
!               // or lambda:     list->((arg) => expr)(arg)
!               // Fist compile the arguments.
!               expr = *arg;
!               *arg = skipwhite(*arg + 1);
!               skip_expr_cctx(arg, cctx);
!               *arg = skipwhite(*arg);
!               if (**arg != ')')
!               {
!                   semsg(_(e_missing_paren), *arg);
!                   return FAIL;
!               }
!               ++*arg;
!               if (**arg != '(')
!               {
!                   semsg(_(e_missing_paren), *arg);
!                   return FAIL;
!               }
! 
!               *arg = skipwhite(*arg + 1);
!               if (compile_arguments(arg, cctx, &argcount) == FAIL)
!                   return FAIL;
! 
!               // Compile the function expression.
!               if (compile_parenthesis(&expr, cctx, ppconst) == FAIL)
!                   return FAIL;
! 
!               stack = &cctx->ctx_type_stack;
!               type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
!               if (generate_PCALL(cctx, argcount,
!                               (char_u *)"[expression]", type, FALSE) == FAIL)
                    return FAIL;
            }
            else
***************
*** 3998,4025 ****
                                break;
                            }
                        }
! 
!                       // (expression): recursive!
!                       *arg = skipwhite(*arg + 1);
!                       if (ppconst->pp_used <= PPSIZE - 10)
!                       {
!                           ret = compile_expr1(arg, cctx, ppconst);
!                       }
!                       else
!                       {
!                           // Not enough space in ppconst, flush constants.
!                           if (generate_ppconst(cctx, ppconst) == FAIL)
!                               return FAIL;
!                           ret = compile_expr0(arg, cctx);
!                       }
!                       *arg = skipwhite(*arg);
!                       if (**arg == ')')
!                           ++*arg;
!                       else if (ret == OK)
!                       {
!                           emsg(_(e_missing_close));
!                           ret = FAIL;
!                       }
                    }
                    break;
  
--- 4074,4080 ----
                                break;
                            }
                        }
!                       ret = compile_parenthesis(arg, cctx, ppconst);
                    }
                    break;
  
***************
*** 4597,4603 ****
   * end:
   */
      static int
! compile_expr1(char_u **arg,  cctx_T *cctx, ppconst_T *ppconst)
  {
      char_u    *p;
      int               ppconst_used = ppconst->pp_used;
--- 4652,4658 ----
   * end:
   */
      static int
! compile_expr1(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
  {
      char_u    *p;
      int               ppconst_used = ppconst->pp_used;
***************
*** 4606,4616 ****
      // Ignore all kinds of errors when not producing code.
      if (cctx->ctx_skip == SKIP_YES)
      {
!       evalarg_T       evalarg;
! 
!       CLEAR_FIELD(evalarg);
!       evalarg.eval_cctx = cctx;
!       skip_expr(arg, &evalarg);
        return OK;
      }
  
--- 4661,4667 ----
      // Ignore all kinds of errors when not producing code.
      if (cctx->ctx_skip == SKIP_YES)
      {
!       skip_expr_cctx(arg, cctx);
        return OK;
      }
  
*** ../vim-8.2.2218/src/testdir/test_vim9_expr.vim      2020-12-25 
15:24:19.902942195 +0100
--- src/testdir/test_vim9_expr.vim      2020-12-25 21:53:38.330148915 +0100
***************
*** 2560,2565 ****
--- 2560,2598 ----
    delete('Xruntime', 'rf')
  enddef
  
+ def Test_expr7_method_call()
+   new
+   setline(1, ['first', 'last'])
+   'second'->append(1)
+   "third"->append(2)
+   assert_equal(['first', 'second', 'third', 'last'], getline(1, '$'))
+   bwipe!
+ 
+   var bufnr = bufnr()
+   var loclist = [{bufnr: bufnr, lnum: 42, col: 17, text: 'wrong'}]
+   loclist->setloclist(0)
+   assert_equal([{bufnr: bufnr,
+               lnum: 42,
+               col: 17,
+               text: 'wrong',
+               pattern: '',
+               valid: 1,
+               vcol: 0,
+               nr: 0,
+               type: '',
+               module: ''}
+               ], getloclist(0))
+ 
+   var result: bool = get({n: 0}, 'n', 0)
+   assert_equal(false, result)
+ 
+   assert_equal('+string+', 'string'->((s) => '+' .. s .. '+')())
+   assert_equal('-text-', 'text'->((s, c) => c .. s .. c)('-'))
+ 
+   var Join = (l) => join(l, 'x')
+   assert_equal('axb', ['a', 'b']->(Join)())
+ enddef
+ 
  
  def Test_expr7_not()
    var lines =<< trim END
***************
*** 2852,2884 ****
        one)
  enddef
  
- def Test_expr7_method_call()
-   new
-   setline(1, ['first', 'last'])
-   'second'->append(1)
-   "third"->append(2)
-   assert_equal(['first', 'second', 'third', 'last'], getline(1, '$'))
-   bwipe!
- 
-   var bufnr = bufnr()
-   var loclist = [{bufnr: bufnr, lnum: 42, col: 17, text: 'wrong'}]
-   loclist->setloclist(0)
-   assert_equal([{bufnr: bufnr,
-               lnum: 42,
-               col: 17,
-               text: 'wrong',
-               pattern: '',
-               valid: 1,
-               vcol: 0,
-               nr: 0,
-               type: '',
-               module: ''}
-               ], getloclist(0))
- 
-   var result: bool = get({n: 0}, 'n', 0)
-   assert_equal(false, result)
- 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)
--- 2885,2890 ----
*** ../vim-8.2.2218/src/version.c       2020-12-25 20:24:48.172245018 +0100
--- src/version.c       2020-12-25 21:52:17.594679993 +0100
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2219,
  /**/

-- 
How To Keep A Healthy Level Of Insanity:
14. Put mosquito netting around your work area. Play a tape of jungle
    sounds all day.

 /// 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/202012252057.0BPKvOK53652608%40masaka.moolenaar.net.

Raspunde prin e-mail lui