Patch 8.2.1637
Problem:    Vim9: :put ={expr} does not work inside :def function.
Solution:   Add ISN_PUT. (closes #6397)
Files:      src/vim9.h, src/vim9compile.c, src/vim9execute.c, src/register.c,
            src/proto/register.pro, src/edit.c, src/ex_docmd.c, src/mouse.c,
            src/normal.c, src/testdir/test_vim9_cmd.vim,
            src/testdir/test_vim9_disassemble.vim


*** ../vim-8.2.1636/src/vim9.h  2020-08-16 17:33:29.517887810 +0200
--- src/vim9.h  2020-09-07 22:41:01.141689898 +0200
***************
*** 135,140 ****
--- 135,142 ----
      ISN_CHECKTYPE,  // check value type is isn_arg.type.tc_type
      ISN_CHECKLEN,   // check list length is isn_arg.checklen.cl_min_len
  
+     ISN_PUT,      // ":put", uses isn_arg.put
+ 
      ISN_SHUFFLE,    // move item on stack up or down
      ISN_DROP      // pop stack and discard value
  } isntype_T;
***************
*** 261,266 ****
--- 263,274 ----
      int               shfl_up;        // places to move upwards
  } shuffle_T;
  
+ // arguments to ISN_PUT
+ typedef struct {
+     int               put_regname;    // register, can be NUL
+     linenr_T  put_lnum;       // line number to put below
+ } put_T;
+ 
  /*
   * Instruction
   */
***************
*** 296,301 ****
--- 304,310 ----
        newfunc_T           newfunc;
        checklen_T          checklen;
        shuffle_T           shuffle;
+       put_T               put;
      } isn_arg;
  };
  
*** ../vim-8.2.1636/src/vim9compile.c   2020-09-01 19:56:10.928571016 +0200
--- src/vim9compile.c   2020-09-08 22:34:11.887703034 +0200
***************
*** 1567,1572 ****
--- 1567,1588 ----
      return OK;
  }
  
+ /*
+  * Generate an ISN_PUT instruction.
+  */
+     static int
+ generate_PUT(cctx_T *cctx, int regname, linenr_T lnum)
+ {
+     isn_T     *isn;
+ 
+     RETURN_OK_IF_SKIP(cctx);
+     if ((isn = generate_instr(cctx, ISN_PUT)) == NULL)
+       return FAIL;
+     isn->isn_arg.put.put_regname = regname;
+     isn->isn_arg.put.put_lnum = lnum;
+     return OK;
+ }
+ 
      static int
  generate_EXEC(cctx_T *cctx, char_u *line)
  {
***************
*** 6272,6277 ****
--- 6288,6337 ----
  }
  
  /*
+  * :put r
+  * :put ={expr}
+  */
+     static char_u *
+ compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
+ {
+     char_u    *line = arg;
+     linenr_T  lnum;
+     char      *errormsg;
+     int               above = FALSE;
+ 
+     if (*arg == '!')
+     {
+       above = TRUE;
+       line = skipwhite(arg + 1);
+     }
+     eap->regname = *line;
+ 
+     if (eap->regname == '=')
+     {
+       char_u *p = line + 1;
+ 
+       if (compile_expr0(&p, cctx) == FAIL)
+           return NULL;
+       line = p;
+     }
+     else if (eap->regname != NUL)
+       ++line;
+ 
+     // TODO: if the range is something like "$" need to evaluate at runtime
+     if (parse_cmd_address(eap, &errormsg, FALSE) == FAIL)
+       return NULL;
+     if (eap->addr_count == 0)
+       lnum = -1;
+     else
+       lnum = eap->line2;
+     if (above)
+       --lnum;
+ 
+     generate_PUT(cctx, eap->regname, lnum);
+     return line;
+ }
+ 
+ /*
   * A command that is not compiled, execute with legacy code.
   */
      static char_u *
***************
*** 6870,6875 ****
--- 6930,6940 ----
                    line = compile_mult_expr(p, ea.cmdidx, &cctx);
                    break;
  
+           case CMD_put:
+                   ea.cmd = cmd;
+                   line = compile_put(p, &ea, &cctx);
+                   break;
+ 
            // TODO: any other commands with an expression argument?
  
            case CMD_append:
***************
*** 7192,7197 ****
--- 7257,7263 ----
        case ISN_PUSHF:
        case ISN_PUSHNR:
        case ISN_PUSHSPEC:
+       case ISN_PUT:
        case ISN_RETURN:
        case ISN_SHUFFLE:
        case ISN_SLICE:
*** ../vim-8.2.1636/src/vim9execute.c   2020-08-30 23:24:17.219401371 +0200
--- src/vim9execute.c   2020-09-08 22:36:32.211254084 +0200
***************
*** 2581,2586 ****
--- 2581,2616 ----
                }
                break;
  
