Patch 8.2.0487
Problem: Vim9: compiling not sufficiently tested.
Solution: Add more tests. Fix bug with PCALL.
Files: src/vim9compile.c, src/vim9execute.c, src/vim9.h,
src/testdir/test_vim9_script.vim,
src/testdir/test_vim9_disassemble.vim
*** ../vim-8.2.0486/src/vim9compile.c 2020-03-30 22:51:20.647982632 +0200
--- src/vim9compile.c 2020-03-31 22:14:42.410207941 +0200
***************
*** 1196,1201 ****
--- 1196,1206 ----
// drop the funcref/partial, get back the return value
((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;
}
***************
*** 5200,5206 ****
p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
? ea.cmd + 1 : ea.cmd;
p = to_name_end(p, TRUE);
! if ((p > ea.cmd && *p != NUL) || *p == '(')
{
int oplen;
int heredoc;
--- 5205,5211 ----
p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
? ea.cmd + 1 : ea.cmd;
p = to_name_end(p, TRUE);
! if (p > ea.cmd && *p != NUL)
{
int oplen;
int heredoc;
***************
*** 5538,5543 ****
--- 5543,5549 ----
case ISN_OPFLOAT:
case ISN_OPANY:
case ISN_PCALL:
+ case ISN_PCALL_END:
case ISN_PUSHF:
case ISN_PUSHNR:
case ISN_PUSHBOOL:
*** ../vim-8.2.0486/src/vim9execute.c 2020-03-29 18:40:08.853652561 +0200
--- src/vim9execute.c 2020-03-31 22:57:21.186038745 +0200
***************
*** 345,351 ****
static int
call_partial(typval_T *tv, int argcount, ectx_T *ectx)
{
! char_u *name;
int called_emsg_before = called_emsg;
if (tv->v_type == VAR_PARTIAL)
--- 345,351 ----
static int
call_partial(typval_T *tv, int argcount, ectx_T *ectx)
{
! char_u *name = NULL;
int called_emsg_before = called_emsg;
if (tv->v_type == VAR_PARTIAL)
***************
*** 356,364 ****
return call_ufunc(pt->pt_func, argcount, ectx, NULL);
name = pt->pt_name;
}
! else
name = tv->vval.v_string;
! if (call_by_name(name, argcount, ectx, NULL) == FAIL)
{
if (called_emsg == called_emsg_before)
semsg(_(e_unknownfunc), name);
--- 356,364 ----
return call_ufunc(pt->pt_func, argcount, ectx, NULL);
name = pt->pt_name;
}
! else if (tv->v_type == VAR_FUNC)
name = tv->vval.v_string;
! if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL)
{
if (called_emsg == called_emsg_before)
semsg(_(e_unknownfunc), name);
***************
*** 421,427 ****
typval_T *tv;
int idx;
int ret = FAIL;
- dfunc_T *dfunc;
int defcount = ufunc->uf_args.ga_len - argc;
// Get pointer to item in the stack.
--- 421,426 ----
***************
*** 467,479 ****
++ectx.ec_stack.ga_len;
}
! // Reserve space for local variables.
! dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
! 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.
init_instr_idx(ufunc, argc, &ectx);
--- 466,482 ----
++ectx.ec_stack.ga_len;
}
! {
! // Reserve space for local variables.
! dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
! + ufunc->uf_dfunc_idx;
!
! 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.
init_instr_idx(ufunc, argc, &ectx);
***************
*** 1022,1039 ****
clear_tv(&partial);
if (r == FAIL)
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;
// call a user defined function or funcref/partial
case ISN_UCALL:
{
--- 1025,1042 ----
clear_tv(&partial);
if (r == FAIL)
goto failed;
}
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
case ISN_UCALL:
{
***************
*** 1078,1083 ****
--- 1081,1087 ----
case ISN_FUNCREF:
{
partial_T *pt = NULL;
+ dfunc_T *dfunc;
pt = ALLOC_CLEAR_ONE(partial_T);
if (pt == NULL)
***************
*** 2005,2010 ****
--- 2009,2017 ----
cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount);
}
break;
+ case ISN_PCALL_END:
+ smsg("%4d PCALL end", current);
+ break;
case ISN_RETURN:
smsg("%4d RETURN", current);
break;
*** ../vim-8.2.0486/src/vim9.h 2020-03-20 18:39:42.981273170 +0100
--- src/vim9.h 2020-03-31 23:06:03.492096623 +0200
***************
*** 57,62 ****
--- 57,63 ----
ISN_DCALL, // call def function isn_arg.dfunc
ISN_UCALL, // call user function or funcref/partial
isn_arg.ufunc
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_FUNCREF, // push a function ref to dfunc isn_arg.number
***************
*** 256,262 ****
// Functions defined with :def are stored in this growarray.
// They are never removed, so that they can be found by index.
// Deleted functions have the df_deleted flag set.
! garray_T def_functions = {0, 0, sizeof(dfunc_T), 50, NULL};
#else
extern garray_T def_functions;
#endif
--- 257,263 ----
// Functions defined with :def are stored in this growarray.
// They are never removed, so that they can be found by index.
// Deleted functions have the df_deleted flag set.
! garray_T def_functions = {0, 0, sizeof(dfunc_T), 200, NULL};
#else
extern garray_T def_functions;
#endif
*** ../vim-8.2.0486/src/testdir/test_vim9_script.vim 2020-03-30
22:51:20.647982632 +0200
--- src/testdir/test_vim9_script.vim 2020-03-31 21:20:09.159386006 +0200
***************
*** 260,268 ****
echo a:arg
endfunc
! def Test_call_wrong_arg_count()
call CheckDefFailure(['TakesOneArg()'], 'E119:')
call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
enddef
" Default arg and varargs
--- 260,269 ----
echo a:arg
endfunc
! def Test_call_wrong_args()
call CheckDefFailure(['TakesOneArg()'], 'E119:')
call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
+ call CheckDefFailure(['bufnr(xxx)'], 'E1001:')
enddef
" Default arg and varargs
***************
*** 1029,1034 ****
--- 1030,1043 ----
assert_equal('1_3_', result)
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()
let caught = false
let x = 0
*** ../vim-8.2.0486/src/testdir/test_vim9_disassemble.vim 2020-03-19
14:52:16.973228215 +0100
--- src/testdir/test_vim9_disassemble.vim 2020-03-31 22:53:33.458923423
+0200
***************
*** 224,229 ****
--- 224,254 ----
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
return DefinedLater("yes")
enddef
*** ../vim-8.2.0486/src/version.c 2020-03-30 22:51:20.647982632 +0200
--- src/version.c 2020-03-31 23:07:02.831880459 +0200
***************
*** 740,741 ****
--- 740,743 ----
{ /* Add new patch number below this line */
+ /**/
+ 487,
/**/
--
My girlfriend told me I should be more affectionate.
So I got TWO girlfriends.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/202003312113.02VLDdNg021765%40masaka.moolenaar.net.