Patch 8.2.0223
Problem: Some instructions not yet tested.
Solution: Disassemble more instructions. Move tests to a new file. Compile
call to s:function().
Files: src/testdir/test_vim9_script.vim, src/testdir/Make_all.mak,
src/testdir/test_vim9_disassemble.vim, src/vim9compile.c,
src/userfunc.c, src/proto/userfunc.pro, src/vim.h
*** ../vim-8.2.0222/src/testdir/test_vim9_script.vim 2020-02-06
17:51:31.306336443 +0100
--- src/testdir/test_vim9_script.vim 2020-02-06 18:36:52.595282394 +0100
***************
*** 489,703 ****
assert_notmatch('JUMP', instr)
enddef
- func NotCompiled()
- echo "not"
- endfunc
-
- let s:scriptvar = 4
- let g:globalvar = 'g'
-
- def s:ScriptFuncLoad(arg: string)
- let local = 1
- buffers
- echo arg
- echo local
- echo v:version
- echo s:scriptvar
- echo g:globalvar
- echo &tabstop
- echo $ENVVAR
- echo @z
- enddef
-
- def Test_disassembleLoad()
- assert_fails('disass NoFunc', 'E1061:')
- assert_fails('disass NotCompiled', 'E1062:')
-
- let res = execute('disass s:ScriptFuncLoad')
- assert_match('<SNR>\d*_ScriptFuncLoad.*'
- \ .. 'buffers.*'
- \ .. ' EXEC \+buffers.*'
- \ .. ' LOAD arg\[-1\].*'
- \ .. ' LOAD $0.*'
- \ .. ' LOADV v:version.*'
- \ .. ' LOADS s:scriptvar from .*test_vim9_script.vim.*'
- \ .. ' LOADG g:globalvar.*'
- \ .. ' LOADENV $ENVVAR.*'
- \ .. ' LOADREG @z.*'
- \, res)
- enddef
-
- def s:ScriptFuncPush()
- let localbool = true
- let localspec = v:none
- let localblob = 0z1234
- if has('float')
- let localfloat = 1.234
- endif
- enddef
-
- def Test_disassemblePush()
- let res = execute('disass s:ScriptFuncPush')
- assert_match('<SNR>\d*_ScriptFuncPush.*'
- \ .. 'localbool = true.*'
- \ .. ' PUSH v:true.*'
- \ .. 'localspec = v:none.*'
- \ .. ' PUSH v:none.*'
- \ .. 'localblob = 0z1234.*'
- \ .. ' PUSHBLOB 0z1234.*'
- \, res)
- if has('float')
- assert_match('<SNR>\d*_ScriptFuncPush.*'
- \ .. 'localfloat = 1.234.*'
- \ .. ' PUSHF 1.234.*'
- \, res)
- endif
- enddef
-
- def s:ScriptFuncStore()
- let localnr = 1
- localnr = 2
- let localstr = 'abc'
- localstr = 'xyz'
- v:char = 'abc'
- s:scriptvar = 'sv'
- g:globalvar = 'gv'
- &tabstop = 8
- $ENVVAR = 'ev'
- @z = 'rv'
- enddef
-
- def Test_disassembleStore()
- let res = execute('disass s:ScriptFuncStore')
- assert_match('<SNR>\d*_ScriptFuncStore.*'
- \ .. 'localnr = 2.*'
- \ .. ' STORE 2 in $0.*'
- \ .. 'localstr = ''xyz''.*'
- \ .. ' STORE $1.*'
- \ .. 'v:char = ''abc''.*'
- \ .. 'STOREV v:char.*'
- \ .. 's:scriptvar = ''sv''.*'
- \ .. ' STORES s:scriptvar in .*test_vim9_script.vim.*'
- \ .. 'g:globalvar = ''gv''.*'
- \ .. ' STOREG g:globalvar.*'
- \ .. '&tabstop = 8.*'
- \ .. ' STOREOPT &tabstop.*'
- \ .. '$ENVVAR = ''ev''.*'
- \ .. ' STOREENV $ENVVAR.*'
- \ .. '@z = ''rv''.*'
- \ .. ' STOREREG @z.*'
- \, res)
- enddef
-
- def s:ScriptFuncTry()
- try
- echo 'yes'
- catch /fail/
- echo 'no'
- finally
- echo 'end'
- endtry
- enddef
-
- def Test_disassembleTry()
- let res = execute('disass s:ScriptFuncTry')
- assert_match('<SNR>\d*_ScriptFuncTry.*'
- \ .. 'try.*'
- \ .. 'TRY catch -> \d\+, finally -> \d\+.*'
- \ .. 'catch /fail/.*'
- \ .. ' JUMP -> \d\+.*'
- \ .. ' PUSH v:exception.*'
- \ .. ' PUSHS "fail".*'
- \ .. ' COMPARESTRING =\~.*'
- \ .. ' JUMP_IF_FALSE -> \d\+.*'
- \ .. ' CATCH.*'
- \ .. 'finally.*'
- \ .. ' PUSHS "end".*'
- \ .. 'endtry.*'
- \ .. ' ENDTRY.*'
- \, res)
- enddef
-
- def s:ScriptFuncNew()
- let ll = [1, "two", 333]
- let dd = #{one: 1, two: "val"}
- enddef
-
- def Test_disassembleNew()
- let res = execute('disass s:ScriptFuncNew')
- assert_match('<SNR>\d*_ScriptFuncNew.*'
- \ .. 'let ll = \[1, "two", 333].*'
- \ .. 'PUSHNR 1.*'
- \ .. 'PUSHS "two".*'
- \ .. 'PUSHNR 333.*'
- \ .. 'NEWLIST size 3.*'
- \ .. 'let dd = #{one: 1, two: "val"}.*'
- \ .. 'PUSHS "one".*'
- \ .. 'PUSHNR 1.*'
- \ .. 'PUSHS "two".*'
- \ .. 'PUSHS "val".*'
- \ .. 'NEWDICT size 2.*'
- \, res)
- enddef
-
- def FuncWithArg(arg)
- echo arg
- enddef
-
- func UserFunc()
- echo 'nothing'
- endfunc
-
- func UserFuncWithArg(arg)
- echo a:arg
- endfunc
-
- def s:ScriptFuncCall(): string
- changenr()
- char2nr("abc")
- Test_disassembleNew()
- FuncWithArg(343)
- UserFunc()
- UserFuncWithArg("foo")
- let FuncRef = function("UserFunc")
- FuncRef()
- let FuncRefWithArg = function("UserFuncWithArg")
- FuncRefWithArg("bar")
- return "yes"
- enddef
-
- def Test_disassembleCall()
- let res = execute('disass s:ScriptFuncCall')
- assert_match('<SNR>\d*_ScriptFuncCall.*'
- \ .. 'changenr().*'
- \ .. ' BCALL changenr(argc 0).*'
- \ .. 'char2nr("abc").*'
- \ .. ' PUSHS "abc".*'
- \ .. ' BCALL char2nr(argc 1).*'
- \ .. 'Test_disassembleNew().*'
- \ .. ' DCALL Test_disassembleNew(argc 0).*'
- \ .. 'FuncWithArg(343).*'
- \ .. ' PUSHNR 343.*'
- \ .. ' DCALL FuncWithArg(argc 1).*'
- \ .. 'UserFunc().*'
- \ .. ' UCALL UserFunc(argc 0).*'
- \ .. 'UserFuncWithArg("foo").*'
- \ .. ' PUSHS "foo".*'
- \ .. ' UCALL UserFuncWithArg(argc 1).*'
- \ .. 'let FuncRef = function("UserFunc").*'
- \ .. 'FuncRef().*'
- \ .. ' LOAD $\d.*'
- \ .. ' PCALL (argc 0).*'
- \ .. 'let FuncRefWithArg = function("UserFuncWithArg").*'
- \ .. 'FuncRefWithArg("bar").*'
- \ .. ' PUSHS "bar".*'
- \ .. ' LOAD $\d.*'
- \ .. ' PCALL (argc 1).*'
- \ .. 'return "yes".*'
- \ .. ' PUSHS "yes".*'
- \ .. ' RETURN.*'
- \, res)
- enddef
-
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
--- 489,493 ----
*** ../vim-8.2.0222/src/testdir/Make_all.mak 2020-01-28 21:53:24.039964573
+0100
--- src/testdir/Make_all.mak 2020-02-06 18:38:47.010836096 +0100
***************
*** 268,273 ****
--- 268,274 ----
test_utf8 \
test_utf8_comparisons \
test_vartabs \
+ test_vim9_disassemble \
test_vim9_expr \
test_vim9_script \
test_viminfo \
***************
*** 470,475 ****
--- 471,477 ----
test_user_func.res \
test_usercommands.res \
test_vartabs.res \
+ test_vim9_disassemble.res \
test_vim9_expr.res \
test_vim9_script.res \
test_viminfo.res \
*** ../vim-8.2.0222/src/testdir/test_vim9_disassemble.vim 2020-02-06
19:24:19.456463654 +0100
--- src/testdir/test_vim9_disassemble.vim 2020-02-06 19:23:57.984545879
+0100
***************
*** 0 ****
--- 1,220 ----
+ " Test the :disassemble command, and compilation as a side effect
+
+ func NotCompiled()
+ echo "not"
+ endfunc
+
+ let s:scriptvar = 4
+ let g:globalvar = 'g'
+
+ def s:ScriptFuncLoad(arg: string)
+ let local = 1
+ buffers
+ echo arg
+ echo local
+ echo v:version
+ echo s:scriptvar
+ echo g:globalvar
+ echo &tabstop
+ echo $ENVVAR
+ echo @z
+ enddef
+
+ def Test_disassembleLoad()
+ assert_fails('disass NoFunc', 'E1061:')
+ assert_fails('disass NotCompiled', 'E1062:')
+
+ let res = execute('disass s:ScriptFuncLoad')
+ assert_match('<SNR>\d*_ScriptFuncLoad.*'
+ \ .. 'buffers.*'
+ \ .. ' EXEC \+buffers.*'
+ \ .. ' LOAD arg\[-1\].*'
+ \ .. ' LOAD $0.*'
+ \ .. ' LOADV v:version.*'
+ \ .. ' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*'
+ \ .. ' LOADG g:globalvar.*'
+ \ .. ' LOADENV $ENVVAR.*'
+ \ .. ' LOADREG @z.*'
+ \, res)
+ enddef
+
+ def s:ScriptFuncPush()
+ let localbool = true
+ let localspec = v:none
+ let localblob = 0z1234
+ if has('float')
+ let localfloat = 1.234
+ endif
+ enddef
+
+ def Test_disassemblePush()
+ let res = execute('disass s:ScriptFuncPush')
+ assert_match('<SNR>\d*_ScriptFuncPush.*'
+ \ .. 'localbool = true.*'
+ \ .. ' PUSH v:true.*'
+ \ .. 'localspec = v:none.*'
+ \ .. ' PUSH v:none.*'
+ \ .. 'localblob = 0z1234.*'
+ \ .. ' PUSHBLOB 0z1234.*'
+ \, res)
+ if has('float')
+ assert_match('<SNR>\d*_ScriptFuncPush.*'
+ \ .. 'localfloat = 1.234.*'
+ \ .. ' PUSHF 1.234.*'
+ \, res)
+ endif
+ enddef
+
+ def s:ScriptFuncStore()
+ let localnr = 1
+ localnr = 2
+ let localstr = 'abc'
+ localstr = 'xyz'
+ v:char = 'abc'
+ s:scriptvar = 'sv'
+ g:globalvar = 'gv'
+ &tabstop = 8
+ $ENVVAR = 'ev'
+ @z = 'rv'
+ enddef
+
+ def Test_disassembleStore()
+ let res = execute('disass s:ScriptFuncStore')
+ assert_match('<SNR>\d*_ScriptFuncStore.*'
+ \ .. 'localnr = 2.*'
+ \ .. ' STORE 2 in $0.*'
+ \ .. 'localstr = ''xyz''.*'
+ \ .. ' STORE $1.*'
+ \ .. 'v:char = ''abc''.*'
+ \ .. 'STOREV v:char.*'
+ \ .. 's:scriptvar = ''sv''.*'
+ \ .. ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*'
+ \ .. 'g:globalvar = ''gv''.*'
+ \ .. ' STOREG g:globalvar.*'
+ \ .. '&tabstop = 8.*'
+ \ .. ' STOREOPT &tabstop.*'
+ \ .. '$ENVVAR = ''ev''.*'
+ \ .. ' STOREENV $ENVVAR.*'
+ \ .. '@z = ''rv''.*'
+ \ .. ' STOREREG @z.*'
+ \, res)
+ enddef
+
+ def s:ScriptFuncTry()
+ try
+ echo 'yes'
+ catch /fail/
+ echo 'no'
+ finally
+ echo 'end'
+ endtry
+ enddef
+
+ def Test_disassembleTry()
+ let res = execute('disass s:ScriptFuncTry')
+ assert_match('<SNR>\d*_ScriptFuncTry.*'
+ \ .. 'try.*'
+ \ .. 'TRY catch -> \d\+, finally -> \d\+.*'
+ \ .. 'catch /fail/.*'
+ \ .. ' JUMP -> \d\+.*'
+ \ .. ' PUSH v:exception.*'
+ \ .. ' PUSHS "fail".*'
+ \ .. ' COMPARESTRING =\~.*'
+ \ .. ' JUMP_IF_FALSE -> \d\+.*'
+ \ .. ' CATCH.*'
+ \ .. 'finally.*'
+ \ .. ' PUSHS "end".*'
+ \ .. 'endtry.*'
+ \ .. ' ENDTRY.*'
+ \, res)
+ enddef
+
+ def s:ScriptFuncNew()
+ let ll = [1, "two", 333]
+ let dd = #{one: 1, two: "val"}
+ enddef
+
+ def Test_disassembleNew()
+ let res = execute('disass s:ScriptFuncNew')
+ assert_match('<SNR>\d*_ScriptFuncNew.*'
+ \ .. 'let ll = \[1, "two", 333].*'
+ \ .. 'PUSHNR 1.*'
+ \ .. 'PUSHS "two".*'
+ \ .. 'PUSHNR 333.*'
+ \ .. 'NEWLIST size 3.*'
+ \ .. 'let dd = #{one: 1, two: "val"}.*'
+ \ .. 'PUSHS "one".*'
+ \ .. 'PUSHNR 1.*'
+ \ .. 'PUSHS "two".*'
+ \ .. 'PUSHS "val".*'
+ \ .. 'NEWDICT size 2.*'
+ \, res)
+ enddef
+
+ def FuncWithArg(arg)
+ echo arg
+ enddef
+
+ func UserFunc()
+ echo 'nothing'
+ endfunc
+
+ func UserFuncWithArg(arg)
+ echo a:arg
+ endfunc
+
+ def s:ScriptFuncCall(): string
+ changenr()
+ char2nr("abc")
+ Test_disassembleNew()
+ FuncWithArg(343)
+ ScriptFuncNew()
+ s:ScriptFuncNew()
+ UserFunc()
+ UserFuncWithArg("foo")
+ let FuncRef = function("UserFunc")
+ FuncRef()
+ let FuncRefWithArg = function("UserFuncWithArg")
+ FuncRefWithArg("bar")
+ return "yes"
+ enddef
+
+ def Test_disassembleCall()
+ let res = execute('disass s:ScriptFuncCall')
+ assert_match('<SNR>\d\+_ScriptFuncCall.*'
+ \ .. 'changenr().*'
+ \ .. ' BCALL changenr(argc 0).*'
+ \ .. 'char2nr("abc").*'
+ \ .. ' PUSHS "abc".*'
+ \ .. ' BCALL char2nr(argc 1).*'
+ \ .. 'Test_disassembleNew().*'
+ \ .. ' DCALL Test_disassembleNew(argc 0).*'
+ \ .. 'FuncWithArg(343).*'
+ \ .. ' PUSHNR 343.*'
+ \ .. ' DCALL FuncWithArg(argc 1).*'
+ \ .. 'ScriptFuncNew().*'
+ \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
+ \ .. 's:ScriptFuncNew().*'
+ \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
+ \ .. 'UserFunc().*'
+ \ .. ' UCALL UserFunc(argc 0).*'
+ \ .. 'UserFuncWithArg("foo").*'
+ \ .. ' PUSHS "foo".*'
+ \ .. ' UCALL UserFuncWithArg(argc 1).*'
+ \ .. 'let FuncRef = function("UserFunc").*'
+ \ .. 'FuncRef().*'
+ \ .. ' LOAD $\d.*'
+ \ .. ' PCALL (argc 0).*'
+ \ .. 'let FuncRefWithArg = function("UserFuncWithArg").*'
+ \ .. 'FuncRefWithArg("bar").*'
+ \ .. ' PUSHS "bar".*'
+ \ .. ' LOAD $\d.*'
+ \ .. ' PCALL (argc 1).*'
+ \ .. 'return "yes".*'
+ \ .. ' PUSHS "yes".*'
+ \ .. ' RETURN.*'
+ \, res)
+ enddef
+
+
+ " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
*** ../vim-8.2.0222/src/vim9compile.c 2020-02-06 17:51:31.306336443 +0100
--- src/vim9compile.c 2020-02-06 19:19:41.025526497 +0100
***************
*** 1686,1734 ****
char_u *p;
int argcount = argcount_init;
char_u namebuf[100];
ufunc_T *ufunc;
if (varlen >= sizeof(namebuf))
{
semsg(_("E1011: name too long: %s"), name);
return FAIL;
}
! vim_strncpy(namebuf, name, varlen);
*arg = skipwhite(*arg + varlen + 1);
if (compile_arguments(arg, cctx, &argcount) == FAIL)
! return FAIL;
! if (ASCII_ISLOWER(*name))
{
int idx;
// builtin function
! idx = find_internal_func(namebuf);
if (idx >= 0)
! return generate_BCALL(cctx, idx, argcount);
semsg(_(e_unknownfunc), namebuf);
}
- // User defined function or variable must start with upper case.
- if (!ASCII_ISUPPER(*name))
- {
- semsg(_("E1012: Invalid function name: %s"), namebuf);
- return FAIL;
- }
-
// If we can find the function by name generate the right call.
! ufunc = find_func(namebuf, cctx);
if (ufunc != NULL)
! return generate_CALL(cctx, ufunc, argcount);
// If the name is a variable, load it and use PCALL.
p = namebuf;
if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
! return generate_PCALL(cctx, argcount, FALSE);
// The function may be defined only later. Need to figure out at runtime.
! return generate_UCALL(cctx, namebuf, argcount);
}
// like NAMESPACE_CHAR but with 'a' and 'l'.
--- 1686,1745 ----
char_u *p;
int argcount = argcount_init;
char_u namebuf[100];
+ char_u fname_buf[FLEN_FIXED + 1];
+ char_u *tofree = NULL;
+ int error = FCERR_NONE;
ufunc_T *ufunc;
+ int res = FAIL;
if (varlen >= sizeof(namebuf))
{
semsg(_("E1011: name too long: %s"), name);
return FAIL;
}
! vim_strncpy(namebuf, *arg, varlen);
! name = fname_trans_sid(namebuf, fname_buf, &tofree, &error);
*arg = skipwhite(*arg + varlen + 1);
if (compile_arguments(arg, cctx, &argcount) == FAIL)
! goto theend;
! if (ASCII_ISLOWER(*name) && name[1] != ':')
{
int idx;
// builtin function
! idx = find_internal_func(name);
if (idx >= 0)
! {
! res = generate_BCALL(cctx, idx, argcount);
! goto theend;
! }
semsg(_(e_unknownfunc), namebuf);
}
// If we can find the function by name generate the right call.
! ufunc = find_func(name, cctx);
if (ufunc != NULL)
! {
! res = generate_CALL(cctx, ufunc, argcount);
! goto theend;
! }
// If the name is a variable, load it and use PCALL.
p = namebuf;
if (compile_load(&p, namebuf + varlen, cctx, FALSE) == OK)
! {
! res = generate_PCALL(cctx, argcount, FALSE);
! goto theend;
! }
// The function may be defined only later. Need to figure out at runtime.
! res = generate_UCALL(cctx, name, argcount);
!
! theend:
! vim_free(tofree);
! return res;
}
// like NAMESPACE_CHAR but with 'a' and 'l'.
*** ../vim-8.2.0222/src/userfunc.c 2020-02-06 17:51:31.306336443 +0100
--- src/userfunc.c 2020-02-06 19:15:08.234558758 +0100
***************
*** 573,580 ****
return ret;
}
- #define FLEN_FIXED 40
-
/*
* Return TRUE if "p" starts with "<SID>" or "s:".
* Only works if eval_fname_script() returned non-zero for "p"!
--- 573,578 ----
***************
*** 591,597 ****
* Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory
* (slow).
*/
! static char_u *
fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error)
{
int llen;
--- 589,595 ----
* Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory
* (slow).
*/
! char_u *
fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error)
{
int llen;
*** ../vim-8.2.0222/src/proto/userfunc.pro 2020-01-26 15:52:33.023833239
+0100
--- src/proto/userfunc.pro 2020-02-06 19:16:58.658142270 +0100
***************
*** 6,11 ****
--- 6,12 ----
char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int
no_autoload);
void emsg_funcname(char *ermsg, char_u *name);
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg,
funcexe_T *funcexe);
+ char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int
*error);
ufunc_T *find_func(char_u *name, cctx_T *cctx);
int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars,
typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
void save_funccal(funccal_entry_T *entry);
***************
*** 26,32 ****
int function_exists(char_u *name, int no_deref);
char_u *get_expanded_name(char_u *name, int check);
char_u *get_user_func_name(expand_T *xp, int idx);
- void clean_script_functions(int sid);
void ex_delfunction(exarg_T *eap);
void func_unref(char_u *name);
void func_ptr_unref(ufunc_T *fp);
--- 27,32 ----
*** ../vim-8.2.0222/src/vim.h 2020-01-26 22:43:27.484098902 +0100
--- src/vim.h 2020-02-06 19:16:09.830326727 +0100
***************
*** 2574,2579 ****
--- 2574,2582 ----
#define FCERR_DELETED 7
#define FCERR_NOTMETHOD 8 // function cannot be used as a method
+ // fixed buffer length for fname_trans_sid()
+ #define FLEN_FIXED 40
+
// flags for find_name_end()
#define FNE_INCL_BR 1 // include [] in name
#define FNE_CHECK_START 2 // check name starts with valid
character
*** ../vim-8.2.0222/src/version.c 2020-02-06 17:51:31.306336443 +0100
--- src/version.c 2020-02-06 18:38:12.370971292 +0100
***************
*** 744,745 ****
--- 744,747 ----
{ /* Add new patch number below this line */
+ /**/
+ 223,
/**/
--
He who laughs last, thinks slowest.
/// 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/202002061825.016IPtWQ019830%40masaka.moolenaar.net.