]> granicus.if.org Git - vim/commitdiff
patch 8.2.0223: some instructions not yet tested v8.2.0223
authorBram Moolenaar <Bram@vim.org>
Thu, 6 Feb 2020 18:25:19 +0000 (19:25 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 6 Feb 2020 18:25:19 +0000 (19:25 +0100)
Problem:    Some instructions not yet tested.
Solution:   Disassemble more instructions.  Move tests to a new file.  Compile
            call to s:function().

src/proto/userfunc.pro
src/testdir/Make_all.mak
src/testdir/test_vim9_disassemble.vim [new file with mode: 0644]
src/testdir/test_vim9_script.vim
src/userfunc.c
src/version.c
src/vim.h
src/vim9compile.c

index 74bcabd8cefdaac97d7a2e329899f85b781ba353..165b04b5e49c5f268a2891b2821098c386898784 100644 (file)
@@ -6,6 +6,7 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate);
 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,7 +27,6 @@ int has_varargs(ufunc_T *ufunc);
 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);
index 350e58e571bec205a566c2788cd6ea759df61bdf..40e56a290fa7f07284fa12036be4700c4086a68f 100644 (file)
@@ -268,6 +268,7 @@ NEW_TESTS = \
        test_utf8 \
        test_utf8_comparisons \
        test_vartabs \
+       test_vim9_disassemble \
        test_vim9_expr \
        test_vim9_script \
        test_viminfo \
@@ -470,6 +471,7 @@ NEW_TESTS_RES = \
        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 \
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
new file mode 100644 (file)
index 0000000..3345758
--- /dev/null
@@ -0,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
index d7b3b4c9950f4478ed28ee6c0d46b94c924c9547..4b57bde0bd2b6d6debdf9723bf14db43b4ddbca4 100644 (file)
@@ -489,215 +489,5 @@ def Test_compile_const_expr()
   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
index 3c2673dde6d5140364294f0d45d933cda0f5acdb..1c25a626850679467f7ca4361f065d6f5df41790 100644 (file)
@@ -573,8 +573,6 @@ get_func_tv(
     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"!
@@ -591,7 +589,7 @@ eval_fname_sid(char_u *p)
  * Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory
  * (slow).
  */
-    static char_u *
+    char_u *
 fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error)
 {
     int                llen;
index 09f9e9c3c695cc3a5ae3550904c296c3042de71e..e76bdea7732043907bc002fe9b5e05e978fba846 100644 (file)
@@ -742,6 +742,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    223,
 /**/
     222,
 /**/
index 23e53747a4ffb84f0f7d92205bfc77f76945b323..12af8560c6fc8a00e2b77c149691e782016833d0 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2574,6 +2574,9 @@ typedef enum {
 #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
index a362fe8b489262fac679a49389f08d25178ddabc..922618b0a09a741cb2a66e05f5c05d702be5cc25 100644 (file)
@@ -1686,49 +1686,60 @@ compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
     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, name, varlen);
+    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)
-       return FAIL;
+       goto theend;
 
-    if (ASCII_ISLOWER(*name))
+    if (ASCII_ISLOWER(*name) && name[1] != ':')
     {
        int         idx;
 
        // builtin function
-       idx = find_internal_func(namebuf);
+       idx = find_internal_func(name);
        if (idx >= 0)
-           return generate_BCALL(cctx, idx, argcount);
+       {
+           res = generate_BCALL(cctx, idx, argcount);
+           goto theend;
+       }
        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);
+    ufunc = find_func(name, cctx);
     if (ufunc != NULL)
-       return generate_CALL(cctx, ufunc, argcount);
+    {
+       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)
-       return generate_PCALL(cctx, argcount, FALSE);
+    {
+       res = generate_PCALL(cctx, argcount, FALSE);
+       goto theend;
+    }
 
     // The function may be defined only later.  Need to figure out at runtime.
-    return generate_UCALL(cctx, namebuf, argcount);
+    res = generate_UCALL(cctx, name, argcount);
+
+theend:
+    vim_free(tofree);
+    return res;
 }
 
 // like NAMESPACE_CHAR but with 'a' and 'l'.