mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.2.2861: Vim9: "legacy return" is not recognized as a return statement
Problem: Vim9: "legacy return" is not recognized as a return statement. Solution: Specifically check for a return command. (closes #8213)
This commit is contained in:
@@ -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
|
||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2861,
|
||||
/**/
|
||||
2860,
|
||||
/**/
|
||||
|
@@ -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
|
||||
|
@@ -2173,6 +2173,25 @@ generate_EXEC(cctx_T *cctx, char_u *line)
|
||||
return OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -5321,20 +5340,36 @@ 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;
|
||||
type_T *stack_type;
|
||||
|
||||
if (*p != NUL && *p != '|' && *p != '\n')
|
||||
{
|
||||
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)
|
||||
{
|
||||
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:
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user