Patch 8.2.2721
Problem:    Vim9: cannot have a linebreak inside a lambda.
Solution:   Compile the expression before the arguments.
Files:      src/vim9compile.c, src/testdir/test_vim9_expr.vim


*** ../vim-8.2.2720/src/vim9compile.c   2021-04-05 17:11:11.093726064 +0200
--- src/vim9compile.c   2021-04-05 19:34:28.940626689 +0200
***************
*** 3975,3997 ****
            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 != '(')
                {
                    if (*skipwhite(*arg) == '(')
--- 3975,3999 ----
            if (**arg == '(')
            {
                int         argcount = 1;
!               garray_T    *stack = &cctx->ctx_type_stack;
!               int         type_idx_start = stack->ga_len;
                type_T      *type;
+               int         expr_isn_start = cctx->ctx_instr.ga_len;
+               int         expr_isn_end;
+               int         arg_isn_count;
  
                // Funcref call:  list->(Refs[2])(arg)
                // or lambda:     list->((arg) => expr)(arg)
!               //
!               // Fist compile the function expression.
!               if (compile_parenthesis(arg, cctx, ppconst) == FAIL)
                    return FAIL;
! 
!               // Remember the next instruction index, where the instructions
!               // for arguments are being written.
!               expr_isn_end = cctx->ctx_instr.ga_len;
! 
!               // Compile the arguments.
                if (**arg != '(')
                {
                    if (*skipwhite(*arg) == '(')
***************
*** 4000,4015 ****
                        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)
--- 4002,4044 ----
                        semsg(_(e_missing_paren), *arg);
                    return FAIL;
                }
                *arg = skipwhite(*arg + 1);
                if (compile_arguments(arg, cctx, &argcount) == FAIL)
                    return FAIL;
  
!               // Move the instructions for the arguments to before the
!               // instructions of the expression and move the type of the
!               // expression after the argument types.  This is what ISN_PCALL
!               // expects.
                stack = &cctx->ctx_type_stack;
+               arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end;
+               if (arg_isn_count > 0)
+               {
+                   int     expr_isn_count = expr_isn_end - expr_isn_start;
+                   isn_T   *isn = ALLOC_MULT(isn_T, expr_isn_count);
+ 
+                   if (isn == NULL)
+                       return FAIL;
+                   mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data)
+                                                             + expr_isn_start,
+                                              sizeof(isn_T) * expr_isn_count);
+                   mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
+                                                             + expr_isn_start,
+                            ((isn_T *)cctx->ctx_instr.ga_data) + expr_isn_end,
+                                               sizeof(isn_T) * arg_isn_count);
+                   mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
+                                             + expr_isn_start + arg_isn_count,
+                                         isn, sizeof(isn_T) * expr_isn_count);
+                   vim_free(isn);
+ 
+                   type = ((type_T **)stack->ga_data)[type_idx_start];
+                   mch_memmove(((type_T **)stack->ga_data) + type_idx_start,
+                             ((type_T **)stack->ga_data) + type_idx_start + 1,
+                             sizeof(type_T *)
+                                      * (stack->ga_len - type_idx_start - 1));
+                   ((type_T **)stack->ga_data)[stack->ga_len - 1] = type;
+               }
+ 
                type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
                if (generate_PCALL(cctx, argcount,
                                (char_u *)"[expression]", type, FALSE) == FAIL)
*** ../vim-8.2.2720/src/testdir/test_vim9_expr.vim      2021-04-05 
13:36:30.155371201 +0200
--- src/testdir/test_vim9_expr.vim      2021-04-05 19:35:39.968477986 +0200
***************
*** 2075,2090 ****
  enddef
  
  def Test_expr7_lambda_vim9script()
-   # TODO: make this work in a :def function
    var lines =<< trim END
-       vim9script
        var v = 10->((a) =>
            a
              + 2
              )()
        assert_equal(12, v)
    END
!   CheckScriptSuccess(lines)
  
    # nested lambda with line breaks
    lines =<< trim END
--- 2075,2088 ----
  enddef
  
  def Test_expr7_lambda_vim9script()
    var lines =<< trim END
        var v = 10->((a) =>
            a
              + 2
              )()
        assert_equal(12, v)
    END
!   CheckDefAndScriptSuccess(lines)
  
    # nested lambda with line breaks
    lines =<< trim END
*** ../vim-8.2.2720/src/version.c       2021-04-05 18:20:42.024142486 +0200
--- src/version.c       2021-04-05 19:36:46.704334790 +0200
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2721,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
65. The last time you looked at the clock it was 11:30pm, and in what
    seems like only a few seconds later, your sister runs past you to
    catch her 7am school bus.

 /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            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 vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202104051741.135HfnQl3128645%40masaka.moolenaar.net.

Raspunde prin e-mail lui