changeset 24531:3bfec39ce31c v8.2.2805

patch 8.2.2805: Vim9: cannot use legacy syntax in Vim9 script Commit: https://github.com/vim/vim/commit/96cf4ba8fb96e5778192d2dab7458b9a7da0a49d Author: Bram Moolenaar <Bram@vim.org> Date: Sat Apr 24 14:15:41 2021 +0200 patch 8.2.2805: Vim9: cannot use legacy syntax in Vim9 script Problem: Vim9: cannot use legacy syntax in Vim9 script. Solution: Add the :legacy command.
author Bram Moolenaar <Bram@vim.org>
date Sat, 24 Apr 2021 14:30:04 +0200
parents 51e01f7c2069
children 7660cdae6683
files runtime/doc/index.txt runtime/doc/vim9.txt src/ex_cmdidxs.h src/ex_cmds.h src/ex_docmd.c src/structs.h src/testdir/test_vim9_assign.vim src/testdir/test_vim9_func.vim src/version.c src/vim9compile.c src/vim9script.c
diffstat 11 files changed, 64 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1396,6 +1396,7 @@ tag		command		action ~
 |:lfdo|		:lfd[o]		execute command in each file in location list
 |:left|		:le[ft]		left align lines
 |:leftabove|	:lefta[bove]	make split window appear left or above
+|:legacy|	:leg[acy]	make following command use legacy script syntax
 |:let|		:let		assign a value to a variable or option
 |:lexpr|	:lex[pr]	read locations from expr and jump to first
 |:lfile|	:lf[ile]	read file with locations and jump to first
--- a/runtime/doc/vim9.txt
+++ b/runtime/doc/vim9.txt
@@ -61,12 +61,17 @@ Vim9 script and legacy Vim script can be
 rewrite old scripts, they keep working as before.  You may want to use a few
 `:def` functions for code that needs to be fast.
 
-						*:vim9* *:vim9cmd*
-:vim9[cmd] {cmd}
+:vim9[cmd] {cmd}				*:vim9* *:vim9cmd*
 		Execute {cmd} using Vim9 script syntax and semantics.
 		Useful when typing a command and in a legacy script or
 		function.
 
+:leg[acy] {cmd}					*:leg* *:legacy*
+		Execute {cmd} using legacy script syntax and semantics.  Only
+		useful in a Vim9 script or a :def function.
+		Note that {cmd} cannot use local variables, since it is parsed
+		with legacy expression syntax.
+
 ==============================================================================
 
 2. Differences from legacy Vim script			*vim9-differences*
--- a/src/ex_cmdidxs.h
+++ b/src/ex_cmdidxs.h
@@ -17,20 +17,20 @@ static const unsigned short cmdidxs1[26]
   /* j */ 209,
   /* k */ 211,
   /* l */ 216,
-  /* m */ 278,
-  /* n */ 296,
-  /* o */ 316,
-  /* p */ 328,
-  /* q */ 367,
-  /* r */ 370,
-  /* s */ 390,
-  /* t */ 459,
-  /* u */ 504,
-  /* v */ 515,
-  /* w */ 536,
-  /* x */ 550,
-  /* y */ 560,
-  /* z */ 561
+  /* m */ 279,
+  /* n */ 297,
+  /* o */ 317,
+  /* p */ 329,
+  /* q */ 368,
+  /* r */ 371,
+  /* s */ 391,
+  /* t */ 460,
+  /* u */ 505,
+  /* v */ 516,
+  /* w */ 537,
+  /* x */ 551,
+  /* y */ 561,
+  /* z */ 562
 };
 
 /*
@@ -52,7 +52,7 @@ static const unsigned char cmdidxs2[26][
   /* i */ {  1,  0,  0,  0,  0,  3,  0,  0,  0,  4,  0,  5,  6,  0,  0,  0,  0,  0, 14,  0, 16,  0,  0,  0,  0,  0 },
   /* j */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0 },
   /* k */ {  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 },
-  /* l */ {  3, 11, 15, 19, 20, 24, 27, 32,  0,  0,  0, 34, 37, 40, 44, 50,  0, 52, 61, 53, 54, 58, 60,  0,  0,  0 },
+  /* l */ {  3, 11, 15, 19, 20, 25, 28, 33,  0,  0,  0, 35, 38, 41, 45, 51,  0, 53, 62, 54, 55, 59, 61,  0,  0,  0 },
   /* m */ {  1,  0,  0,  0,  7,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 16 },
   /* n */ {  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  5,  8, 10,  0,  0,  0,  0,  0, 17,  0,  0,  0,  0,  0 },
   /* o */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  5,  0,  0,  0,  0,  0,  0,  9,  0, 11,  0,  0,  0 },
@@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][
   /* z */ {  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 }
 };
 
