To: vim_dev@googlegroups.com Subject: Patch 8.2.0321 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0321 Problem: Vim9: ":execute" does not work yet. Solution: Add ISN_EXECUTE. (closes #5699) Also make :echo work with more than one argument. Files: src/vim9.h, src/vim9compile.c, src/vim9execute.c, src/testdir/test_vim9_disassemble.vim, src/testdir/test_vim9_script.vim *** ../vim-8.2.0320/src/vim9.h 2020-02-06 21:27:05.158175180 +0100 --- src/vim9.h 2020-02-26 17:36:10.318495603 +0100 *************** *** 13,19 **** typedef enum { ISN_EXEC, // execute Ex command line isn_arg.string ! ISN_ECHO, // echo isn_arg.number items on top of stack // get and set variables ISN_LOAD, // push local variable isn_arg.number --- 13,20 ---- typedef enum { ISN_EXEC, // execute Ex command line isn_arg.string ! ISN_ECHO, // echo isn_arg.echo.echo_count items on top of stack ! ISN_EXECUTE, // execute Ex commands isn_arg.number items on top of stack // get and set variables ISN_LOAD, // push local variable isn_arg.number *** ../vim-8.2.0320/src/vim9compile.c 2020-02-25 22:58:25.607851771 +0100 --- src/vim9compile.c 2020-02-26 18:04:00.856556077 +0100 *************** *** 1116,1121 **** --- 1116,1136 ---- return OK; } + /* + * Generate an ISN_EXECUTE instruction. + */ + static int + generate_EXECUTE(cctx_T *cctx, int count) + { + isn_T *isn; + + if ((isn = generate_instr_drop(cctx, ISN_EXECUTE, count)) == NULL) + return FAIL; + isn->isn_arg.number = count; + + return OK; + } + static int generate_EXEC(cctx_T *cctx, char_u *line) { *************** *** 4671,4684 **** char_u *p = arg; int count = 0; ! // for () { if (compile_expr1(&p, cctx) == FAIL) return NULL; ++count; } generate_ECHO(cctx, with_white, count); return p; } --- 4686,4725 ---- char_u *p = arg; int count = 0; ! for (;;) { if (compile_expr1(&p, cctx) == FAIL) return NULL; ++count; + p = skipwhite(p); + if (ends_excmd(*p)) + break; } generate_ECHO(cctx, with_white, count); + return p; + } + + /* + * compile "execute expr" + */ + static char_u * + compile_execute(char_u *arg, cctx_T *cctx) + { + char_u *p = arg; + int count = 0; + + for (;;) + { + if (compile_expr1(&p, cctx) == FAIL) + return NULL; + ++count; + p = skipwhite(p); + if (ends_excmd(*p)) + break; + } + + generate_EXECUTE(cctx, count); return p; } *************** *** 5017,5028 **** case CMD_echon: line = compile_echo(p, FALSE, &cctx); break; default: // Not recognized, execute with do_cmdline_cmd(). // TODO: // CMD_echomsg - // CMD_execute // etc. generate_EXEC(&cctx, line); line = (char_u *)""; --- 5058,5071 ---- case CMD_echon: line = compile_echo(p, FALSE, &cctx); break; + case CMD_execute: + line = compile_execute(p, &cctx); + break; default: // Not recognized, execute with do_cmdline_cmd(). // TODO: // CMD_echomsg // etc. generate_EXEC(&cctx, line); line = (char_u *)""; *************** *** 5150,5155 **** --- 5193,5199 ---- case ISN_DCALL: case ISN_DROP: case ISN_ECHO: + case ISN_EXECUTE: case ISN_ENDTRY: case ISN_FOR: case ISN_FUNCREF: *** ../vim-8.2.0320/src/vim9execute.c 2020-02-20 22:18:01.856405473 +0100 --- src/vim9execute.c 2020-02-26 18:00:26.425318481 +0100 *************** *** 533,538 **** --- 533,580 ---- } break; + // execute :execute {string} ... + case ISN_EXECUTE: + { + int count = iptr->isn_arg.number; + garray_T ga; + char_u buf[NUMBUFLEN]; + char_u *p; + int len; + int failed = FALSE; + + ga_init2(&ga, 1, 80); + for (idx = 0; idx < count; ++idx) + { + tv = STACK_TV_BOT(idx - count); + if (tv->v_type == VAR_CHANNEL || tv->v_type == VAR_JOB) + { + emsg(_(e_inval_string)); + break; + } + else + p = tv_get_string_buf(tv, buf); + + len = (int)STRLEN(p); + if (ga_grow(&ga, len + 2) == FAIL) + failed = TRUE; + else + { + if (ga.ga_len > 0) + ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; + STRCPY((char_u *)(ga.ga_data) + ga.ga_len, p); + ga.ga_len += len; + } + clear_tv(tv); + } + ectx.ec_stack.ga_len -= count; + + if (!failed && ga.ga_data != NULL) + do_cmdline_cmd((char_u *)ga.ga_data); + ga_clear(&ga); + } + break; + // load local variable or argument case ISN_LOAD: if (ga_grow(&ectx.ec_stack, 1) == FAIL) *************** *** 1666,1671 **** --- 1708,1716 ---- echo->echo_count); } break; + case ISN_EXECUTE: + smsg("%4d EXECUTE %d", current, iptr->isn_arg.number); + break; case ISN_LOAD: if (iptr->isn_arg.number < 0) smsg("%4d LOAD arg[%lld]", current, *** ../vim-8.2.0320/src/testdir/test_vim9_disassemble.vim 2020-02-22 19:07:24.393786830 +0100 --- src/testdir/test_vim9_disassemble.vim 2020-02-26 17:32:45.855222594 +0100 *************** *** 690,693 **** --- 690,726 ---- " delete('Xdisassemble') enddef + def s:Execute() + execute 'help vim9.txt' + let cmd = 'help vim9.txt' + execute cmd + let tag = 'vim9.txt' + execute 'help ' .. tag + enddef + + def Test_disassemble_execute() + let res = execute('disass s:Execute') + assert_match('\\d*_Execute.*' + \ .. "execute 'help vim9.txt'.*" + \ .. '\d PUSHS "help vim9.txt".*' + \ .. '\d EXECUTE 1.*' + \ .. "let cmd = 'help vim9.txt'.*" + \ .. '\d PUSHS "help vim9.txt".*' + \ .. '\d STORE $0.*' + \ .. 'execute cmd.*' + \ .. '\d LOAD $0.*' + \ .. '\d EXECUTE 1.*' + \ .. "let tag = 'vim9.txt'.*" + \ .. '\d PUSHS "vim9.txt".*' + \ .. '\d STORE $1.*' + \ .. "execute 'help ' .. tag.*" + \ .. '\d PUSHS "help ".*' + \ .. '\d LOAD $1.*' + \ .. '\d CONCAT.*' + \ .. '\d EXECUTE 1.*' + \ .. '\d PUSHNR 0.*' + \ .. '\d RETURN' + \, res) + enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker *** ../vim-8.2.0320/src/testdir/test_vim9_script.vim 2020-02-25 22:58:25.607851771 +0100 --- src/testdir/test_vim9_script.vim 2020-02-26 18:10:39.768258187 +0100 *************** *** 1,6 **** --- 1,7 ---- " Test various aspects of the Vim9 script language. source check.vim + source view_util.vim " Check that "lines" inside ":def" results in an "error" message. func CheckDefFailure(lines, error) *************** *** 692,696 **** --- 693,725 ---- delete('Xvim9lines') enddef + def Test_execute_cmd() + new + setline(1, 'default') + execute 'call setline(1, "execute-string")' + assert_equal('execute-string', getline(1)) + let cmd1 = 'call setline(1,' + let cmd2 = '"execute-var")' + execute cmd1 cmd2 + assert_equal('execute-var', getline(1)) + execute cmd1 cmd2 '|call setline(1, "execute-var-string")' + assert_equal('execute-var-string', getline(1)) + let cmd_first = 'call ' + let cmd_last = 'setline(1, "execute-var-var")' + execute cmd_first .. cmd_last + assert_equal('execute-var-var', getline(1)) + bwipe! + enddef + + def Test_echo_cmd() + echo 'something' + assert_match('^something$', Screenline(&lines)) + + let str1 = 'some' + let str2 = 'more' + echo str1 str2 + assert_match('^some more$', Screenline(&lines)) + enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker *** ../vim-8.2.0320/src/version.c 2020-02-26 16:15:31.076386941 +0100 --- src/version.c 2020-02-26 17:33:59.350961277 +0100 *************** *** 740,741 **** --- 740,743 ---- { /* Add new patch number below this line */ + /**/ + 321, /**/ -- hundred-and-one symptoms of being an internet addict: 124. You begin conversations with, "Who is your internet service provider?" /// 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 ///