Patch 8.1.1816

12 views
Skip to first unread message

Bram Moolenaar

unread,
Aug 4, 2019, 5:05:29 PM8/4/19
to vim...@googlegroups.com

Patch 8.1.1816
Problem: Cannot use a user defined function as a method.
Solution: Pass the base as the first argument to the user defined function
after "->". (partly by FUJIWARA Takuya)
Files: src/eval.c, src/userfunc.c, src/testdir/test_user_func.vim,
src/testdir/test_autoload.vim,
src/testdir/sautest/autoload/foo.vim


*** ../vim-8.1.1815/src/eval.c 2019-08-03 21:58:17.753476626 +0200
--- src/eval.c 2019-08-04 23:03:59.314117093 +0200
***************
*** 4734,4740 ****
*arg = skipwhite(*arg);

/* Handle following '[', '(' and '.' for expr[expr], expr.name,
! * expr(expr). */
if (ret == OK)
ret = handle_subscript(arg, rettv, evaluate, TRUE);

--- 4734,4740 ----
*arg = skipwhite(*arg);

/* Handle following '[', '(' and '.' for expr[expr], expr.name,
! * expr(expr), expr->name(expr) */
if (ret == OK)
ret = handle_subscript(arg, rettv, evaluate, TRUE);

***************
*** 4824,4830 ****

