mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.0487: Vim9: compiling not sufficiently tested
Problem: Vim9: compiling not sufficiently tested. Solution: Add more tests. Fix bug with PCALL.
This commit is contained in:
@@ -224,6 +224,31 @@ def Test_disassemble_call()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
|
||||||
|
def EchoArg(arg: string): string
|
||||||
|
return arg
|
||||||
|
enddef
|
||||||
|
def RefThis(): func
|
||||||
|
return function('EchoArg')
|
||||||
|
enddef
|
||||||
|
def s:ScriptPCall()
|
||||||
|
RefThis()("text")
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Test_disassemble_pcall()
|
||||||
|
let res = execute('disass s:ScriptPCall')
|
||||||
|
assert_match('<SNR>\d\+_ScriptPCall.*'
|
||||||
|
\ .. 'RefThis()("text").*'
|
||||||
|
\ .. '\d DCALL RefThis(argc 0).*'
|
||||||
|
\ .. '\d PUSHS "text".*'
|
||||||
|
\ .. '\d PCALL top (argc 1).*'
|
||||||
|
\ .. '\d PCALL end.*'
|
||||||
|
\ .. '\d DROP.*'
|
||||||
|
\ .. '\d PUSHNR 0.*'
|
||||||
|
\ .. '\d RETURN.*'
|
||||||
|
\, res)
|
||||||
|
enddef
|
||||||
|
|
||||||
|
|
||||||
def FuncWithForwardCall(): string
|
def FuncWithForwardCall(): string
|
||||||
return DefinedLater("yes")
|
return DefinedLater("yes")
|
||||||
enddef
|
enddef
|
||||||
|
@@ -260,9 +260,10 @@ func TakesOneArg(arg)
|
|||||||
echo a:arg
|
echo a:arg
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
def Test_call_wrong_arg_count()
|
def Test_call_wrong_args()
|
||||||
call CheckDefFailure(['TakesOneArg()'], 'E119:')
|
call CheckDefFailure(['TakesOneArg()'], 'E119:')
|
||||||
call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
|
call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
|
||||||
|
call CheckDefFailure(['bufnr(xxx)'], 'E1001:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
" Default arg and varargs
|
" Default arg and varargs
|
||||||
@@ -1029,6 +1030,14 @@ def Test_while_loop()
|
|||||||
assert_equal('1_3_', result)
|
assert_equal('1_3_', result)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_for_loop_fails()
|
||||||
|
call CheckDefFailure(['for # in range(5)'], 'E690:')
|
||||||
|
call CheckDefFailure(['for i In range(5)'], 'E690:')
|
||||||
|
call CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:')
|
||||||
|
call CheckScriptFailure(['def Func(arg)', 'for arg in range(5)', 'enddef'], 'E1006:')
|
||||||
|
call CheckDefFailure(['for i in "text"'], 'E1024:')
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_interrupt_loop()
|
def Test_interrupt_loop()
|
||||||
let caught = false
|
let caught = false
|
||||||
let x = 0
|
let x = 0
|
||||||
|
@@ -738,6 +738,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 */
|
||||||
|
/**/
|
||||||
|
487,
|
||||||
/**/
|
/**/
|
||||||
486,
|
486,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -57,6 +57,7 @@ typedef enum {
|
|||||||
ISN_DCALL, // call def function isn_arg.dfunc
|
ISN_DCALL, // call def function isn_arg.dfunc
|
||||||
ISN_UCALL, // call user function or funcref/partial isn_arg.ufunc
|
ISN_UCALL, // call user function or funcref/partial isn_arg.ufunc
|
||||||
ISN_PCALL, // call partial, use isn_arg.pfunc
|
ISN_PCALL, // call partial, use isn_arg.pfunc
|
||||||
|
ISN_PCALL_END, // cleanup after ISN_PCALL with cpf_top set
|
||||||
ISN_RETURN, // return, result is on top of stack
|
ISN_RETURN, // return, result is on top of stack
|
||||||
ISN_FUNCREF, // push a function ref to dfunc isn_arg.number
|
ISN_FUNCREF, // push a function ref to dfunc isn_arg.number
|
||||||
|
|
||||||
@@ -256,7 +257,7 @@ struct dfunc_S {
|
|||||||
// Functions defined with :def are stored in this growarray.
|
// Functions defined with :def are stored in this growarray.
|
||||||
// They are never removed, so that they can be found by index.
|
// They are never removed, so that they can be found by index.
|
||||||
// Deleted functions have the df_deleted flag set.
|
// Deleted functions have the df_deleted flag set.
|
||||||
garray_T def_functions = {0, 0, sizeof(dfunc_T), 50, NULL};
|
garray_T def_functions = {0, 0, sizeof(dfunc_T), 200, NULL};
|
||||||
#else
|
#else
|
||||||
extern garray_T def_functions;
|
extern garray_T def_functions;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1196,6 +1196,11 @@ generate_PCALL(cctx_T *cctx, int argcount, int at_top)
|
|||||||
// drop the funcref/partial, get back the return value
|
// drop the funcref/partial, get back the return value
|
||||||
((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
|
((type_T **)stack->ga_data)[stack->ga_len - 1] = &t_any;
|
||||||
|
|
||||||
|
// If partial is above the arguments it must be cleared and replaced with
|
||||||
|
// the return value.
|
||||||
|
if (at_top && generate_instr(cctx, ISN_PCALL_END) == NULL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5200,7 +5205,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
|
|||||||
p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
|
p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
|
||||||
? ea.cmd + 1 : ea.cmd;
|
? ea.cmd + 1 : ea.cmd;
|
||||||
p = to_name_end(p, TRUE);
|
p = to_name_end(p, TRUE);
|
||||||
if ((p > ea.cmd && *p != NUL) || *p == '(')
|
if (p > ea.cmd && *p != NUL)
|
||||||
{
|
{
|
||||||
int oplen;
|
int oplen;
|
||||||
int heredoc;
|
int heredoc;
|
||||||
@@ -5538,6 +5543,7 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_OPFLOAT:
|
case ISN_OPFLOAT:
|
||||||
case ISN_OPANY:
|
case ISN_OPANY:
|
||||||
case ISN_PCALL:
|
case ISN_PCALL:
|
||||||
|
case ISN_PCALL_END:
|
||||||
case ISN_PUSHF:
|
case ISN_PUSHF:
|
||||||
case ISN_PUSHNR:
|
case ISN_PUSHNR:
|
||||||
case ISN_PUSHBOOL:
|
case ISN_PUSHBOOL:
|
||||||
|
@@ -345,7 +345,7 @@ call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
|
|||||||
static int
|
static int
|
||||||
call_partial(typval_T *tv, int argcount, ectx_T *ectx)
|
call_partial(typval_T *tv, int argcount, ectx_T *ectx)
|
||||||
{
|
{
|
||||||
char_u *name;
|
char_u *name = NULL;
|
||||||
int called_emsg_before = called_emsg;
|
int called_emsg_before = called_emsg;
|
||||||
|
|
||||||
if (tv->v_type == VAR_PARTIAL)
|
if (tv->v_type == VAR_PARTIAL)
|
||||||
@@ -356,9 +356,9 @@ call_partial(typval_T *tv, int argcount, ectx_T *ectx)
|
|||||||
return call_ufunc(pt->pt_func, argcount, ectx, NULL);
|
return call_ufunc(pt->pt_func, argcount, ectx, NULL);
|
||||||
name = pt->pt_name;
|
name = pt->pt_name;
|
||||||
}
|
}
|
||||||
else
|
else if (tv->v_type == VAR_FUNC)
|
||||||
name = tv->vval.v_string;
|
name = tv->vval.v_string;
|
||||||
if (call_by_name(name, argcount, ectx, NULL) == FAIL)
|
if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL)
|
||||||
{
|
{
|
||||||
if (called_emsg == called_emsg_before)
|
if (called_emsg == called_emsg_before)
|
||||||
semsg(_(e_unknownfunc), name);
|
semsg(_(e_unknownfunc), name);
|
||||||
@@ -421,7 +421,6 @@ call_def_function(
|
|||||||
typval_T *tv;
|
typval_T *tv;
|
||||||
int idx;
|
int idx;
|
||||||
int ret = FAIL;
|
int ret = FAIL;
|
||||||
dfunc_T *dfunc;
|
|
||||||
int defcount = ufunc->uf_args.ga_len - argc;
|
int defcount = ufunc->uf_args.ga_len - argc;
|
||||||
|
|
||||||
// Get pointer to item in the stack.
|
// Get pointer to item in the stack.
|
||||||
@@ -467,13 +466,17 @@ call_def_function(
|
|||||||
++ectx.ec_stack.ga_len;
|
++ectx.ec_stack.ga_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserve space for local variables.
|
{
|
||||||
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
|
// Reserve space for local variables.
|
||||||
for (idx = 0; idx < dfunc->df_varcount; ++idx)
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||||
STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
|
+ ufunc->uf_dfunc_idx;
|
||||||
ectx.ec_stack.ga_len += dfunc->df_varcount;
|
|
||||||
|
|
||||||
ectx.ec_instr = dfunc->df_instr;
|
for (idx = 0; idx < dfunc->df_varcount; ++idx)
|
||||||
|
STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN;
|
||||||
|
ectx.ec_stack.ga_len += dfunc->df_varcount;
|
||||||
|
|
||||||
|
ectx.ec_instr = dfunc->df_instr;
|
||||||
|
}
|
||||||
|
|
||||||
// Decide where to start execution, handles optional arguments.
|
// Decide where to start execution, handles optional arguments.
|
||||||
init_instr_idx(ufunc, argc, &ectx);
|
init_instr_idx(ufunc, argc, &ectx);
|
||||||
@@ -1022,18 +1025,18 @@ call_def_function(
|
|||||||
clear_tv(&partial);
|
clear_tv(&partial);
|
||||||
if (r == FAIL)
|
if (r == FAIL)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
if (pfunc->cpf_top)
|
|
||||||
{
|
|
||||||
// Get the funcref from the stack, overwrite with the
|
|
||||||
// return value.
|
|
||||||
clear_tv(tv);
|
|
||||||
--ectx.ec_stack.ga_len;
|
|
||||||
*STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISN_PCALL_END:
|
||||||
|
// PCALL finished, arguments have been consumed and replaced by
|
||||||
|
// the return value. Now clear the funcref from the stack,
|
||||||
|
// and move the return value in its place.
|
||||||
|
--ectx.ec_stack.ga_len;
|
||||||
|
clear_tv(STACK_TV_BOT(-1));
|
||||||
|
*STACK_TV_BOT(-1) = *STACK_TV_BOT(0);
|
||||||
|
break;
|
||||||
|
|
||||||
// call a user defined function or funcref/partial
|
// call a user defined function or funcref/partial
|
||||||
case ISN_UCALL:
|
case ISN_UCALL:
|
||||||
{
|
{
|
||||||
@@ -1078,6 +1081,7 @@ call_def_function(
|
|||||||
case ISN_FUNCREF:
|
case ISN_FUNCREF:
|
||||||
{
|
{
|
||||||
partial_T *pt = NULL;
|
partial_T *pt = NULL;
|
||||||
|
dfunc_T *dfunc;
|
||||||
|
|
||||||
pt = ALLOC_CLEAR_ONE(partial_T);
|
pt = ALLOC_CLEAR_ONE(partial_T);
|
||||||
if (pt == NULL)
|
if (pt == NULL)
|
||||||
@@ -2005,6 +2009,9 @@ ex_disassemble(exarg_T *eap)
|
|||||||
cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
|
cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ISN_PCALL_END:
|
||||||
|
smsg("%4d PCALL end", current);
|
||||||
|
break;
|
||||||
case ISN_RETURN:
|
case ISN_RETURN:
|
||||||
smsg("%4d RETURN", current);
|
smsg("%4d RETURN", current);
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user