Patch 7.4.1581
Problem: Using ":call dict.func()" where the function is a partial does
not work. Using "dict.func()" where the function does not take a
Dictionary does not work.
Solution: Handle partial properly in ":call". (Yasuhiro Matsumoto)
Files: src/eval.c, src/testdir/test_partial.vim, src/testdir/test55.ok
*** ../vim-7.4.1580/src/eval.c 2016-03-16 20:41:16.489091037 +0100
--- src/eval.c 2016-03-16 21:34:38.811937117 +0100
***************
*** 867,873 ****
static int tv_check_lock(int lock, char_u *name, int use_gettext);
static int item_copy(typval_T *from, typval_T *to, int deep, int copyID);
static char_u *find_option_end(char_u **arg, int *opt_flags);
! static char_u *trans_function_name(char_u **pp, int skip, int flags,
funcdict_T *fd);
static int eval_fname_script(char_u *p);
static int eval_fname_sid(char_u *p);
static void list_func_head(ufunc_T *fp, int indent);
--- 867,873 ----
static int tv_check_lock(int lock, char_u *name, int use_gettext);
static int item_copy(typval_T *from, typval_T *to, int deep, int copyID);
static char_u *find_option_end(char_u **arg, int *opt_flags);
! static char_u *trans_function_name(char_u **pp, int skip, int flags,
funcdict_T *fd, partial_T **partial);
static int eval_fname_script(char_u *p);
static int eval_fname_sid(char_u *p);
static void list_func_head(ufunc_T *fp, int indent);
***************
*** 3476,3482 ****
return;
}
! tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi);
if (fudi.fd_newkey != NULL)
{
/* Still need to give an error message for missing key. */
--- 3476,3482 ----
return;
}
! tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi, &partial);
if (fudi.fd_newkey != NULL)
{
/* Still need to give an error message for missing key. */
***************
*** 3491,3499 ****
if (fudi.fd_dict != NULL)
++fudi.fd_dict->dv_refcount;
! /* If it is the name of a variable of type VAR_FUNC use its contents. */
len = (int)STRLEN(tofree);
! name = deref_func_name(tofree, &len, &partial, FALSE);
/* Skip white space to allow ":call func ()". Not good, but required for
* backward compatibility. */
--- 3491,3508 ----
if (fudi.fd_dict != NULL)
++fudi.fd_dict->dv_refcount;
! /* If it is the name of a variable of type VAR_FUNC or VAR_PARTIAL use its
! * contents. For VAR_PARTIAL get its partial, unless we already have one
! * from trans_function_name(). */
len = (int)STRLEN(tofree);
! name = deref_func_name(tofree, &len,
! partial != NULL ? NULL : &partial, FALSE);
!
! /* When calling fdict.func(), where "func" is a partial, use "fdict"
! * instead of the dict in the partial, for backwards compatibility.
! * TODO: Do use the arguments in the partial? */
! if (fudi.fd_dict != NULL)
! partial = NULL;
/* Skip white space to allow ":call func ()". Not good, but required for
* backward compatibility. */
***************
*** 8561,8575 ****
/*
* Check if "name" is a variable of type VAR_FUNC. If so, return the function
* name it contains, otherwise return "name".
! * If "name" is of type VAR_PARTIAL also return "partial"
*/
static char_u *
! deref_func_name(char_u *name, int *lenp, partial_T **partial, int no_autoload)
{
dictitem_T *v;
int cc;
! *partial = NULL;
cc = name[*lenp];
name[*lenp] = NUL;
--- 8570,8586 ----
/*
* Check if "name" is a variable of type VAR_FUNC. If so, return the function
* name it contains, otherwise return "name".
! * If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set
! * "partialp".
*/
static char_u *
! deref_func_name(char_u *name, int *lenp, partial_T **partialp, int
no_autoload)
{
dictitem_T *v;
int cc;
! if (partialp != NULL)
! *partialp = NULL;
cc = name[*lenp];
name[*lenp] = NUL;
***************
*** 8588,8601 ****
if (v != NULL && v->di_tv.v_type == VAR_PARTIAL)
{
! *partial = v->di_tv.vval.v_partial;
! if (*partial == NULL)
{
*lenp = 0;
return (char_u *)""; /* just in case */
}
! *lenp = (int)STRLEN((*partial)->pt_name);
! return (*partial)->pt_name;
}
return name;
--- 8599,8615 ----
if (v != NULL && v->di_tv.v_type == VAR_PARTIAL)
{
! partial_T *pt = v->di_tv.vval.v_partial;
!
! if (pt == NULL)
{
*lenp = 0;
return (char_u *)""; /* just in case */
}
! if (partialp != NULL)
! *partialp = pt;
! *lenp = (int)STRLEN(pt->pt_name);
! return pt->pt_name;
}
return name;
***************
*** 21700,21717 ****
if (rettv->v_type == VAR_FUNC && selfdict != NULL)
{
! partial_T *pt = (partial_T *)alloc_clear(sizeof(partial_T));
/* Turn "dict.Func" into a partial for "Func" with "dict". */
! if (pt != NULL)
{
! pt->pt_refcount = 1;
! pt->pt_dict = selfdict;
! selfdict = NULL;
! pt->pt_name = rettv->vval.v_string;
! func_ref(pt->pt_name);
! rettv->v_type = VAR_PARTIAL;
! rettv->vval.v_partial = pt;
}
}
--- 21714,21736 ----
if (rettv->v_type == VAR_FUNC && selfdict != NULL)
{
! ufunc_T *fp = find_func(rettv->vval.v_string);
/* Turn "dict.Func" into a partial for "Func" with "dict". */
! if (fp != NULL && (fp->uf_flags & FC_DICT))
{
! partial_T *pt = (partial_T *)alloc_clear(sizeof(partial_T));
!
! if (pt != NULL)
! {
! pt->pt_refcount = 1;
! pt->pt_dict = selfdict;
! selfdict = NULL;
! pt->pt_name = rettv->vval.v_string;
! func_ref(pt->pt_name);
! rettv->v_type = VAR_PARTIAL;
! rettv->vval.v_partial = pt;
! }
}
}
***************
*** 23220,23226 ****
* g:func global function name, same as "func"
*/
p = eap->arg;
! name = trans_function_name(&p, eap->skip, 0, &fudi);
paren = (vim_strchr(p, '(') != NULL);
if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
{
--- 23239,23245 ----
* g:func global function name, same as "func"
*/
p = eap->arg;
! name = trans_function_name(&p, eap->skip, 0, &fudi, NULL);
paren = (vim_strchr(p, '(') != NULL);
if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
{
***************
*** 23533,23539 ****
if (*p == '!')
p = skipwhite(p + 1);
p += eval_fname_script(p);
! vim_free(trans_function_name(&p, TRUE, 0, NULL));
if (*skipwhite(p) == '(')
{
++nesting;
--- 23552,23558 ----
if (*p == '!')
p = skipwhite(p + 1);
p += eval_fname_script(p);
! vim_free(trans_function_name(&p, TRUE, 0, NULL, NULL));
if (*skipwhite(p) == '(')
{
++nesting;
***************
*** 23788,23794 ****
char_u **pp,
int skip, /* only find the end, don't evaluate */
int flags,
! funcdict_T *fdp) /* return: info about dictionary used */
{
char_u *name = NULL;
char_u *start;
--- 23807,23814 ----
char_u **pp,
int skip, /* only find the end, don't evaluate */
int flags,
! funcdict_T *fdp, /* return: info about dictionary used */
! partial_T **partial) /* return: partial of a FuncRef */
{
char_u *name = NULL;
char_u *start;
***************
*** 23797,23803 ****
char_u sid_buf[20];
int len;
lval_T lv;
- partial_T *partial;
if (fdp != NULL)
vim_memset(fdp, 0, sizeof(funcdict_T));
--- 23817,23822 ----
***************
*** 23882,23888 ****
if (lv.ll_exp_name != NULL)
{
len = (int)STRLEN(lv.ll_exp_name);
! name = deref_func_name(lv.ll_exp_name, &len, &partial,
flags & TFN_NO_AUTOLOAD);
if (name == lv.ll_exp_name)
name = NULL;
--- 23901,23907 ----
if (lv.ll_exp_name != NULL)
{
len = (int)STRLEN(lv.ll_exp_name);
! name = deref_func_name(lv.ll_exp_name, &len, partial,
flags & TFN_NO_AUTOLOAD);
if (name == lv.ll_exp_name)
name = NULL;
***************
*** 23890,23896 ****
else
{
len = (int)(end - *pp);
! name = deref_func_name(*pp, &len, &partial, flags & TFN_NO_AUTOLOAD);
if (name == *pp)
name = NULL;
}
--- 23909,23915 ----
else
{
len = (int)(end - *pp);
! name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD);
if (name == *pp)
name = NULL;
}
***************
*** 24115,24121 ****
int n = FALSE;
p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD,
! NULL);
nm = skipwhite(nm);
/* Only accept "funcname", "funcname ", "funcname (..." and
--- 24134,24140 ----
int n = FALSE;
p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET|TFN_NO_AUTOLOAD,
! NULL, NULL);
nm = skipwhite(nm);
/* Only accept "funcname", "funcname ", "funcname (..." and
***************
*** 24132,24138 ****
char_u *nm = name;
char_u *p;
! p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL);
if (p != NULL && *nm == NUL)
if (!check || translated_function_exists(p))
--- 24151,24157 ----
char_u *nm = name;
char_u *p;
! p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL, NULL);
if (p != NULL && *nm == NUL)
if (!check || translated_function_exists(p))
***************
*** 24488,24494 ****
funcdict_T fudi;
p = eap->arg;
! name = trans_function_name(&p, eap->skip, 0, &fudi);
vim_free(fudi.fd_newkey);
if (name == NULL)
{
--- 24507,24513 ----
funcdict_T fudi;
p = eap->arg;
! name = trans_function_name(&p, eap->skip, 0, &fudi, NULL);
vim_free(fudi.fd_newkey);
if (name == NULL)
{
*** ../vim-7.4.1580/src/testdir/test_partial.vim 2016-03-16
20:41:16.489091037 +0100
--- src/testdir/test_partial.vim 2016-03-16 20:43:29.567712656 +0100
***************
*** 16,21 ****
--- 16,23 ----
func Test_partial_args()
let Cb = function('MyFunc', ["foo", "bar"])
+
+ call Cb("zzz")
call assert_equal("foo/bar/xxx", Cb("xxx"))
call assert_equal("foo/bar/yyy", call(Cb, ["yyy"]))
***************
*** 49,54 ****
--- 51,59 ----
let Cb = function('MyDictFunc', dict)
call assert_equal("hello/xxx/yyy", Cb("xxx", "yyy"))
call assert_fails('Cb("fff")', 'E492:')
+
+ let dict = {"tr": function('tr', ['hello', 'h', 'H'])}
+ call assert_equal("Hello", dict.tr())
endfunc
func Test_partial_implicit()
*** ../vim-7.4.1580/src/testdir/test55.ok 2016-03-12 19:33:43.430403350
+0100
--- src/testdir/test55.ok 2016-03-16 21:28:32.627735123 +0100
***************
*** 44,50 ****
{'33': 999}
len: 3
again: 3
! Vim(call):E725:
g:dict.func-4
a:function('3')
Vim(let):E698:
--- 44,50 ----
{'33': 999}
len: 3
again: 3
! xxx3
g:dict.func-4
a:function('3')
Vim(let):E698:
*** ../vim-7.4.1580/src/version.c 2016-03-16 20:41:16.489091037 +0100
--- src/version.c 2016-03-16 20:44:15.699234847 +0100
***************
*** 750,751 ****
--- 750,753 ----
{ /* Add new patch number below this line */
+ /**/
+ 1581,
/**/
--
"I don’t know how to make a screenshot" - Richard Stallman, July 2002
(when asked to send a screenshot of his desktop for unix.se)
/// 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].
For more options, visit https://groups.google.com/d/optout.