# HG changeset patch # User Bram Moolenaar # Date 1582738204 -3600 # Node ID 3b026343f39872ecebb958fe5b82e819d16fc613 # Parent b4e703999a84616bb2332dad4e7745494d04d570 patch 8.2.0321: Vim9: ":execute" does not work yet Commit: https://github.com/vim/vim/commit/ad39c094d261109a695aba2c4f19fe336736cc55 Author: Bram Moolenaar Date: Wed Feb 26 18:23:43 2020 +0100 patch 8.2.0321: Vim9: ":execute" does not work yet Problem: Vim9: ":execute" does not work yet. Solution: Add ISN_EXECUTE. (closes https://github.com/vim/vim/issues/5699) Also make :echo work with more than one argument. diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -690,4 +690,37 @@ def Test_disassemble_compare() " 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 diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -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,5 +693,33 @@ def Test_substitute_cmd() 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 diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -739,6 +739,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 321, +/**/ 320, /**/ 319, diff --git a/src/vim9.h b/src/vim9.h --- a/src/vim9.h +++ b/src/vim9.h @@ -13,7 +13,8 @@ typedef enum { ISN_EXEC, // execute Ex command line isn_arg.string - ISN_ECHO, // echo isn_arg.number items on top of stack + 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 diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1116,6 +1116,21 @@ generate_ECHO(cctx_T *cctx, int with_whi 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,14 +4686,40 @@ compile_echo(char_u *arg, int with_white char_u *p = arg; int count = 0; - // for () + 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,12 +5058,14 @@ compile_def_function(ufunc_T *ufunc, int 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 - // CMD_execute // etc. generate_EXEC(&cctx, line); line = (char_u *)""; @@ -5150,6 +5193,7 @@ delete_instr(isn_T *isn) case ISN_DCALL: case ISN_DROP: case ISN_ECHO: + case ISN_EXECUTE: case ISN_ENDTRY: case ISN_FOR: case ISN_FUNCREF: diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -533,6 +533,48 @@ call_def_function( } 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,6 +1708,9 @@ ex_disassemble(exarg_T *eap) 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,