forked from aniani/vim
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:')
|
CheckDefAndScriptFailure(lines, 'E15:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def LegacyReturn(): string
|
||||||
|
legacy return #{key: 'ok'}.key
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_expr7_legacy_script()
|
def Test_expr7_legacy_script()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
let s:legacy = 'legacy'
|
let s:legacy = 'legacy'
|
||||||
@@ -2790,6 +2794,17 @@ def Test_expr7_legacy_script()
|
|||||||
call assert_equal('legacy', GetLocalPrefix())
|
call assert_equal('legacy', GetLocalPrefix())
|
||||||
END
|
END
|
||||||
CheckScriptSuccess(lines)
|
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
|
enddef
|
||||||
|
|
||||||
def Echo(arg: any): string
|
def Echo(arg: any): string
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2861,
|
||||||
/**/
|
/**/
|
||||||
2860,
|
2860,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
ISN_EXEC, // execute Ex command line isn_arg.string
|
ISN_EXEC, // execute Ex command line isn_arg.string
|
||||||
ISN_EXECCONCAT, // execute Ex command from isn_arg.number items on stack
|
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_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_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
|
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;
|
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
|
static int
|
||||||
generate_EXECCONCAT(cctx_T *cctx, int count)
|
generate_EXECCONCAT(cctx_T *cctx, int count)
|
||||||
{
|
{
|
||||||
@@ -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 *
|
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;
|
char_u *p = arg;
|
||||||
garray_T *stack = &cctx->ctx_type_stack;
|
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')
|
if (*p != NUL && *p != '|' && *p != '\n')
|
||||||
{
|
{
|
||||||
// compile return argument into instructions
|
if (legacy)
|
||||||
if (compile_expr0(&p, cctx) == FAIL)
|
{
|
||||||
return NULL;
|
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)
|
if (cctx->ctx_skip != SKIP_YES)
|
||||||
{
|
{
|
||||||
@@ -9193,7 +9228,15 @@ compile_def_function(
|
|||||||
|
|
||||||
// When using ":legacy cmd" always use compile_exec().
|
// When using ":legacy cmd" always use compile_exec().
|
||||||
if (local_cmdmod.cmod_flags & CMOD_LEGACY)
|
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)
|
if (p == ea.cmd && ea.cmdidx != CMD_SIZE)
|
||||||
{
|
{
|
||||||
@@ -9254,7 +9297,8 @@ compile_def_function(
|
|||||||
goto erret;
|
goto erret;
|
||||||
|
|
||||||
case CMD_return:
|
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;
|
cctx.ctx_had_return = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -9605,6 +9649,7 @@ delete_instr(isn_T *isn)
|
|||||||
{
|
{
|
||||||
case ISN_DEF:
|
case ISN_DEF:
|
||||||
case ISN_EXEC:
|
case ISN_EXEC:
|
||||||
|
case ISN_LEGACY_EVAL:
|
||||||
case ISN_LOADAUTO:
|
case ISN_LOADAUTO:
|
||||||
case ISN_LOADB:
|
case ISN_LOADB:
|
||||||
case ISN_LOADENV:
|
case ISN_LOADENV:
|
||||||
|
@@ -1388,6 +1388,27 @@ exec_instructions(ectx_T *ectx)
|
|||||||
}
|
}
|
||||||
break;
|
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
|
// push typeval VAR_INSTR with instructions to be executed
|
||||||
case ISN_INSTR:
|
case ISN_INSTR:
|
||||||
{
|
{
|
||||||
@@ -4464,6 +4485,10 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
|||||||
case ISN_EXEC:
|
case ISN_EXEC:
|
||||||
smsg("%s%4d EXEC %s", pfx, current, iptr->isn_arg.string);
|
smsg("%s%4d EXEC %s", pfx, current, iptr->isn_arg.string);
|
||||||
break;
|
break;
|
||||||
|
case ISN_LEGACY_EVAL:
|
||||||
|
smsg("%s%4d EVAL legacy %s", pfx, current,
|
||||||
|
iptr->isn_arg.string);
|
||||||
|
break;
|
||||||
case ISN_REDIRSTART:
|
case ISN_REDIRSTART:
|
||||||
smsg("%s%4d REDIR", pfx, current);
|
smsg("%s%4d REDIR", pfx, current);
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user