summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-05-17 00:01:42 +0200
committerBram Moolenaar <Bram@vim.org>2021-05-17 00:01:42 +0200
commit3b1373b193ce5fbf25e852277a4ecc98688c7bb8 (patch)
tree5d8343ef3e9a3ecac8618b4846fc24fec7d50797
parent1764faa38645a559172e9a31f08447385835de81 (diff)
downloadvim-git-3b1373b193ce5fbf25e852277a4ecc98688c7bb8.tar.gz
patch 8.2.2861: Vim9: "legacy return" is not recognized as a return statementv8.2.2861
Problem: Vim9: "legacy return" is not recognized as a return statement. Solution: Specifically check for a return command. (closes #8213)
-rw-r--r--src/testdir/test_vim9_expr.vim15
-rw-r--r--src/version.c2
-rw-r--r--src/vim9.h1
-rw-r--r--src/vim9compile.c59
-rw-r--r--src/vim9execute.c25
5 files changed, 95 insertions, 7 deletions
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index 718db8b70..fe5de29d0 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -2777,6 +2777,10 @@ def Test_expr7_negate_add()
CheckDefAndScriptFailure(lines, 'E15:')
enddef
+def LegacyReturn(): string
+ legacy return #{key: 'ok'}.key
+enddef
+
def Test_expr7_legacy_script()
var lines =<< trim END
let s:legacy = 'legacy'
@@ -2790,6 +2794,17 @@ def Test_expr7_legacy_script()
call assert_equal('legacy', GetLocalPrefix())
END
CheckScriptSuccess(lines)
+
+ assert_equal('ok', LegacyReturn())
+
+ lines =<< trim END
+ vim9script
+ def GetNumber(): number
+ legacy return range(3)->map('v:val + 1')
+ enddef
+ echo GetNumber()
+ END
+ CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got list<number>')
enddef
def Echo(arg: any): string
diff --git a/src/version.c b/src/version.c
index cd42c0a7e..fca2cd8c4 100644
--- 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 */
/**/
+ 2861,
+/**/
2860,
/**/
2859,
diff --git a/src/vim9.h b/src/vim9.h
index 9f45ea412..b260bdf1f 100644
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -14,6 +14,7 @@
typedef enum {
ISN_EXEC, // execute Ex command line isn_arg.string
ISN_EXECCONCAT, // execute Ex command from isn_arg.number items on stack
+ ISN_LEGACY_EVAL, // evaluate expression isn_arg.string with legacy syntax.
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
ISN_ECHOMSG, // echo Ex commands isn_arg.number items on top of stack
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 9aa93de7b..160c8e428 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2174,6 +2174,25 @@ generate_EXEC(cctx_T *cctx, char_u *line)
}
static int
+generate_LEGACY_EVAL(cctx_T *cctx, char_u *line)
+{
+ isn_T *isn;
+ garray_T *stack = &cctx->ctx_type_stack;
+
+ RETURN_OK_IF_SKIP(cctx);
+ if ((isn = generate_instr(cctx, ISN_LEGACY_EVAL)) == NULL)
+ return FAIL;
+ isn->isn_arg.string = vim_strsave(line);
+
+ if (ga_grow(stack, 1) == FAIL)
+ return FAIL;
+ ((type_T **)stack->ga_data)[stack->ga_len] = &t_any;
+ ++stack->ga_len;
+
+ return OK;
+}
+
+ static int
generate_EXECCONCAT(cctx_T *cctx, int count)
{
isn_T *isn;
@@ -5321,10 +5340,11 @@ compile_expr0(char_u **arg, cctx_T *cctx)
}
/*
- * compile "return [expr]"
+ * Compile "return [expr]".
+ * When "legacy" is TRUE evaluate [expr] with legacy syntax
*/
static char_u *
-compile_return(char_u *arg, int check_return_type, cctx_T *cctx)
+compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
{
char_u *p = arg;
garray_T *stack = &cctx->ctx_type_stack;
@@ -5332,9 +5352,24 @@ compile_return(char_u *arg, int check_return_type, cctx_T *cctx)
if (*p != NUL && *p != '|' && *p != '\n')
{
- // compile return argument into instructions
- if (compile_expr0(&p, cctx) == FAIL)
- return NULL;
+ if (legacy)
+ {
+ int save_flags = cmdmod.cmod_flags;
+
+ generate_LEGACY_EVAL(cctx, p);
+ if (need_type(&t_any, cctx->ctx_ufunc->uf_ret_type, -1,
+ 0, cctx, FALSE, FALSE) == FAIL)
+ return NULL;
+ cmdmod.cmod_flags |= CMOD_LEGACY;
+ (void)skip_expr(&p, NULL);
+ cmdmod.cmod_flags = save_flags;
+ }
+ else
+ {
+ // compile return argument into instructions
+ if (compile_expr0(&p, cctx) == FAIL)
+ return NULL;
+ }
if (cctx->ctx_skip != SKIP_YES)
{
@@ -9193,7 +9228,15 @@ compile_def_function(
// When using ":legacy cmd" always use compile_exec().
if (local_cmdmod.cmod_flags & CMOD_LEGACY)
- ea.cmdidx = CMD_legacy;
+ {
+ char_u *start = ea.cmd;
+
+ // ":legacy return expr" needs to be handled differently.
+ if (checkforcmd(&start, "return", 4))
+ ea.cmdidx = CMD_return;
+ else
+ ea.cmdidx = CMD_legacy;
+ }
if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
{
@@ -9254,7 +9297,8 @@ compile_def_function(
goto erret;
case CMD_return:
- line = compile_return(p, check_return_type, &cctx);
+ line = compile_return(p, check_return_type,
+ local_cmdmod.cmod_flags & CMOD_LEGACY, &cctx);
cctx.ctx_had_return = TRUE;
break;
@@ -9605,6 +9649,7 @@ delete_instr(isn_T *isn)
{
case ISN_DEF:
case ISN_EXEC:
+ case ISN_LEGACY_EVAL:
case ISN_LOADAUTO:
case ISN_LOADB:
case ISN_LOADENV:
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 425cdb9bb..7f56597b3 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1388,6 +1388,27 @@ exec_instructions(ectx_T *ectx)
}
break;
+ // Evaluate an expression with legacy syntax, push it onto the
+ // stack.
+ case ISN_LEGACY_EVAL:
+ {
+ char_u *arg = iptr->isn_arg.string;
+ int res;
+ int save_flags = cmdmod.cmod_flags;
+
+ if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
+ return FAIL;
+ tv = STACK_TV_BOT(0);
+ init_tv(tv);
+ cmdmod.cmod_flags |= CMOD_LEGACY;
+ res = eval0(arg, tv, NULL, &EVALARG_EVALUATE);
+ cmdmod.cmod_flags = save_flags;
+ if (res == FAIL)
+ goto on_error;
+ ++ectx->ec_stack.ga_len;
+ }
+ break;
+
// push typeval VAR_INSTR with instructions to be executed
case ISN_INSTR:
{
@@ -4464,6 +4485,10 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
case ISN_EXEC:
smsg("%s%4d EXEC %s", pfx, current, iptr->isn_arg.string);
break;
+ case ISN_LEGACY_EVAL:
+ smsg("%s%4d EVAL legacy %s", pfx, current,
+ iptr->isn_arg.string);
+ break;
case ISN_REDIRSTART:
smsg("%s%4d REDIR", pfx, current);
break;