]> granicus.if.org Git - vim/commitdiff
patch 8.2.0321: Vim9: ":execute" does not work yet v8.2.0321
authorBram Moolenaar <Bram@vim.org>
Wed, 26 Feb 2020 17:23:43 +0000 (18:23 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 26 Feb 2020 17:23:43 +0000 (18:23 +0100)
Problem:    Vim9: ":execute" does not work yet.
Solution:   Add ISN_EXECUTE. (closes #5699) Also make :echo work with more
            than one argument.

src/testdir/test_vim9_disassemble.vim
src/testdir/test_vim9_script.vim
src/version.c
src/vim9.h
src/vim9compile.c
src/vim9execute.c

index cf3dd8c45078b2dd840cb94ef0d85bc639a508e9..375869717170abd8c028e9377801e35f6a28abba 100644 (file)
@@ -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
index 938dc634094ed95a08d771b4e16f199f678009d5..3f0773b173afb4a7853c735eda11159f883ba5ca 100644 (file)
@@ -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
index 46540e9eb943cc7674c755c37ea0a53b69bd20c9..beceb6da8014975cf33c0342e3a5b22762a070dc 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    321,
 /**/
     320,
 /**/
index a97796505fa196b573bb0e95eb0e9f5dc83069b2..77bf626d6f583f1c158fa43731ca21ff2e7679d8 100644 (file)
@@ -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
index d62df6ed486c2c25a6230a57d15911d9eb2abf9e..32d6349e517c9b780dff9192799bbce5ca462ded 100644 (file)
@@ -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:
index 3bbf94ff676415fb402c302af45085f7dcbd6550..4f2265475453ca0f6abe8405a09b646b0cf795cf 100644 (file)
@@ -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,