+           case ISN_PUT:
+               {
+                   int         regname = iptr->isn_arg.put.put_regname;
+                   linenr_T    lnum = iptr->isn_arg.put.put_lnum;
+                   char_u      *expr = NULL;
+                   int         dir = FORWARD;
+ 
+                   if (regname == '=')
+                   {
+                       tv = STACK_TV_BOT(-1);
+                       if (tv->v_type == VAR_STRING)
+                           expr = tv->vval.v_string;
+                       else
+                       {
+                           expr = typval_tostring(tv);  // allocates value
+                           clear_tv(tv);
+                       }
+                       --ectx.ec_stack.ga_len;
+                   }
+                   if (lnum == -2)
+                       // :put! above cursor
+                       dir = BACKWARD;
+                   else if (lnum >= 0)
+                       curwin->w_cursor.lnum = iptr->isn_arg.put.put_lnum;
+                   check_cursor();
+                   do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
+                   vim_free(expr);
+               }
+               break;
+ 
            case ISN_SHUFFLE:
                {
                    typval_T        tmp_tv;
***************
*** 3227,3232 ****
--- 3257,3266 ----
            case ISN_2STRING_ANY: smsg("%4d 2STRING_ANY stack[%lld]", current,
                                         (long long)(iptr->isn_arg.number));
                              break;
+           case ISN_PUT:
+               smsg("%4d PUT %c %ld", current, iptr->isn_arg.put.put_regname,
+                                            (long)iptr->isn_arg.put.put_lnum);
+               break;
  
            case ISN_SHUFFLE: smsg("%4d SHUFFLE %d up %d", current,
                                         iptr->isn_arg.shuffle.shfl_item,
*** ../vim-8.2.1636/src/register.c      2020-08-22 21:08:40.756880896 +0200
--- src/register.c      2020-09-07 23:01:51.011437331 +0200
***************
*** 1487,1492 ****
--- 1487,1493 ----
      void
  do_put(
      int               regname,
+     char_u    *expr_result,   // result for regname "=" when compiled
      int               dir,            // BACKWARD for 'P', FORWARD for 'p'
      long      count,
      int               flags)
***************
*** 1551,1561 ****
  
      // For special registers '%' (file name), '#' (alternate file name) and
      // ':' (last command line), etc. we have to create a fake yank register.
!     if (get_spec_reg(regname, &insert_string, &allocated, TRUE))
!     {
!       if (insert_string == NULL)
!           return;
!     }
  
      // Autocommands may be executed when saving lines for undo.  This might
      // make "y_array" invalid, so we start undo now to avoid that.
--- 1552,1563 ----
  
      // For special registers '%' (file name), '#' (alternate file name) and
      // ':' (last command line), etc. we have to create a fake yank register.
!     // For compiled code "expr_result" holds the expression result.
!     if (regname == '=' && expr_result != NULL)
!       insert_string = expr_result;
!     else if (get_spec_reg(regname, &insert_string, &allocated, TRUE)
!               && insert_string == NULL)
!       return;
  
      // Autocommands may be executed when saving lines for undo.  This might
      // make "y_array" invalid, so we start undo now to avoid that.
*** ../vim-8.2.1636/src/proto/register.pro      2020-06-07 18:16:31.307293302 
+0200
--- src/proto/register.pro      2020-09-07 23:01:54.483433547 +0200
***************
*** 27,33 ****
  void clear_registers(void);
  void free_yank_all(void);
  int op_yank(oparg_T *oap, int deleting, int mess);
! void do_put(int regname, int dir, long count, int flags);
  int get_register_name(int num);
  int get_unname_register(void);
  void ex_display(exarg_T *eap);
--- 27,33 ----
  void clear_registers(void);
  void free_yank_all(void);
  int op_yank(oparg_T *oap, int deleting, int mess);
! void do_put(int regname, char_u *expr_result, int dir, long count, int flags);
  int get_register_name(int num);
  int get_unname_register(void);
  void ex_display(exarg_T *eap);
*** ../vim-8.2.1636/src/edit.c  2020-09-05 15:48:32.469546692 +0200
--- src/edit.c  2020-09-07 22:54:59.227542967 +0200
***************
*** 3399,3405 ****
            AppendCharToRedobuff(literally);
            AppendCharToRedobuff(regname);
  
!           do_put(regname, BACKWARD, 1L,
                 (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
        }
        else if (insert_reg(regname, literally) == FAIL)
--- 3399,3405 ----
            AppendCharToRedobuff(literally);
            AppendCharToRedobuff(regname);
  
!           do_put(regname, NULL, BACKWARD, 1L,
                 (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
        }
        else if (insert_reg(regname, literally) == FAIL)
***************
*** 4776,4782 ****
      static void
  ins_drop(void)
  {
!     do_put('~', BACKWARD, 1L, PUT_CURSEND);
  }
  #endif
  
--- 4776,4782 ----
      static void
  ins_drop(void)
  {
!     do_put('~', NULL, BACKWARD, 1L, PUT_CURSEND);
  }
  #endif
  
*** ../vim-8.2.1636/src/ex_docmd.c      2020-08-23 21:05:59.210438670 +0200
--- src/ex_docmd.c      2020-09-07 22:55:34.319567860 +0200
***************
*** 7321,7327 ****
        eap->forceit = TRUE;
      }
      curwin->w_cursor.lnum = eap->line2;
!     do_put(eap->regname, eap->forceit ? BACKWARD : FORWARD, 1L,
                                                       PUT_LINE|PUT_CURSLINE);
  }
  
--- 7321,7327 ----
        eap->forceit = TRUE;
      }
      curwin->w_cursor.lnum = eap->line2;
!     do_put(eap->regname, NULL, eap->forceit ? BACKWARD : FORWARD, 1L,
                                                       PUT_LINE|PUT_CURSLINE);
  }
  
