To: vim_dev@googlegroups.com Subject: Patch 8.2.1637 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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('\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 -- Bram@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 ///