// Locate the method name.
name = *arg;
! for (len = 0; ASCII_ISALNUM(name[len]) || name[len] == '_'; ++len)
;
if (len == 0)
{
--- 4824,4830 ----

// Locate the method name.
name = *arg;
! for (len = 0; eval_isnamec(name[len]); ++len)
;
if (len == 0)
{
***************
*** 4842,4847 ****
--- 4842,4849 ----
}
*arg += len;

+ // TODO: if "name" is a function reference, resolve it.
+
vim_memset(&funcexe, 0, sizeof(funcexe));
funcexe.evaluate = evaluate;
funcexe.basetv = &base;
*** ../vim-8.1.1815/src/userfunc.c 2019-08-03 21:58:17.753476626 +0200
--- src/userfunc.c 2019-08-04 22:30:21.439145793 +0200
***************
*** 1495,1501 ****
int argcount = argcount_in;
typval_T *argvars = argvars_in;
dict_T *selfdict = funcexe->selfdict;
! typval_T argv[MAX_FUNC_ARGS + 1]; /* used when "partial" is not NULL */
int argv_clear = 0;
partial_T *partial = funcexe->partial;

--- 1495,1502 ----
int argcount = argcount_in;
typval_T *argvars = argvars_in;
dict_T *selfdict = funcexe->selfdict;
! typval_T argv[MAX_FUNC_ARGS + 1]; // used when "partial" or
! // "funcexe->basetv" is not NULL
int argv_clear = 0;
partial_T *partial = funcexe->partial;

***************
*** 1554,1563 ****
/*
* User defined function.
*/
! if (funcexe->basetv != NULL)
! // TODO: support User function: base->Method()
! fp = NULL;
! else if (partial != NULL && partial->pt_func != NULL)
fp = partial->pt_func;
else
fp = find_func(rfname);
--- 1555,1561 ----
/*
* User defined function.
*/
! if (partial != NULL && partial->pt_func != NULL)
fp = partial->pt_func;
else
fp = find_func(rfname);
***************
*** 1586,1591 ****
--- 1584,1599 ----
argcount = funcexe->argv_func(argcount, argvars,
fp->uf_args.ga_len);

+ if (funcexe->basetv != NULL)
+ {
+ // Method call: base->Method()
+ mch_memmove(&argv[1], argvars, sizeof(typval_T) * argcount);
+ argv[0] = *funcexe->basetv;
+ argcount++;
+ }
+ else
+ memcpy(argv, argvars, sizeof(typval_T) * argcount);
+
if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL)
*funcexe->doesrange = TRUE;
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len)
***************
*** 1613,1619 ****
did_save_redo = TRUE;
}
++fp->uf_calls;
! call_user_func(fp, argcount, argvars, rettv,
funcexe->firstline, funcexe->lastline,
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
--- 1621,1627 ----
did_save_redo = TRUE;
}
++fp->uf_calls;
! call_user_func(fp, argcount, argv, rettv,
funcexe->firstline, funcexe->lastline,
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
***************
*** 1630,1636 ****
else if (funcexe->basetv != NULL)
{
/*
! * Find the method name in the table, call its implementation.
*/
error = call_internal_method(fname, argcount, argvars, rettv,
funcexe->basetv);
--- 1638,1645 ----
else if (funcexe->basetv != NULL)
{
/*
! * expr->method(): Find the method name in the table, call its
! * implementation with the base as one of the arguments.
*/
error = call_internal_method(fname, argcount, argvars, rettv,
funcexe->basetv);
*** ../vim-8.1.1815/src/testdir/test_user_func.vim 2019-05-09 21:08:53.764083394 +0200
--- src/testdir/test_user_func.vim 2019-08-04 22:39:19.696363364 +0200
***************
*** 47,53 ****
endfunc

func Test_user_func()
! let g:FuncRef=function("FuncWithRef")
let g:counter = 0
inoremap <expr> ( ListItem()
inoremap <expr> [ ListReset()
--- 47,53 ----
endfunc

func Test_user_func()
! let g:FuncRef = function("FuncWithRef")
let g:counter = 0
inoremap <expr> ( ListItem()
inoremap <expr> [ ListReset()
***************
*** 62,67 ****
--- 62,75 ----
call assert_equal(9, g:retval)
call assert_equal(333, g:FuncRef(333))

+ let g:retval = "nop"
+ call assert_equal('xxx4asdf', "xxx"->Table(4, "asdf"))
+ call assert_equal('fail', 45->Compute(0, "retval"))
+ call assert_equal('nop', g:retval)
+ call assert_equal('ok', 45->Compute(5, "retval"))
+ call assert_equal(9, g:retval)
+ " call assert_equal(333, 333->g:FuncRef())
+
enew

normal oXX+-XX
***************
*** 144,146 ****
--- 152,162 ----
\ .. " endfunction",
\ execute('func Args2'))
endfunc
+
+ func s:addFoo(lead)
+ return a:lead .. 'foo'
+ endfunc
+
+ func Test_user_method()
+ eval 'bar'->s:addFoo()->assert_equal('barfoo')
+ endfunc
*** ../vim-8.1.1815/src/testdir/test_autoload.vim 2017-12-07 22:18:46.000000000 +0100
--- src/testdir/test_autoload.vim 2019-08-04 22:44:15.459095622 +0200
***************
*** 8,13 ****
--- 8,15 ----
call g:foo#bar.echo()
call assert_equal(1, g:loaded_foo_vim)
call assert_equal(1, g:called_foo_bar_echo)
+
+ eval 'bar'->g:foo#addFoo()->assert_equal('barfoo')
endfunc

func Test_source_autoload()
*** ../vim-8.1.1815/src/testdir/sautest/autoload/foo.vim 2017-12-07 21:44:49.000000000 +0100
--- src/testdir/sautest/autoload/foo.vim 2019-08-04 22:44:34.831034514 +0200
***************
*** 5,7 ****
--- 5,11 ----
func foo#bar.echo()
let g:called_foo_bar_echo += 1
endfunc
+
+ func foo#addFoo(head)
+ return a:head .. 'foo'
+ endfunc
*** ../vim-8.1.1815/src/version.c 2019-08-04 21:35:08.035889064 +0200
--- src/version.c 2019-08-04 23:02:06.206648737 +0200
***************
*** 775,776 ****
--- 775,778 ----
{ /* Add new patch number below this line */
+ /**/
+ 1816,
/**/

--
How To Keep A Healthy Level Of Insanity:
2. Page yourself over the intercom. Don't disguise your voice.

/// Bram Moolenaar -- Br...@Moolenaar.net -- 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 ///
Reply all
Reply to author
Forward
0 new messages