Patch 8.2.1071
Problem:    Vim9: no line break allowed inside a lambda.
Solution:   Handle line break inside a lambda in Vim9 script.
Files:      src/eval.c, src/proto/eval.pro, src/evalvars.c, src/userfunc.c,
            src/proto/userfunc.pro, src/popupwin.c, src/vim9compile.c,
            src/ex_eval.c, src/globals.h, src/structs.h,
            src/testdir/test_vim9_expr.vim


*** ../vim-8.2.1070/src/eval.c  2020-06-27 14:11:50.494644105 +0200
--- src/eval.c  2020-06-27 18:02:08.197832760 +0200
***************
*** 325,332 ****
  
      if (skip)
        ++emsg_skip;
!     if (eval0(arg, &tv, eap, skip ? NULL : &EVALARG_EVALUATE)
!                                                              == FAIL || skip)
        retval = NULL;
      else
      {
--- 325,331 ----
  
      if (skip)
        ++emsg_skip;
!     if (eval0(arg, &tv, eap, skip ? NULL : &EVALARG_EVALUATE) == FAIL || skip)
        retval = NULL;
      else
      {
***************
*** 353,358 ****
--- 352,412 ----
  }
  
  /*
+  * Skip over an expression at "*pp".
+  * If in Vim9 script and line breaks are encountered, the lines are
+  * concatenated.  "evalarg->eval_tofree" will be set accordingly.
+  * Return FAIL for an error, OK otherwise.
+  */
+     int
+ skip_expr_concatenate(char_u **start, char_u **end, evalarg_T *evalarg)
+ {
+     typval_T  rettv;
+     int               res;
+     int               vim9script = current_sctx.sc_version == 
SCRIPT_VERSION_VIM9;
+     garray_T    *gap = &evalarg->eval_ga;
+     int               save_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
+ 
+     if (vim9script && evalarg->eval_cookie != NULL)
+     {
+       ga_init2(gap, sizeof(char_u *), 10);
+       if (ga_grow(gap, 1) == OK)
+           // leave room for "start"
+           ++gap->ga_len;
+     }
+ 
+     // Don't evaluate the expression.
+     if (evalarg != NULL)
+       evalarg->eval_flags &= ~EVAL_EVALUATE;
+     *end = skipwhite(*end);
+     res = eval1(end, &rettv, evalarg);
+     if (evalarg != NULL)
+       evalarg->eval_flags = save_flags;
+ 
+     if (vim9script && evalarg->eval_cookie != NULL
+                                               && evalarg->eval_ga.ga_len > 1)
+     {
+       char_u      *p;
+       size_t      endoff = STRLEN(*end);
+ 
+       // Line breaks encountered, concatenate all the lines.
+       *((char_u **)gap->ga_data) = *start;
+       p = ga_concat_strings(gap, "");
+       *((char_u **)gap->ga_data) = NULL;
+       ga_clear_strings(gap);
+       gap->ga_itemsize = 0;
+       if (p == NULL)
+           return FAIL;
+       *start = p;
+       vim_free(evalarg->eval_tofree);
+       evalarg->eval_tofree = p;
+       // Compute "end" relative to the end.
+       *end = *start + STRLEN(*start) - endoff;
+     }
+ 
+     return res;
+ }
+ 
+ /*
   * Top level evaluation function, returning a string.
   * When "convert" is TRUE convert a List into a sequence of lines and convert
   * a Float to a String.
***************
*** 1794,1807 ****
  }
  
  /*
!  * To be called when eval_next_non_blank() sets "getnext" to TRUE.
   */
      char_u *
  eval_next_line(evalarg_T *evalarg)
  {
!     vim_free(evalarg->eval_tofree);
!     evalarg->eval_tofree = getsourceline(0, evalarg->eval_cookie, 0, TRUE);
!     return skipwhite(evalarg->eval_tofree);
  }
  
  /*
--- 1848,1874 ----
  }
  
  /*
!  * To be called after eval_next_non_blank() sets "getnext" to TRUE.
   */
      char_u *
  eval_next_line(evalarg_T *evalarg)
  {
!     garray_T  *gap = &evalarg->eval_ga;
!     char_u    *line;
! 
!     line = getsourceline(0, evalarg->eval_cookie, 0, TRUE);
!     if (gap->ga_itemsize > 0 && ga_grow(gap, 1) == OK)
!     {
!       // Going to concatenate the lines after parsing.
!       ((char_u **)gap->ga_data)[gap->ga_len] = line;
!       ++gap->ga_len;
!     }
!     else
!     {
!       vim_free(evalarg->eval_tofree);
!       evalarg->eval_tofree = line;
!     }
!     return skipwhite(line);
  }
  
  /*
***************
*** 1831,1838 ****
      int               called_emsg_before = called_emsg;
      int               flags = evalarg == NULL ? 0 : evalarg->eval_flags;
  
-     if (evalarg != NULL)
-       evalarg->eval_tofree = NULL;
      p = skipwhite(arg);
      ret = eval1(&p, rettv, evalarg);
  
--- 1898,1903 ----
***************
*** 1857,1878 ****
      if (eap != NULL)
        eap->nextcmd = check_nextcmd(p);
  
!     if (evalarg != NULL)
      {
!       if (eap != NULL)
!       {
!           if (evalarg->eval_tofree != NULL)
!           {
!               // We may need to keep the original command line, e.g. for
!               // ":let" it has the variable names.  But we may also need the
!               // new one, "nextcmd" points into it.  Keep both.
!               vim_free(eap->cmdline_tofree);
!               eap->cmdline_tofree = *eap->cmdlinep;
!               *eap->cmdlinep = evalarg->eval_tofree;
!           }
!       }
!       else
!           vim_free(evalarg->eval_tofree);
      }
  
      return ret;
--- 1922,1936 ----
      if (eap != NULL)
        eap->nextcmd = check_nextcmd(p);
  
!     if (evalarg != NULL && eap != NULL && evalarg->eval_tofree != NULL)
      {
!       // We may need to keep the original command line, e.g. for
!       // ":let" it has the variable names.  But we may also need the
!       // new one, "nextcmd" points into it.  Keep both.
!       vim_free(eap->cmdline_tofree);
!       eap->cmdline_tofree = *eap->cmdlinep;
!       *eap->cmdlinep = evalarg->eval_tofree;
!       evalarg->eval_tofree = NULL;
      }
  
      return ret;
***************
*** 2797,2803 ****
       * Lambda: {arg, arg -> expr}
       * Dictionary: {'key': val, 'key': val}
       */
!     case '{': ret = get_lambda_tv(arg, rettv, evaluate);
                if (ret == NOTDONE)
                    ret = eval_dict(arg, rettv, evalarg, FALSE);
                break;
--- 2855,2861 ----
       * Lambda: {arg, arg -> expr}
       * Dictionary: {'key': val, 'key': val}
       */
!     case '{': ret = get_lambda_tv(arg, rettv, evalarg);
                if (ret == NOTDONE)
                    ret = eval_dict(arg, rettv, evalarg, FALSE);
                break;
***************
*** 2884,2890 ****
      // Handle following '[', '(' and '.' for expr[expr], expr.name,
      // expr(expr), expr->name(expr)
      if (ret == OK)
!       ret = handle_subscript(arg, rettv, flags, TRUE);
  
      /*
       * Apply logical NOT and unary '-', from right to left, ignore '+'.
--- 2942,2948 ----
      // Handle following '[', '(' and '.' for expr[expr], expr.name,
      // expr(expr), expr->name(expr)
      if (ret == OK)
!       ret = handle_subscript(arg, rettv, evalarg, TRUE);
  
      /*
       * Apply logical NOT and unary '-', from right to left, ignore '+'.
***************
*** 3031,3039 ****
  eval_lambda(
      char_u    **arg,
      typval_T  *rettv,
!     int               evaluate,
      int               verbose)        // give error messages
  {
      typval_T  base = *rettv;
      int               ret;
  
--- 3089,3099 ----
  eval_lambda(
      char_u    **arg,
      typval_T  *rettv,
!     evalarg_T *evalarg,
      int               verbose)        // give error messages
  {
+     int               evaluate = evalarg != NULL
+                                     && (evalarg->eval_flags & EVAL_EVALUATE);
      typval_T  base = *rettv;
      int               ret;
  
***************
*** 3041,3047 ****
      *arg += 2;
      rettv->v_type = VAR_UNKNOWN;
  
!     ret = get_lambda_tv(arg, rettv, evaluate);
      if (ret != OK)
        return FAIL;
      else if (**arg != '(')
--- 3101,3107 ----
      *arg += 2;
      rettv->v_type = VAR_UNKNOWN;
  
!     ret = get_lambda_tv(arg, rettv, evalarg);
      if (ret != OK)
        return FAIL;
      else if (**arg != '(')
***************
*** 3136,3145 ****
  eval_index(
      char_u    **arg,
      typval_T  *rettv,
!     int               flags,
      int               verbose)        // give error messages
  {
!     int               evaluate = flags & EVAL_EVALUATE;
      int               empty1 = FALSE, empty2 = FALSE;
      typval_T  var1, var2;
      long      i;
--- 3196,3206 ----
  eval_index(
      char_u    **arg,
      typval_T  *rettv,
!     evalarg_T *evalarg,
      int               verbose)        // give error messages
  {
!     int               evaluate = evalarg != NULL
!                                     && (evalarg->eval_flags & EVAL_EVALUATE);
      int               empty1 = FALSE, empty2 = FALSE;
      typval_T  var1, var2;
      long      i;
***************
*** 3200,3210 ****
      }
      else
      {
-       evalarg_T       evalarg;
- 
-       CLEAR_FIELD(evalarg);
-       evalarg.eval_flags = flags;
- 
        /*
         * something[idx]
         *
--- 3261,3266 ----
***************
*** 3213,3219 ****
        *arg = skipwhite(*arg + 1);
        if (**arg == ':')
            empty1 = TRUE;
!       else if (eval1(arg, &var1, &evalarg) == FAIL)   // recursive!
            return FAIL;
        else if (evaluate && tv_get_string_chk(&var1) == NULL)
        {
--- 3269,3275 ----
        *arg = skipwhite(*arg + 1);
        if (**arg == ':')
            empty1 = TRUE;
!       else if (eval1(arg, &var1, evalarg) == FAIL)    // recursive!
            return FAIL;
        else if (evaluate && tv_get_string_chk(&var1) == NULL)
        {
***************
*** 3231,3237 ****
            *arg = skipwhite(*arg + 1);
            if (**arg == ']')
                empty2 = TRUE;
!           else if (eval1(arg, &var2, &evalarg) == FAIL)       // recursive!
            {
                if (!empty1)
                    clear_tv(&var1);
--- 3287,3293 ----
            *arg = skipwhite(*arg + 1);
            if (**arg == ']')
                empty2 = TRUE;
!           else if (eval1(arg, &var2, evalarg) == FAIL)        // recursive!
            {
                if (!empty1)
                    clear_tv(&var1);
***************
*** 4884,4893 ****
  handle_subscript(
      char_u    **arg,
      typval_T  *rettv,
!     int               flags,          // do more than finding the end
      int               verbose)        // give error messages
  {
!     int               evaluate = flags & EVAL_EVALUATE;
      int               ret = OK;
      dict_T    *selfdict = NULL;
  
--- 4940,4950 ----
  handle_subscript(
      char_u    **arg,
      typval_T  *rettv,
!     evalarg_T *evalarg,
      int               verbose)        // give error messages
  {
!     int               evaluate = evalarg != NULL
!                                     && (evalarg->eval_flags & EVAL_EVALUATE);
      int               ret = OK;
      dict_T    *selfdict = NULL;
  
***************
*** 4926,4932 ****
            {
                if ((*arg)[2] == '{')
                    // expr->{lambda}()
!                   ret = eval_lambda(arg, rettv, evaluate, verbose);
                else
                    // expr->name()
                    ret = eval_method(arg, rettv, evaluate, verbose);
--- 4983,4989 ----
            {
                if ((*arg)[2] == '{')
                    // expr->{lambda}()
!                   ret = eval_lambda(arg, rettv, evalarg, verbose);
                else
                    // expr->name()
                    ret = eval_method(arg, rettv, evaluate, verbose);
***************
*** 4943,4949 ****
            }
            else
                selfdict = NULL;
!           if (eval_index(arg, rettv, flags, verbose) == FAIL)
            {
                clear_tv(rettv);
                ret = FAIL;
--- 5000,5006 ----
            }
            else
                selfdict = NULL;
!           if (eval_index(arg, rettv, evalarg, verbose) == FAIL)
            {
                clear_tv(rettv);
                ret = FAIL;
*** ../vim-8.2.1070/src/proto/eval.pro  2020-06-27 13:11:46.863462713 +0200
--- src/proto/eval.pro  2020-06-27 15:27:38.043790985 +0200
***************
*** 9,14 ****
--- 9,15 ----
  int eval_expr_to_bool(typval_T *expr, int *error);
  char_u *eval_to_string_skip(char_u *arg, exarg_T *eap, int skip);
  int skip_expr(char_u **pp);
+ int skip_expr_concatenate(char_u **start, char_u **end, evalarg_T *evalarg);
  char_u *eval_to_string(char_u *arg, int convert);
  char_u *eval_to_string_safe(char_u *arg, int use_sandbox);
  varnumber_T eval_to_number(char_u *expr);
***************
*** 53,59 ****
  char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, 
int flags);
  int eval_isnamec(int c);
  int eval_isnamec1(int c);
! int handle_subscript(char_u **arg, typval_T *rettv, int flags, int verbose);
  int item_copy(typval_T *from, typval_T *to, int deep, int copyID);
  void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr);
  void ex_echo(exarg_T *eap);
--- 54,60 ----
  char_u *find_name_end(char_u *arg, char_u **expr_start, char_u **expr_end, 
int flags);
  int eval_isnamec(int c);
  int eval_isnamec1(int c);
! int handle_subscript(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int 
verbose);
  int item_copy(typval_T *from, typval_T *to, int deep, int copyID);
  void echo_one(typval_T *rettv, int with_space, int *atstart, int *needclr);
  void ex_echo(exarg_T *eap);
*** ../vim-8.2.1070/src/evalvars.c      2020-06-27 13:11:46.863462713 +0200
--- src/evalvars.c      2020-06-27 17:15:36.878996132 +0200
***************
*** 797,808 ****
--- 797,810 ----
  
            if (eap->skip)
                ++emsg_skip;
+           CLEAR_FIELD(evalarg);
            evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
            evalarg.eval_cookie = eap->getline == getsourceline
                                                          ? eap->cookie : NULL;
            i = eval0(expr, &rettv, eap, &evalarg);
            if (eap->skip)
                --emsg_skip;
+           vim_free(evalarg.eval_tofree);
        }
        if (eap->skip)
        {
***************
*** 1125,1131 ****
                {
                    // handle d.key, l[idx], f(expr)
                    arg_subsc = arg;
!                   if (handle_subscript(&arg, &tv, EVAL_EVALUATE, TRUE)
                                                                       == FAIL)
                        error = TRUE;
                    else
--- 1127,1133 ----
                {
                    // handle d.key, l[idx], f(expr)
                    arg_subsc = arg;
!                   if (handle_subscript(&arg, &tv, &EVALARG_EVALUATE, TRUE)
                                                                       == FAIL)
                        error = TRUE;
                    else
***************
*** 3341,3347 ****
        if (n)
        {
            // handle d.key, l[idx], f(expr)
!           n = (handle_subscript(&var, &tv, EVAL_EVALUATE, FALSE) == OK);
            if (n)
                clear_tv(&tv);
        }
--- 3343,3349 ----
        if (n)
        {
            // handle d.key, l[idx], f(expr)
!           n = (handle_subscript(&var, &tv, &EVALARG_EVALUATE, FALSE) == OK);
            if (n)
                clear_tv(&tv);
        }
*** ../vim-8.2.1070/src/userfunc.c      2020-06-27 13:11:46.863462713 +0200
--- src/userfunc.c      2020-06-27 17:55:25.163278860 +0200
***************
*** 391,398 ****
   * Return OK or FAIL.  Returns NOTDONE for dict or {expr}.
   */
      int
! get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate)
  {
      garray_T  newargs;
      garray_T  newlines;
      garray_T  *pnewargs;
--- 391,400 ----
   * Return OK or FAIL.  Returns NOTDONE for dict or {expr}.
   */
      int
! get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
  {
+     int               evaluate = evalarg != NULL
+                                     && (evalarg->eval_flags & EVAL_EVALUATE);
      garray_T  newargs;
      garray_T  newlines;
      garray_T  *pnewargs;
***************
*** 404,409 ****
--- 406,413 ----
      char_u    *s, *e;
      int               *old_eval_lavars = eval_lavars_used;
      int               eval_lavars = FALSE;
+     int               getnext;
+     char_u    *tofree = NULL;
  
      ga_init(&newargs);
      ga_init(&newlines);
***************
*** 432,443 ****
  
      // Get the start and the end of the expression.
      *arg = skipwhite(*arg + 1);
      s = *arg;
!     ret = skip_expr(arg);
      if (ret == FAIL)
        goto errret;
      e = *arg;
      *arg = skipwhite(*arg);
      if (**arg != '}')
      {
        semsg(_("E451: Expected }: %s"), *arg);
--- 436,460 ----
  
      // Get the start and the end of the expression.
      *arg = skipwhite(*arg + 1);
+     eval_next_non_blank(*arg, evalarg, &getnext);
+     if (getnext)
+       *arg = eval_next_line(evalarg);
      s = *arg;
!     ret = skip_expr_concatenate(&s, arg, evalarg);
      if (ret == FAIL)
        goto errret;
+     if (evalarg != NULL)
+     {
+       // avoid that the expression gets freed when another line break follows
+       tofree = evalarg->eval_tofree;
+       evalarg->eval_tofree = NULL;
+     }
+ 
      e = *arg;
      *arg = skipwhite(*arg);
+     eval_next_non_blank(*arg, evalarg, &getnext);
+     if (getnext)
+       *arg = eval_next_line(evalarg);
      if (**arg != '}')
      {
        semsg(_("E451: Expected }: %s"), *arg);
***************
*** 447,453 ****
  
      if (evaluate)
      {
!       int         len, flags = 0;
        char_u      *p;
        char_u      *name = get_lambda_name();
  
--- 464,471 ----
  
      if (evaluate)
      {
!       int         len;
!       int         flags = 0;
        char_u      *p;
        char_u      *name = get_lambda_name();
  
***************
*** 464,470 ****
            goto errret;
  
        // Add "return " before the expression.
!       len = 7 + e - s + 1;
        p = alloc(len);
        if (p == NULL)
            goto errret;
--- 482,488 ----
            goto errret;
  
        // Add "return " before the expression.
!       len = 7 + (int)(e - s) + 1;
        p = alloc(len);
        if (p == NULL)
            goto errret;
***************
*** 510,515 ****
--- 528,534 ----
      }
  
      eval_lavars_used = old_eval_lavars;
+     vim_free(tofree);
      return OK;
  
  errret:
***************
*** 517,522 ****
--- 536,542 ----
      ga_clear_strings(&newlines);
      vim_free(fp);
      vim_free(pt);
+     vim_free(tofree);
      eval_lavars_used = old_eval_lavars;
      return FAIL;
  }
***************
*** 3925,3932 ****
            dbg_check_breakpoint(eap);
  
        // Handle a function returning a Funcref, Dictionary or List.
!       if (handle_subscript(&arg, &rettv, eap->skip ? 0 : EVAL_EVALUATE,
!                                                                TRUE) == FAIL)
        {
            failed = TRUE;
            break;
--- 3945,3952 ----
            dbg_check_breakpoint(eap);
  
        // Handle a function returning a Funcref, Dictionary or List.
!       if (handle_subscript(&arg, &rettv,
!                          eap->skip ? NULL : &EVALARG_EVALUATE, TRUE) == FAIL)
        {
            failed = TRUE;
            break;
*** ../vim-8.2.1070/src/proto/userfunc.pro      2020-06-25 19:27:53.036387595 
+0200
--- src/proto/userfunc.pro      2020-06-27 14:42:50.009378168 +0200
***************
*** 3,10 ****
  hashtab_T *func_tbl_get(void);
  int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, 
garray_T *argtypes, int *varargs, garray_T *default_args, int skip, exarg_T 
*eap, char_u **line_to_free);
  char_u *get_lambda_name(void);
! int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate);
! char_u *register_cfunc(cfunc_T cb, cfunc_free_T free_cb, void *state);
  char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int 
no_autoload);
  void emsg_funcname(char *ermsg, char_u *name);
  int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, 
funcexe_T *funcexe);
--- 3,10 ----
  hashtab_T *func_tbl_get(void);
  int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, 
garray_T *argtypes, int *varargs, garray_T *default_args, int skip, exarg_T 
*eap, char_u **line_to_free);
  char_u *get_lambda_name(void);
! char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state);
! int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
  char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int 
