patch 8.1.1996: more functions can be used as methods

Problem:    More functions can be used as methods.
Solution:   Make various functions usable as a method.
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 2949c89..0aa8fbf 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -336,6 +336,7 @@
 #define FEARG_1    1	    // base is the first argument
 #define FEARG_2    2	    // base is the second argument
 #define FEARG_3    3	    // base is the third argument
+#define FEARG_4    4	    // base is the fourth argument
 #define FEARG_LAST 9	    // base is the last argument
 
 static funcentry_T global_functions[] =
@@ -721,20 +722,20 @@
     {"setenv",		2, 2, FEARG_2,	  f_setenv},
     {"setfperm",	2, 2, FEARG_1,	  f_setfperm},
     {"setline",		2, 2, FEARG_2,	  f_setline},
-    {"setloclist",	2, 4, 0,	  f_setloclist},
-    {"setmatches",	1, 2, 0,	  f_setmatches},
-    {"setpos",		2, 2, 0,	  f_setpos},
-    {"setqflist",	1, 3, 0,	  f_setqflist},
-    {"setreg",		2, 3, 0,	  f_setreg},
-    {"settabvar",	3, 3, 0,	  f_settabvar},
-    {"settabwinvar",	4, 4, 0,	  f_settabwinvar},
-    {"settagstack",	2, 3, 0,	  f_settagstack},
-    {"setwinvar",	3, 3, 0,	  f_setwinvar},
+    {"setloclist",	2, 4, FEARG_2,	  f_setloclist},
+    {"setmatches",	1, 2, FEARG_1,	  f_setmatches},
+    {"setpos",		2, 2, FEARG_2,	  f_setpos},
+    {"setqflist",	1, 3, FEARG_1,	  f_setqflist},
+    {"setreg",		2, 3, FEARG_2,	  f_setreg},
+    {"settabvar",	3, 3, FEARG_3,	  f_settabvar},
+    {"settabwinvar",	4, 4, FEARG_4,	  f_settabwinvar},
+    {"settagstack",	2, 3, FEARG_2,	  f_settagstack},
+    {"setwinvar",	3, 3, FEARG_3,	  f_setwinvar},
 #ifdef FEAT_CRYPT
-    {"sha256",		1, 1, 0,	  f_sha256},
+    {"sha256",		1, 1, FEARG_1,	  f_sha256},
 #endif
-    {"shellescape",	1, 2, 0,	  f_shellescape},
-    {"shiftwidth",	0, 1, 0,	  f_shiftwidth},
+    {"shellescape",	1, 2, FEARG_1,	  f_shellescape},
+    {"shiftwidth",	0, 1, FEARG_1,	  f_shiftwidth},
 #ifdef FEAT_SIGNS
     {"sign_define",	1, 2, FEARG_1,	  f_sign_define},
     {"sign_getdefined",	0, 1, FEARG_1,	  f_sign_getdefined},
@@ -1060,6 +1061,16 @@
 	for (i = 2; i < argcount; ++i)
 	    argv[i + 1] = argvars[i];
     }
