1
0
forked from aniani/vim

patch 7.4.1559

Problem:    Passing cookie to a callback is clumsy.
Solution:   Change function() to take arguments and return a partial.
This commit is contained in:
Bram Moolenaar
2016-03-14 23:05:14 +01:00
parent 9cdf86b86f
commit 1735bc988c
12 changed files with 486 additions and 69 deletions

View File

@@ -452,8 +452,8 @@ static char_u *tv2string(typval_T *tv, char_u **tofree, char_u *numbuf, int copy
static char_u *string_quote(char_u *str, int function);
static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate);
static int find_internal_func(char_u *name);
static char_u *deref_func_name(char_u *name, int *lenp, int no_autoload);
static int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict);
static char_u *deref_func_name(char_u *name, int *lenp, partial_T **partial, int no_autoload);
static int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict);
static void emsg_funcname(char *ermsg, char_u *name);
static int non_zero_arg(typval_T *argvars);
@@ -1675,7 +1675,7 @@ call_vim_function(
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars,
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&doesrange, TRUE, NULL);
&doesrange, TRUE, NULL, NULL);
if (safe)
{
--sandbox;
@@ -3091,6 +3091,7 @@ tv_op(typval_T *tv1, typval_T *tv2, char_u *op)
case VAR_UNKNOWN:
case VAR_DICT:
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_SPECIAL:
case VAR_JOB:
case VAR_CHANNEL:
@@ -3456,6 +3457,7 @@ ex_call(exarg_T *eap)
int doesrange;
int failed = FALSE;
funcdict_T fudi;
partial_T *partial;
if (eap->skip)
{
@@ -3486,7 +3488,7 @@ ex_call(exarg_T *eap)
/* 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, FALSE);
name = deref_func_name(tofree, &len, &partial, FALSE);
/* Skip white space to allow ":call func ()". Not good, but required for
* backward compatibility. */
@@ -3525,7 +3527,7 @@ ex_call(exarg_T *eap)
arg = startarg;
if (get_func_tv(name, (int)STRLEN(name), &rettv, &arg,
eap->line1, eap->line2, &doesrange,
!eap->skip, fudi.fd_dict) == FAIL)
!eap->skip, partial, fudi.fd_dict) == FAIL)
{
failed = TRUE;
break;
@@ -3870,6 +3872,7 @@ item_lock(typval_T *tv, int deep, int lock)
case VAR_NUMBER:
case VAR_STRING:
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_FLOAT:
case VAR_SPECIAL:
case VAR_JOB:
@@ -4542,7 +4545,8 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
}
}
else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC)
else if (rettv->v_type == VAR_FUNC || var2.v_type == VAR_FUNC
|| rettv->v_type == VAR_PARTIAL || var2.v_type == VAR_PARTIAL)
{
if (rettv->v_type != var2.v_type
|| (type != TYPE_EQUAL && type != TYPE_NEQUAL))
@@ -4555,6 +4559,12 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
clear_tv(&var2);
return FAIL;
}
else if (rettv->v_type == VAR_PARTIAL)
{
/* Partials are only equal when identical. */
n1 = rettv->vval.v_partial != NULL
&& rettv->vval.v_partial == var2.vval.v_partial;
}
else
{
/* Compare two Funcrefs for being equal or unequal. */
@@ -4564,9 +4574,9 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
else
n1 = STRCMP(rettv->vval.v_string,
var2.vval.v_string) == 0;
if (type == TYPE_NEQUAL)
n1 = !n1;
}
if (type == TYPE_NEQUAL)
n1 = !n1;
}
#ifdef FEAT_FLOAT
@@ -5230,14 +5240,16 @@ eval7(
{
if (**arg == '(') /* recursive! */
{
partial_T *partial;
/* If "s" is the name of a variable of type VAR_FUNC
* use its contents. */
s = deref_func_name(s, &len, !evaluate);
s = deref_func_name(s, &len, &partial, !evaluate);
/* Invoke the function. */
ret = get_func_tv(s, len, rettv, arg,
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&len, evaluate, NULL);
&len, evaluate, partial, NULL);
/* If evaluate is FALSE rettv->v_type was not set in
* get_func_tv, but it's needed in handle_subscript() to parse
@@ -5359,6 +5371,7 @@ eval_index(
switch (rettv->v_type)
{
case VAR_FUNC:
case VAR_PARTIAL:
if (verbose)
EMSG(_("E695: Cannot index a Funcref"));
return FAIL;
@@ -5480,6 +5493,7 @@ eval_index(
{
case VAR_UNKNOWN:
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_FLOAT:
case VAR_SPECIAL:
case VAR_JOB:
@@ -6218,6 +6232,10 @@ tv_equal(
&& tv2->vval.v_string != NULL
&& STRCMP(tv1->vval.v_string, tv2->vval.v_string) == 0);
case VAR_PARTIAL:
return tv1->vval.v_partial != NULL
&& tv1->vval.v_partial == tv2->vval.v_partial;
case VAR_NUMBER:
return tv1->vval.v_number == tv2->vval.v_number;
@@ -7793,6 +7811,12 @@ echo_string(
r = tv->vval.v_string;
break;
case VAR_PARTIAL:
*tofree = NULL;
/* TODO: arguments */
r = tv->vval.v_partial == NULL ? NULL : tv->vval.v_partial->pt_name;
break;
case VAR_LIST:
if (tv->vval.v_list == NULL)
{
@@ -7878,6 +7902,10 @@ tv2string(
case VAR_FUNC:
*tofree = string_quote(tv->vval.v_string, TRUE);
return *tofree;
case VAR_PARTIAL:
*tofree = string_quote(tv->vval.v_partial == NULL ? NULL
: tv->vval.v_partial->pt_name, TRUE);
return *tofree;
case VAR_STRING:
*tofree = string_quote(tv->vval.v_string, FALSE);
return *tofree;
@@ -8146,7 +8174,7 @@ static struct fst
{"foldtext", 0, 0, f_foldtext},
{"foldtextresult", 1, 1, f_foldtextresult},
{"foreground", 0, 0, f_foreground},
{"function", 1, 1, f_function},
{"function", 1, 3, f_function},
{"garbagecollect", 0, 1, f_garbagecollect},
{"get", 2, 3, f_get},
{"getbufline", 2, 3, f_getbufline},
@@ -8524,13 +8552,16 @@ find_internal_func(
/*
* 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, int no_autoload)
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;
v = find_var(name, NULL, no_autoload);
@@ -8546,6 +8577,18 @@ deref_func_name(char_u *name, int *lenp, int no_autoload)
return v->di_tv.vval.v_string;
}
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;
}
@@ -8563,6 +8606,7 @@ get_func_tv(
linenr_T lastline, /* last line of range */
int *doesrange, /* return: function handled range */
int evaluate,
partial_T *partial, /* for extra arguments */
dict_T *selfdict) /* Dictionary for "self" */
{
char_u *argp;
@@ -8574,7 +8618,7 @@ get_func_tv(
* Get the arguments.
*/
argp = *arg;
while (argcount < MAX_FUNC_ARGS)
while (argcount < MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc))
{
argp = skipwhite(argp + 1); /* skip the '(' or ',' */
if (*argp == ')' || *argp == ',' || *argp == NUL)
@@ -8595,7 +8639,7 @@ get_func_tv(
if (ret == OK)
ret = call_func(name, len, rettv, argcount, argvars,
firstline, lastline, doesrange, evaluate, selfdict);
firstline, lastline, doesrange, evaluate, partial, selfdict);
else if (!aborting())
{
if (argcount == MAX_FUNC_ARGS)
@@ -8622,14 +8666,15 @@ call_func(
char_u *funcname, /* name of the function */
int len, /* length of "name" */
typval_T *rettv, /* return value goes here */
int argcount, /* number of "argvars" */
typval_T *argvars, /* vars for arguments, must have "argcount"
int argcount_in, /* number of "argvars" */
typval_T *argvars_in, /* vars for arguments, must have "argcount"
PLUS ONE elements! */
linenr_T firstline, /* first line of range */
linenr_T lastline, /* last line of range */
int *doesrange, /* return: function handled range */
int evaluate,
dict_T *selfdict) /* Dictionary for "self" */
partial_T *partial, /* optional, can be NULL */
dict_T *selfdict_in) /* Dictionary for "self" */
{
int ret = FAIL;
#define ERROR_UNKNOWN 0
@@ -8639,6 +8684,7 @@ call_func(
#define ERROR_DICT 4
#define ERROR_NONE 5
#define ERROR_OTHER 6
#define ERROR_BOTH 7
int error = ERROR_NONE;
int i;
int llen;
@@ -8647,6 +8693,11 @@ call_func(
char_u fname_buf[FLEN_FIXED + 1];
char_u *fname;
char_u *name;
int argcount = argcount_in;
typval_T *argvars = argvars_in;
dict_T *selfdict = selfdict_in;
typval_T argv[MAX_FUNC_ARGS + 1]; /* used when "partial" is not NULL */
int argv_clear = 0;
/* Make a copy of the name, if it comes from a funcref variable it could
* be changed or deleted in the called function. */
@@ -8698,6 +8749,27 @@ call_func(
*doesrange = FALSE;
if (partial != NULL)
{
if (partial->pt_dict != NULL)
{
if (selfdict_in != NULL)
error = ERROR_BOTH;
selfdict = partial->pt_dict;
}
if (error == ERROR_NONE && partial->pt_argc > 0)
{
int i;
for (argv_clear = 0; argv_clear < partial->pt_argc; ++argv_clear)
copy_tv(&partial->pt_argv[argv_clear], &argv[argv_clear]);
for (i = 0; i < argcount_in; ++i)
argv[i + argv_clear] = argvars_in[i];
argvars = argv;
argcount = partial->pt_argc + argcount_in;
}
}
/* execute the function if no errors detected and executing */
if (evaluate && error == ERROR_NONE)
@@ -8841,9 +8913,15 @@ call_func(
emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
name);
break;
case ERROR_BOTH:
emsg_funcname(N_("E924: can't have both a \"self\" dict and a partial: %s"),
name);
break;
}
}
while (argv_clear > 0)
clear_tv(&argv[--argv_clear]);
if (fname != name && fname != fname_buf)
vim_free(fname);
vim_free(name);
@@ -9737,6 +9815,7 @@ f_byteidxcomp(typval_T *argvars, typval_T *rettv)
func_call(
char_u *name,
typval_T *args,
partial_T *partial,
dict_T *selfdict,
typval_T *rettv)
{
@@ -9749,7 +9828,7 @@ func_call(
for (item = args->vval.v_list->lv_first; item != NULL;
item = item->li_next)
{
if (argc == MAX_FUNC_ARGS)
if (argc == MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc))
{
EMSG(_("E699: Too many arguments"));
break;
@@ -9763,7 +9842,7 @@ func_call(
if (item == NULL)
r = call_func(name, (int)STRLEN(name), rettv, argc, argv,
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&dummy, TRUE, selfdict);
&dummy, TRUE, partial, selfdict);
/* Free the arguments. */
while (argc > 0)
@@ -9773,12 +9852,13 @@ func_call(
}
/*
* "call(func, arglist)" function
* "call(func, arglist [, dict])" function
*/
static void
f_call(typval_T *argvars, typval_T *rettv)
{
char_u *func;
partial_T *partial = NULL;
dict_T *selfdict = NULL;
if (argvars[1].v_type != VAR_LIST)
@@ -9791,6 +9871,11 @@ f_call(typval_T *argvars, typval_T *rettv)
if (argvars[0].v_type == VAR_FUNC)
func = argvars[0].vval.v_string;
else if (argvars[0].v_type == VAR_PARTIAL)
{
partial = argvars[0].vval.v_partial;
func = partial->pt_name;
}
else
func = get_tv_string(&argvars[0]);
if (*func == NUL)
@@ -9806,7 +9891,7 @@ f_call(typval_T *argvars, typval_T *rettv)
selfdict = argvars[2].vval.v_dict;
}
(void)func_call(func, &argvars[1], selfdict, rettv);
(void)func_call(func, &argvars[1], partial, selfdict, rettv);
}
#ifdef FEAT_FLOAT
@@ -10627,6 +10712,9 @@ f_empty(typval_T *argvars, typval_T *rettv)
n = argvars[0].vval.v_string == NULL
|| *argvars[0].vval.v_string == NUL;
break;
case VAR_PARTIAL:
n = FALSE;
break;
case VAR_NUMBER:
n = argvars[0].vval.v_number == 0;
break;
@@ -11688,6 +11776,7 @@ f_foreground(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
f_function(typval_T *argvars, typval_T *rettv)
{
char_u *s;
char_u *name;
s = get_tv_string(&argvars[0]);
if (s == NULL || *s == NUL || VIM_ISDIGIT(*s))
@@ -11707,20 +11796,120 @@ f_function(typval_T *argvars, typval_T *rettv)
* would also work, but some plugins depend on the name being
* printable text. */
sprintf(sid_buf, "<SNR>%ld_", (long)current_SID);
rettv->vval.v_string =
alloc((int)(STRLEN(sid_buf) + STRLEN(s + off) + 1));
if (rettv->vval.v_string != NULL)
name = alloc((int)(STRLEN(sid_buf) + STRLEN(s + off) + 1));
if (name != NULL)
{
STRCPY(rettv->vval.v_string, sid_buf);
STRCAT(rettv->vval.v_string, s + off);
STRCPY(name, sid_buf);
STRCAT(name, s + off);
}
}
else
rettv->vval.v_string = vim_strsave(s);
rettv->v_type = VAR_FUNC;
name = vim_strsave(s);
if (argvars[1].v_type != VAR_UNKNOWN)
{
partial_T *pt;
int dict_idx = 0;
int arg_idx = 0;
if (argvars[2].v_type != VAR_UNKNOWN)
{
/* function(name, [args], dict) */
arg_idx = 1;
dict_idx = 2;
}
else if (argvars[1].v_type == VAR_DICT)
/* function(name, dict) */
dict_idx = 1;
else
/* function(name, [args]) */
arg_idx = 1;
if (dict_idx > 0 && (argvars[dict_idx].v_type != VAR_DICT
|| argvars[dict_idx].vval.v_dict == NULL))
{
EMSG(_("E922: expected a dict"));
vim_free(name);
return;
}
if (arg_idx > 0 && (argvars[arg_idx].v_type != VAR_LIST
|| argvars[arg_idx].vval.v_list == NULL))
{
EMSG(_("E923: Second argument of function() must be a list or a dict"));
vim_free(name);
return;
}
pt = (partial_T *)alloc_clear(sizeof(partial_T));
if (pt != NULL)
{
if (arg_idx > 0)
{
list_T *list = argvars[arg_idx].vval.v_list;
listitem_T *li;
int i = 0;
pt->pt_argv = (typval_T *)alloc(
sizeof(typval_T) * list->lv_len);
if (pt->pt_argv == NULL)
{
vim_free(pt);
vim_free(name);
return;
}
else
{
pt->pt_argc = list->lv_len;
for (li = list->lv_first; li != NULL; li = li->li_next)
copy_tv(&li->li_tv, &pt->pt_argv[i++]);
}
}
if (dict_idx > 0)
{
pt->pt_dict = argvars[dict_idx].vval.v_dict;
++pt->pt_dict->dv_refcount;
}
pt->pt_refcount = 1;
pt->pt_name = name;
func_ref(pt->pt_name);
}
rettv->v_type = VAR_PARTIAL;
rettv->vval.v_partial = pt;
}
else
{
rettv->v_type = VAR_FUNC;
rettv->vval.v_string = name;
func_ref(name);
}
}
}
static void
partial_free(partial_T *pt)
{
int i;
for (i = 0; i < pt->pt_argc; ++i)
clear_tv(&pt->pt_argv[i]);
vim_free(pt->pt_argv);
func_unref(pt->pt_name);
vim_free(pt->pt_name);
vim_free(pt);
}
/*
* Unreference a closure: decrement the reference count and free it when it
* becomes zero.
*/
void
partial_unref(partial_T *pt)
{
if (pt != NULL && --pt->pt_refcount <= 0)
partial_free(pt);
}
/*
* "garbagecollect()" function
*/
@@ -14598,6 +14787,7 @@ f_len(typval_T *argvars, typval_T *rettv)
case VAR_SPECIAL:
case VAR_FLOAT:
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_JOB:
case VAR_CHANNEL:
EMSG(_("E701: Invalid type for len()"));
@@ -18169,6 +18359,7 @@ typedef struct
int item_compare_float;
#endif
char_u *item_compare_func;
partial_T *item_compare_partial;
dict_T *item_compare_selfdict;
int item_compare_func_err;
int item_compare_keep_zero;
@@ -18278,6 +18469,8 @@ item_compare2(const void *s1, const void *s2)
typval_T rettv;
typval_T argv[3];
int dummy;
char_u *func_name;
partial_T *partial = sortinfo->item_compare_partial;
/* shortcut after failure in previous call; compare all items equal */
if (sortinfo->item_compare_func_err)
@@ -18286,16 +18479,20 @@ item_compare2(const void *s1, const void *s2)
si1 = (sortItem_T *)s1;
si2 = (sortItem_T *)s2;
if (partial == NULL)
func_name = sortinfo->item_compare_func;
else
func_name = partial->pt_name;
/* Copy the values. This is needed to be able to set v_lock to VAR_FIXED
* in the copy without changing the original list items. */
copy_tv(&si1->item->li_tv, &argv[0]);
copy_tv(&si2->item->li_tv, &argv[1]);
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
res = call_func(sortinfo->item_compare_func,
(int)STRLEN(sortinfo->item_compare_func),
res = call_func(func_name, (int)STRLEN(func_name),
&rettv, 2, argv, 0L, 0L, &dummy, TRUE,
sortinfo->item_compare_selfdict);
partial, sortinfo->item_compare_selfdict);
clear_tv(&argv[0]);
clear_tv(&argv[1]);
@@ -18358,12 +18555,15 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
info.item_compare_float = FALSE;
#endif
info.item_compare_func = NULL;
info.item_compare_partial = NULL;
info.item_compare_selfdict = NULL;
if (argvars[1].v_type != VAR_UNKNOWN)
{
/* optional second argument: {func} */
if (argvars[1].v_type == VAR_FUNC)
info.item_compare_func = argvars[1].vval.v_string;
else if (argvars[1].v_type == VAR_PARTIAL)
info.item_compare_partial = argvars[1].vval.v_partial;
else
{
int error = FALSE;
@@ -18443,7 +18643,8 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
info.item_compare_func_err = FALSE;
info.item_compare_keep_zero = FALSE;
/* test the compare function */
if (info.item_compare_func != NULL
if ((info.item_compare_func != NULL
|| info.item_compare_partial != NULL)
&& item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
== ITEM_COMPARE_FAIL)
EMSG(_("E702: Sort compare function failed"));
@@ -18452,6 +18653,7 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
/* Sort the array with item pointers. */
qsort((void *)ptrs, (size_t)len, sizeof(sortItem_T),
info.item_compare_func == NULL
&& info.item_compare_partial == NULL
? item_compare : item_compare2);
if (!info.item_compare_func_err)
@@ -18471,7 +18673,8 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
/* f_uniq(): ptrs will be a stack of items to remove */
info.item_compare_func_err = FALSE;
info.item_compare_keep_zero = TRUE;
item_compare_func_ptr = info.item_compare_func
item_compare_func_ptr = info.item_compare_func != NULL
|| info.item_compare_partial != NULL
? item_compare2 : item_compare;
for (li = l->lv_first; li != NULL && li->li_next != NULL;
@@ -20045,6 +20248,7 @@ f_type(typval_T *argvars, typval_T *rettv)
break;
case VAR_JOB: n = 8; break;
case VAR_CHANNEL: n = 9; break;
case VAR_PARTIAL: n = 10; break;
case VAR_UNKNOWN:
EMSG2(_(e_intern2), "f_type(UNKNOWN)");
n = -1;
@@ -21295,11 +21499,13 @@ handle_subscript(
char_u *s;
int len;
typval_T functv;
partial_T *pt = NULL;
while (ret == OK
&& (**arg == '['
|| (**arg == '.' && rettv->v_type == VAR_DICT)
|| (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC)))
|| (**arg == '(' && (!evaluate || rettv->v_type == VAR_FUNC
|| rettv->v_type == VAR_PARTIAL)))
&& !vim_iswhite(*(*arg - 1)))
{
if (**arg == '(')
@@ -21311,13 +21517,19 @@ handle_subscript(
rettv->v_type = VAR_UNKNOWN;
/* Invoke the function. Recursive! */
s = functv.vval.v_string;
if (rettv->v_type == VAR_PARTIAL)
{
pt = functv.vval.v_partial;
s = pt->pt_name;
}
else
s = functv.vval.v_string;
}
else
s = (char_u *)"";
ret = get_func_tv(s, (int)STRLEN(s), rettv, arg,
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&len, evaluate, selfdict);
&len, evaluate, pt, selfdict);
/* Clear the funcref afterwards, so that deleting it while
* evaluating the arguments is possible (see test55). */
@@ -21405,6 +21617,9 @@ free_tv(typval_T *varp)
case VAR_STRING:
vim_free(varp->vval.v_string);
break;
case VAR_PARTIAL:
partial_unref(varp->vval.v_partial);
break;
case VAR_LIST:
list_unref(varp->vval.v_list);
break;
@@ -21448,6 +21663,10 @@ clear_tv(typval_T *varp)
vim_free(varp->vval.v_string);
varp->vval.v_string = NULL;
break;
case VAR_PARTIAL:
partial_unref(varp->vval.v_partial);
varp->vval.v_partial = NULL;
break;
case VAR_LIST:
list_unref(varp->vval.v_list);
varp->vval.v_list = NULL;
@@ -21524,6 +21743,7 @@ get_tv_number_chk(typval_T *varp, int *denote)
break;
#endif
case VAR_FUNC:
case VAR_PARTIAL:
EMSG(_("E703: Using a Funcref as a Number"));
break;
case VAR_STRING:
@@ -21572,6 +21792,7 @@ get_tv_float(typval_T *varp)
case VAR_FLOAT:
return varp->vval.v_float;
case VAR_FUNC:
case VAR_PARTIAL:
EMSG(_("E891: Using a Funcref as a Float"));
break;
case VAR_STRING:
@@ -21688,6 +21909,7 @@ get_tv_string_buf_chk(typval_T *varp, char_u *buf)
sprintf((char *)buf, "%ld", (long)varp->vval.v_number);
return buf;
case VAR_FUNC:
case VAR_PARTIAL:
EMSG(_("E729: using Funcref as a String"));
break;
case VAR_LIST:
@@ -22087,7 +22309,7 @@ list_one_var_a(
msg_advance(22);
if (type == VAR_NUMBER)
msg_putchar('#');
else if (type == VAR_FUNC)
else if (type == VAR_FUNC || type == VAR_PARTIAL)
msg_putchar('*');
else if (type == VAR_LIST)
{
@@ -22106,7 +22328,7 @@ list_one_var_a(
msg_outtrans(string);
if (type == VAR_FUNC)
if (type == VAR_FUNC || type == VAR_PARTIAL)
msg_puts((char_u *)"()");
if (*first)
{
@@ -22138,7 +22360,8 @@ set_var(
}
v = find_var_in_ht(ht, 0, varname, TRUE);
if (tv->v_type == VAR_FUNC && var_check_func_name(name, v == NULL))
if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
&& var_check_func_name(name, v == NULL))
return;
if (v != NULL)
@@ -22383,6 +22606,15 @@ copy_tv(typval_T *from, typval_T *to)
func_ref(to->vval.v_string);
}
break;
case VAR_PARTIAL:
if (from->vval.v_partial == NULL)
to->vval.v_partial = NULL;
else
{
to->vval.v_partial = from->vval.v_partial;
++to->vval.v_partial->pt_refcount;
}
break;
case VAR_LIST:
if (from->vval.v_list == NULL)
to->vval.v_list = NULL;
@@ -22437,6 +22669,7 @@ item_copy(
case VAR_FLOAT:
case VAR_STRING:
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_SPECIAL:
case VAR_JOB:
case VAR_CHANNEL:
@@ -23415,6 +23648,7 @@ trans_function_name(
char_u sid_buf[20];
int len;
lval_T lv;
partial_T *partial;
if (fdp != NULL)
vim_memset(fdp, 0, sizeof(funcdict_T));
@@ -23499,14 +23733,15 @@ trans_function_name(
if (lv.ll_exp_name != NULL)
{
len = (int)STRLEN(lv.ll_exp_name);
name = deref_func_name(lv.ll_exp_name, &len, flags & TFN_NO_AUTOLOAD);
name = deref_func_name(lv.ll_exp_name, &len, &partial,
flags & TFN_NO_AUTOLOAD);
if (name == lv.ll_exp_name)
name = NULL;
}
else
{
len = (int)(end - *pp);
name = deref_func_name(*pp, &len, flags & TFN_NO_AUTOLOAD);
name = deref_func_name(*pp, &len, &partial, flags & TFN_NO_AUTOLOAD);
if (name == *pp)
name = NULL;
}
@@ -25111,6 +25346,7 @@ write_viminfo_varlist(FILE *fp)
case VAR_UNKNOWN:
case VAR_FUNC:
case VAR_PARTIAL:
case VAR_JOB:
case VAR_CHANNEL:
continue;