no_autoload);
  void emsg_funcname(char *ermsg, char_u *name);
  int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, 
funcexe_T *funcexe);
*** ../vim-8.2.1070/src/popupwin.c      2020-06-15 21:19:04.017590497 +0200
--- src/popupwin.c      2020-06-27 14:41:58.969728917 +0200
***************
*** 384,390 ****
  
      vim_snprintf((char *)cbbuf, sizeof(cbbuf),
                                       "{_ -> popup_close(%d)}", wp->w_id);
!     if (get_lambda_tv(&ptr, &tv, TRUE) == OK)
      {
        wp->w_popup_timer = create_timer(time, 0);
        wp->w_popup_timer->tr_callback = get_callback(&tv);
--- 384,390 ----
  
      vim_snprintf((char *)cbbuf, sizeof(cbbuf),
                                       "{_ -> popup_close(%d)}", wp->w_id);
!     if (get_lambda_tv(&ptr, &tv, &EVALARG_EVALUATE) == OK)
      {
        wp->w_popup_timer = create_timer(time, 0);
        wp->w_popup_timer->tr_callback = get_callback(&tv);
*** ../vim-8.2.1070/src/vim9compile.c   2020-06-27 14:11:50.494644105 +0200
--- src/vim9compile.c   2020-06-27 14:42:42.725427502 +0200
***************
*** 3001,3007 ****
      }
      else if (p == arg && *arg == '{')
      {
!       int         ret = get_lambda_tv(&p, &rettv, FALSE);
  
        // Can be "{x -> ret}()".
        // Can be "{'a': 1}->Func()".
--- 3001,3007 ----
      }
      else if (p == arg && *arg == '{')
      {
!       int         ret = get_lambda_tv(&p, &rettv, NULL);
  
        // Can be "{x -> ret}()".
        // Can be "{'a': 1}->Func()".
***************
*** 3065,3071 ****
      ufunc_T   *ufunc;
  
      // Get the funcref in "rettv".
!     if (get_lambda_tv(arg, &rettv, TRUE) != OK)
        return FAIL;
  
      ufunc = rettv.vval.v_partial->pt_func;
--- 3065,3071 ----
      ufunc_T   *ufunc;
  
      // Get the funcref in "rettv".
!     if (get_lambda_tv(arg, &rettv, &EVALARG_EVALUATE) != OK)
        return FAIL;
  
      ufunc = rettv.vval.v_partial->pt_func;
***************
*** 3095,3101 ****
      int               ret = FAIL;
  
      // Get the funcref in "rettv".
!     if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
        return FAIL;
  
      if (**arg != '(')
--- 3095,3101 ----
      int               ret = FAIL;
  
      // Get the funcref in "rettv".
!     if (get_lambda_tv(arg, &rettv, &EVALARG_EVALUATE) == FAIL)
        return FAIL;
  
      if (**arg != '(')
*** ../vim-8.2.1070/src/ex_eval.c       2020-06-24 20:33:59.565106319 +0200
--- src/ex_eval.c       2020-06-27 15:47:09.489105718 +0200
***************
*** 897,902 ****
--- 897,903 ----
      typval_T  tv;
      evalarg_T evalarg;
  
+     CLEAR_FIELD(evalarg);
      evalarg.eval_flags = eap->skip ? 0 : EVAL_EVALUATE;
      evalarg.eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL;
  
*** ../vim-8.2.1070/src/globals.h       2020-06-26 19:44:02.972305916 +0200
--- src/globals.h       2020-06-27 16:14:49.255935319 +0200
***************
*** 1883,1889 ****
  EXTERN listitem_T range_list_item;
  
  // Passed to an eval() function to enable evaluation.
! EXTERN evalarg_T EVALARG_EVALUATE INIT3(EVAL_EVALUATE, NULL, NULL);
  #endif
  
  #ifdef MSWIN
--- 1883,1893 ----
  EXTERN listitem_T range_list_item;
  
  // Passed to an eval() function to enable evaluation.
! EXTERN evalarg_T EVALARG_EVALUATE
! # ifdef DO_INIT
!       = {EVAL_EVALUATE, NULL, {0, 0, 0, 0, NULL}, NULL}
! # endif
!       ;
  #endif
  
  #ifdef MSWIN
*** ../vim-8.2.1070/src/structs.h       2020-06-25 19:27:53.036387595 +0200
--- src/structs.h       2020-06-27 15:09:17.951377551 +0200
***************
*** 1763,1768 ****
--- 1763,1773 ----
      // copied from exarg_T when "getline" is "getsourceline". Can be NULL.
      void      *eval_cookie;   // argument for getline()
  
+     // Used to collect lines while parsing them, so that they can be
+     // concatenated later.  Used when "eval_ga.ga_itemsize" is not zero.
+     // "eval_ga.ga_data" is a list of pointers to lines.
+     garray_T  eval_ga;
+ 
      // pointer to the line obtained with getsourceline()
      char_u    *eval_tofree;
  } evalarg_T;
*** ../vim-8.2.1070/src/testdir/test_vim9_expr.vim      2020-06-27 
14:11:50.494644105 +0200
--- src/testdir/test_vim9_expr.vim      2020-06-27 16:06:06.482819706 +0200
***************
*** 1017,1022 ****
--- 1017,1034 ----
    assert_equal([1, 3, 5], [1, 2, 3]->map({key, val -> key + val}))
  enddef
  
+ def Test_expr7_lambda_vim9script()
+   let lines =<< trim END
+       vim9script
+       let v = 10->{a ->
+           a
+             + 2
+         }()
+       assert_equal(12, v)
+   END
+   CheckScriptSuccess(lines)
+ enddef
+ 
  def Test_expr7_dict()
    " dictionary
    assert_equal(g:dict_empty, {})
*** ../vim-8.2.1070/src/version.c       2020-06-27 17:04:01.298972727 +0200
--- src/version.c       2020-06-27 18:06:03.032763405 +0200
***************
*** 756,757 ****
--- 756,759 ----
  {   /* Add new patch number below this line */
+ /**/
+     1071,
  /**/

-- 
FROG: How you English say:  I one more time, mac, I unclog my nose towards
      you, sons of a window-dresser,  so, you think you could out-clever us
      French fellows with your silly knees-bent creeping about advancing
      behaviour.  (blows a raspberry) I wave my private parts at your aunties,
      you brightly-coloured, mealy-templed, cranberry-smelling, electric
      donkey-bottom biters.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- b...@moolenaar.net -- 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 vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202006271607.05RG79Gx099969%40masaka.moolenaar.net.

Raspunde prin e-mail lui