*** ../vim-8.2.1636/src/mouse.c 2020-08-11 21:58:12.581968226 +0200
--- src/mouse.c 2020-09-07 22:56:33.747592563 +0200
***************
*** 430,436 ****
                    insert_reg(regname, TRUE);
                else
                {
!                   do_put(regname, BACKWARD, 1L, fixindent | PUT_CURSEND);
  
                    // Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r
                    AppendCharToRedobuff(Ctrl_R);
--- 430,437 ----
                    insert_reg(regname, TRUE);
                else
                {
!                   do_put(regname, NULL, BACKWARD, 1L,
!                                                     fixindent | PUT_CURSEND);
  
                    // Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r
                    AppendCharToRedobuff(Ctrl_R);
***************
*** 849,855 ****
        // to this position
        if (restart_edit != 0)
            where_paste_started = curwin->w_cursor;
!       do_put(regname, dir, count, fixindent | PUT_CURSEND);
      }
  
  #if defined(FEAT_QUICKFIX)
--- 850,856 ----
        // to this position
        if (restart_edit != 0)
            where_paste_started = curwin->w_cursor;
!       do_put(regname, NULL, dir, count, fixindent | PUT_CURSEND);
      }
  
  #if defined(FEAT_QUICKFIX)
*** ../vim-8.2.1636/src/normal.c        2020-09-05 14:27:19.466565808 +0200
--- src/normal.c        2020-09-07 22:56:58.583596890 +0200
***************
*** 7427,7433 ****
            // May have been reset in do_put().
            VIsual_active = TRUE;
        }
!       do_put(cap->oap->regname, dir, cap->count1, flags);
  
        // If a register was saved, put it back now.
        if (reg2 != NULL)
--- 7427,7433 ----
            // May have been reset in do_put().
            VIsual_active = TRUE;
        }
!       do_put(cap->oap->regname, NULL, dir, cap->count1, flags);
  
        // If a register was saved, put it back now.
        if (reg2 != NULL)
***************
*** 7500,7506 ****
      static void
  nv_drop(cmdarg_T *cap UNUSED)
  {
!     do_put('~', BACKWARD, 1L, PUT_CURSEND);
  }
  #endif
  
--- 7500,7506 ----
      static void
  nv_drop(cmdarg_T *cap UNUSED)
  {
!     do_put('~', NULL, BACKWARD, 1L, PUT_CURSEND);
  }
  #endif
  
*** ../vim-8.2.1636/src/testdir/test_vim9_cmd.vim       2020-08-23 
21:46:29.075938591 +0200
--- src/testdir/test_vim9_cmd.vim       2020-09-08 22:26:37.385116567 +0200
***************
*** 315,319 ****
--- 315,335 ----
    bwipe!
  enddef
  
+ def Test_put_command()
+   new
+   @p = 'ppp'
+   put p
+   assert_equal('ppp', getline(2))
+ 
+   put ='below'
+   assert_equal('below', getline(3))
+   put! ='above'
+   assert_equal('above', getline(3))
+   assert_equal('below', getline(4))
+ 
+   bwipe!
+ enddef
+ 
+ 
  
  " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
*** ../vim-8.2.1636/src/testdir/test_vim9_disassemble.vim       2020-09-06 
15:58:33.383154915 +0200
--- src/testdir/test_vim9_disassemble.vim       2020-09-08 22:22:57.693762215 
+0200
***************
*** 118,123 ****
--- 118,138 ----
          res)
  enddef
  
+ def s:PutExpr()
+   :3put ="text"
+ enddef
+ 
+ def Test_disassemble_put_expr()
+   let res = execute('disass s:PutExpr')
+   assert_match('<SNR>\d*_PutExpr.*' ..
+         ' :3put ="text"\_s*' ..
+         '\d PUSHS "text"\_s*' ..
+         '\d PUT = 3\_s*' ..
+         '\d PUSHNR 0\_s*' ..
+         '\d RETURN',
+         res)
+ enddef
+ 
  def s:ScriptFuncPush()
    let localbool = true
    let localspec = v:none
*** ../vim-8.2.1636/src/version.c       2020-09-08 22:06:12.829040924 +0200
--- src/version.c       2020-09-08 22:38:20.094906814 +0200
***************
*** 756,757 ****
--- 756,759 ----
  {   /* Add new patch number below this line */
+ /**/
+     1637,
  /**/

-- 
ARTHUR: Go on, Bors, chop its head off.
BORS:   Right.  Silly little bleeder.  One rabbit stew coming up.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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/202009082056.088Kuhrj152219%40masaka.moolenaar.net.

Raspunde prin e-mail lui