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.
diff --git a/src/ex_cmdidxs.h b/src/ex_cmdidxs.h
index 70fb71a..0d148d7 100644
--- a/src/ex_cmdidxs.h
+++ b/src/ex_cmdidxs.h
@@ -17,20 +17,20 @@
   /* 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 @@
   /* 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 @@
   /* 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;
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index aa41ab3..819cf73 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -830,6 +830,9 @@
 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),
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index db7bb93..0d87a89 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -2925,6 +2925,17 @@
 			    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;
diff --git a/src/structs.h b/src/structs.h
index 6c8ef48..8da7c7b 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -645,6 +645,7 @@
 #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
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index ad942a8..a0175cd 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -1500,33 +1500,33 @@
   # 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
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index 8cfb160..230de20 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -2165,6 +2165,14 @@
   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)
diff --git a/src/version.c b/src/version.c
index c5c3fee..4c266ef 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2805,
+/**/
     2804,
 /**/
     2803,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index c74bb6e..c65f1c3 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -9052,6 +9052,10 @@
 	    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)
diff --git a/src/vim9script.c b/src/vim9script.c
index 583a8d4..ddbae78 100644
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -27,8 +27,9 @@
 {
     // "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)