-static const int command_count = 576;
+static const int command_count = 577;
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -830,6 +830,9 @@ EXCMD(CMD_let,		"let",		ex_let,
 EXCMD(CMD_lexpr,	"lexpr",	ex_cexpr,
 	EX_NEEDARG|EX_WORD1|EX_NOTRLCOM|EX_BANG,
 	ADDR_NONE),
+EXCMD(CMD_legacy,	"legacy",	ex_wrongmodifier,
+	EX_NEEDARG|EX_EXTRA|EX_NOTRLCOM|EX_CMDWIN|EX_LOCK_OK,
+	ADDR_NONE),
 EXCMD(CMD_lfile,	"lfile",	ex_cfile,
 	EX_TRLBAR|EX_FILE1|EX_BANG,
 	ADDR_NONE),
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -2925,6 +2925,17 @@ parse_command_modifiers(
 			    cmod->cmod_flags |= CMOD_LOCKMARKS;
 			    continue;
 			}
+			if (checkforcmd_noparen(&eap->cmd, "legacy", 3))
+			{
+			    if (ends_excmd2(p, eap->cmd))
+			    {
+				*errormsg =
+				      _(e_vim9cmd_must_be_followed_by_command);
+				return FAIL;
+			    }
+			    cmod->cmod_flags |= CMOD_LEGACY;
+			    continue;
+			}
 
 			if (!checkforcmd_noparen(&eap->cmd, "leftabove", 5))
 			    break;
--- a/src/structs.h
+++ b/src/structs.h
@@ -645,6 +645,7 @@ typedef struct
 #define CMOD_KEEPPATTERNS   0x1000	// ":keeppatterns"
 #define CMOD_NOSWAPFILE	    0x2000	// ":noswapfile"
 #define CMOD_VIM9CMD	    0x4000	// ":vim9cmd"
+#define CMOD_LEGACY	    0x8000	// ":legacy"
 
     int		cmod_split;		// flags for win_split()
     int		cmod_tab;		// > 0 when ":tab" was used
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -1500,33 +1500,33 @@ def Test_script_local_in_legacy()
   # OK to define script-local later when prefixed with s:
   var lines =<< trim END
     def SetLater()
-      s:legacy = 'two'
+      s:legvar = 'two'
     enddef
     defcompile
-    let s:legacy = 'one'
+    let s:legvar = 'one'
     call SetLater()
-    call assert_equal('two', s:legacy)
+    call assert_equal('two', s:legvar)
   END
   CheckScriptSuccess(lines)
 
   # OK to leave out s: prefix when script-local already defined
   lines =<< trim END
-    let s:legacy = 'one'
+    let s:legvar = 'one'
     def SetNoPrefix()
-      legacy = 'two'
+      legvar = 'two'
     enddef
     call SetNoPrefix()
-    call assert_equal('two', s:legacy)
+    call assert_equal('two', s:legvar)
   END
   CheckScriptSuccess(lines)
 
   # Not OK to leave out s: prefix when script-local defined later
   lines =<< trim END
     def SetLaterNoPrefix()
-      legacy = 'two'
+      legvar = 'two'
     enddef
     defcompile
-    let s:legacy = 'one'
+    let s:legvar = 'one'
   END
   CheckScriptFailure(lines, 'E476:', 1)
 enddef
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -2165,6 +2165,14 @@ def Test_list_lambda()
   assert_match('def <lambda>\d\+(_: any): number\n1  return 0\n   enddef', body)
 enddef
 
+def Test_legacy_lambda()
+  legacy echo {x -> 'hello ' .. x}('foo')
+  var lines =<< trim END
+      echo {x -> 'hello ' .. x}('foo')
+  END
+  CheckDefAndScriptFailure(lines, 'E720:')
+enddef
+
 def DoFilterThis(a: string): list<string>
   # closure nested inside another closure using argument
   var Filter = (l) => filter(l, (_, v) => stridx(v, a) == 0)
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2805,
+/**/
     2804,
 /**/
     2803,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -9052,6 +9052,10 @@ compile_def_function(
 	    goto erret;
 	}
 
+	// When using ":legacy cmd" always use compile_exec().
+	if (local_cmdmod.cmod_flags & CMOD_LEGACY)
+	    ea.cmdidx = CMD_legacy;
+
 	if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
 	{
 	    if (cctx.ctx_skip == SKIP_YES)
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -27,8 +27,9 @@ in_vim9script(void)
 {
     // "sc_version" is also set when compiling a ":def" function in legacy
     // script.
-    return current_sctx.sc_version == SCRIPT_VERSION_VIM9
-		|| (cmdmod.cmod_flags & CMOD_VIM9CMD);
+    return (current_sctx.sc_version == SCRIPT_VERSION_VIM9
+					 || (cmdmod.cmod_flags & CMOD_VIM9CMD))
+		&& !(cmdmod.cmod_flags & CMOD_LEGACY);
 }
 
 #if defined(FEAT_EVAL) || defined(PROTO)