summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-02-26 18:23:43 +0100
committerBram Moolenaar <Bram@vim.org>2020-02-26 18:23:43 +0100
commitad39c094d261109a695aba2c4f19fe336736cc55 (patch)
treedec5a6a908cb0bd81b04688583d5de1b8196f878
parentb3f740695a0199d22cd97aee314f06c7ae32d2ea (diff)
patch 8.2.0321: Vim9: ":execute" does not work yetv8.2.0321
Problem: Vim9: ":execute" does not work yet. Solution: Add ISN_EXECUTE. (closes #5699) Also make :echo work with more than one argument.
-rw-r--r--src/testdir/test_vim9_disassemble.vim33
-rw-r--r--src/testdir/test_vim9_script.vim29
-rw-r--r--src/version.c2
-rw-r--r--src/vim9.h3
-rw-r--r--src/vim9compile.c48
-rw-r--r--src/vim9execute.c45
6 files changed, 157 insertions, 3 deletions
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index cf3dd8c450..3758697171 100644
--- 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('\<SNR>\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
index 938dc63409..3f0773b173 100644
--- 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
index 46540e9eb9..beceb6da80 100644
--- 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
index a97796505f..77bf626d6f 100644
--- 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
index d62df6ed48..32d6349e51 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -1116,6 +1116,21 @@ generate_ECHO(cctx_T *cctx, int with_white, int count)
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, cctx_T *cctx)
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 set_return_type)
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
index 3bbf94ff67..4f22654754 100644
--- 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,