+    else if (global_functions[fi].f_argtype == FEARG_4)
+    {
+	// base value goes fourth
+	argv[0] = argvars[0];
+	argv[1] = argvars[1];
+	argv[2] = argvars[2];
+	argv[3] = *basetv;
+	for (i = 3; i < argcount; ++i)
+	    argv[i + 1] = argvars[i];
+    }
     else
     {
 	// FEARG_1: base value goes first
diff --git a/src/testdir/test_bufwintabinfo.vim b/src/testdir/test_bufwintabinfo.vim
index 4e2c5d2..ee22ebd 100644
--- a/src/testdir/test_bufwintabinfo.vim
+++ b/src/testdir/test_bufwintabinfo.vim
@@ -47,7 +47,7 @@
     tabnew | let w3_id = win_getid()
     new | let w4_id = win_getid()
     vert new | let w5_id = win_getid()
-    call setwinvar(0, 'signal', 'green')
+    eval 'green'->setwinvar(0, 'signal')
     tabfirst
     let winlist = getwininfo()
     call assert_equal(5, len(winlist))
diff --git a/src/testdir/test_cursor_func.vim b/src/testdir/test_cursor_func.vim
index 4fc28c9..66d5d03 100644
--- a/src/testdir/test_cursor_func.vim
+++ b/src/testdir/test_cursor_func.vim
@@ -37,7 +37,7 @@
 " Very short version of what matchparen does.
 function s:Highlight_Matching_Pair()
   let save_cursor = getcurpos()
-  call setpos('.', save_cursor)
+  eval save_cursor->setpos('.')
 endfunc
 
 func Test_curswant_with_autocommand()
diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim
index 9f43732..110cecb 100644
--- a/src/testdir/test_expr.vim
+++ b/src/testdir/test_expr.vim
@@ -504,7 +504,7 @@
     let set[0]['conceal'] = 5
     let exp[0]['conceal'] = '5'
   endif
-  call setmatches(set)
+  eval set->setmatches()
   call assert_equal(exp, getmatches())
 endfunc
 
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim
index 1d8d74d..3588c76 100644
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -1180,7 +1180,7 @@
   let save_shell = &shell
   set shell=bash
   call assert_equal("'text'", shellescape('text'))
-  call assert_equal("'te\"xt'", shellescape('te"xt'))
+  call assert_equal("'te\"xt'", 'te"xt'->shellescape())
   call assert_equal("'te'\\''xt'", shellescape("te'xt"))
 
   call assert_equal("'te%xt'", shellescape("te%xt"))
diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim
index afe82f9..225ebd1 100644
--- a/src/testdir/test_put.vim
+++ b/src/testdir/test_put.vim
@@ -41,7 +41,7 @@
   call assert_equal(['Line 3', '', 'Line 1', 'Line2'], getline(1,'$'))
   " clean up
   bw!
-  call setreg('a', a[0], a[1])
+  eval a[0]->setreg('a', a[1])
 endfunc
 
 func Test_put_expr()
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 7a1f96d..402a96d 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -711,7 +711,7 @@
       " NOTE: problem 1:
       " intentionally not setting 'lnum' so that the quickfix entries are not
       " valid
-      call setloclist(0, qflist, ' ')
+      eval qflist->setloclist(0, ' ')
     endfor
 
     " Test A
@@ -1515,7 +1515,7 @@
 
 func Test_setqflist_invalid_nr()
   " The following command used to crash Vim
-  call setqflist([], ' ', {'nr' : $XXX_DOES_NOT_EXIST})
+  eval []->setqflist(' ', {'nr' : $XXX_DOES_NOT_EXIST})
 endfunc
 
 func Test_quickfix_set_list_with_act()
diff --git a/src/testdir/test_sha256.vim b/src/testdir/test_sha256.vim
index d0f92b1..f6f430b 100644
--- a/src/testdir/test_sha256.vim
+++ b/src/testdir/test_sha256.vim
@@ -6,17 +6,17 @@
 
 function Test_sha256()
   " test for empty string:
-  call assert_equal(sha256(""), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855')
+  call assert_equal('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', sha256(""))
 
   "'test for 1 char:
-  call assert_equal(sha256("a"), 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb')
+  call assert_equal('ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb', sha256("a"))
   "
   "test for 3 chars:
-  call assert_equal(sha256("abc"), 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad')
+  call assert_equal('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', "abc"->sha256())
 
   " test for contains meta char:
-  call assert_equal(sha256("foo\nbar"), '807eff6267f3f926a21d234f7b0cf867a86f47e07a532f15e8cc39ed110ca776')
+  call assert_equal('807eff6267f3f926a21d234f7b0cf867a86f47e07a532f15e8cc39ed110ca776', sha256("foo\nbar"))
 
   " test for contains non-ascii char:
-  call assert_equal(sha256("\xde\xad\xbe\xef"), '5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953')
+  call assert_equal('5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953', sha256("\xde\xad\xbe\xef"))
 endfunction
diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim
index c8ac114..020fe27 100644
--- a/src/testdir/test_tabpage.vim
+++ b/src/testdir/test_tabpage.vim
@@ -34,7 +34,7 @@
   tabnew
   tabfirst
   call settabvar(2, 'val_num', 100)
-  call settabvar(2, 'val_str', 'SetTabVar test')
+  eval 'SetTabVar test'->settabvar(2, 'val_str')
   call settabvar(2, 'val_list', ['red', 'blue', 'green'])
   "
   call assert_true(gettabvar(2, 'val_num') == 100 && gettabvar(2, 'val_str') == 'SetTabVar test' && gettabvar(2, 'val_list') == ['red', 'blue', 'green'])
@@ -183,7 +183,7 @@
   let s:li = split(join(map(copy(winr), 'gettabwinvar('.tabn.', v:val, "a")')), '\s\+')
   call assert_equal(['a', 'a'], s:li)
   let s:li = []
-  C call map(copy(winr), 'settabwinvar('.tabn.', v:val, ''a'', v:val*2)')
+  C call map(copy(winr), '(v:val*2)->settabwinvar(' .. tabn .. ', v:val, ''a'')')
   let s:li = split(join(map(copy(winr), 'gettabwinvar('.tabn.', v:val, "a")')), '\s\+')
   call assert_equal(['2', '4'], s:li)
 
diff --git a/src/testdir/test_tagjump.vim b/src/testdir/test_tagjump.vim
index 4c16129..6d47020 100644
--- a/src/testdir/test_tagjump.vim
+++ b/src/testdir/test_tagjump.vim
@@ -303,7 +303,7 @@
   " Try to set current index to invalid values
   call settagstack(1, {'curidx' : -1})
   call assert_equal(1, gettagstack().curidx)
-  call settagstack(1, {'curidx' : 50})
+  eval {'curidx' : 50}->settagstack(1)
   call assert_equal(4, gettagstack().curidx)
 
   " Try pushing invalid items onto the stack
diff --git a/src/testdir/test_vartabs.vim b/src/testdir/test_vartabs.vim
index b0f3e15..47844fb 100644
--- a/src/testdir/test_vartabs.vim
+++ b/src/testdir/test_vartabs.vim
@@ -329,7 +329,7 @@
   let lines = ScreenLines([1, 2], winwidth(0))
   call s:compare_lines(expect2, lines)
   call assert_equal(20, shiftwidth(virtcol('.')-2))
-  call assert_equal(30, shiftwidth(virtcol('.')))
+  call assert_equal(30, virtcol('.')->shiftwidth())
   norm! $>>
   let expect3 = ['                                        ', '                    x                   ', '~                                       ']
   let lines = ScreenLines([1, 3], winwidth(0))
diff --git a/src/version.c b/src/version.c
index 65512c9..9610b1a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1996,
+/**/
     1995,
 /**/
     1994,