changeset 19528:3b026343f398 v8.2.0321

patch 8.2.0321: Vim9: ":execute" does not work yet Commit: https://github.com/vim/vim/commit/ad39c094d261109a695aba2c4f19fe336736cc55 Author: Bram Moolenaar <Bram@vim.org> 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.
author Bram Moolenaar <Bram@vim.org>
date Wed, 26 Feb 2020 18:30:04 +0100
parents b4e703999a84
children 6f350fb85612
files src/testdir/test_vim9_disassemble.vim src/testdir/test_vim9_script.vim src/version.c src/vim9.h src/vim9compile.c src/vim9execute.c
diffstat 6 files changed, 157 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
--- 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,
--- 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
--- 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:
--- 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,