mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:7.4.1836
Problem: When using a partial on a dictionary it always gets bound to that
dictionary.
Solution: Make a difference between binding a function to a dictionary
explicitly or automatically.
1d429610bf
This commit is contained in:
parent
eb337c9949
commit
c82dc7a6fd
@ -1,6 +1,5 @@
|
|||||||
*eval.txt* For Vim version 7.4. Last change: 2016 Jun 04
|
*eval.txt* For Vim version 7.4. Last change: 2016 Jun 04
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
|
|
||||||
|
|
||||||
@ -49,6 +48,9 @@ String A NUL terminated string of 8-bit unsigned characters (bytes).
|
|||||||
|
|
||||||
Funcref A reference to a function |Funcref|.
|
Funcref A reference to a function |Funcref|.
|
||||||
Example: function("strlen")
|
Example: function("strlen")
|
||||||
|
It can be bound to a dictionary and arguments, it then works
|
||||||
|
like a Partial.
|
||||||
|
Example: function("Callback", [arg], myDict)
|
||||||
|
|
||||||
List An ordered sequence of items |List|.
|
List An ordered sequence of items |List|.
|
||||||
Example: [1, 2, ['a', 'b']]
|
Example: [1, 2, ['a', 'b']]
|
||||||
@ -139,6 +141,43 @@ The name of the referenced function can be obtained with |string()|. >
|
|||||||
You can use |call()| to invoke a Funcref and use a list variable for the
|
You can use |call()| to invoke a Funcref and use a list variable for the
|
||||||
arguments: >
|
arguments: >
|
||||||
:let r = call(Fn, mylist)
|
:let r = call(Fn, mylist)
|
||||||
|
<
|
||||||
|
*Partial*
|
||||||
|
A Funcref optionally binds a Dictionary and/or arguments. This is also called
|
||||||
|
a Partial. This is created by passing the Dictionary and/or arguments to
|
||||||
|
function(). When calling the function the Dictionary and/or arguments will be
|
||||||
|
passed to the function. Example: >
|
||||||
|
|
||||||
|
let Cb = function('Callback', ['foo'], myDict)
|
||||||
|
call Cb()
|
||||||
|
|
||||||
|
This will invoke the function as if using: >
|
||||||
|
call myDict.Callback('foo')
|
||||||
|
|
||||||
|
This is very useful when passing a function around, e.g. in the arguments of
|
||||||
|
|ch_open()|.
|
||||||
|
|
||||||
|
Note that binding a function to a Dictionary also happens when the function is
|
||||||
|
a member of the Dictionary: >
|
||||||
|
|
||||||
|
let myDict.myFunction = MyFunction
|
||||||
|
call myDict.myFunction()
|
||||||
|
|
||||||
|
Here MyFunction() will get myDict passed as "self". This happens when the
|
||||||
|
"myFunction" member is accessed. When making assigning "myFunction" to
|
||||||
|
otherDict and calling it, it will be bound to otherDict: >
|
||||||
|
|
||||||
|
let otherDict.myFunction = myDict.myFunction
|
||||||
|
call otherDict.myFunction()
|
||||||
|
|
||||||
|
Now "self" will be "otherDict". But when the dictionary was bound explicitly
|
||||||
|
this won't happen: >
|
||||||
|
|
||||||
|
let myDict.myFunction = function(MyFunction, myDict)
|
||||||
|
let otherDict.myFunction = myDict.myFunction
|
||||||
|
call otherDict.myFunction()
|
||||||
|
|
||||||
|
Here "self" will be "myDict", because it was bound explitly.
|
||||||
|
|
||||||
|
|
||||||
1.3 Lists ~
|
1.3 Lists ~
|
||||||
|
@ -7099,12 +7099,11 @@ call_func(
|
|||||||
*doesrange = FALSE;
|
*doesrange = FALSE;
|
||||||
|
|
||||||
if (partial != NULL) {
|
if (partial != NULL) {
|
||||||
if (partial->pt_dict != NULL) {
|
// When the function has a partial with a dict and there is a dict
|
||||||
// When the function has a partial with a dict and there is a dict
|
// argument, use the dict argument. That is backwards compatible.
|
||||||
// argument, use the dict argument. That is backwards compatible.
|
// When the dict was bound explicitly use the one from the partial.
|
||||||
if (selfdict_in == NULL) {
|
if (partial->pt_dict != NULL
|
||||||
selfdict = partial->pt_dict;
|
&& (selfdict_in == NULL || !partial->pt_auto)) {
|
||||||
}
|
|
||||||
selfdict = partial->pt_dict;
|
selfdict = partial->pt_dict;
|
||||||
}
|
}
|
||||||
if (error == ERROR_NONE && partial->pt_argc > 0) {
|
if (error == ERROR_NONE && partial->pt_argc > 0) {
|
||||||
@ -9643,10 +9642,14 @@ static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
// For "function(dict.func, [], dict)" and "func" is a partial
|
// For "function(dict.func, [], dict)" and "func" is a partial
|
||||||
// use "dict". That is backwards compatible.
|
// use "dict". That is backwards compatible.
|
||||||
if (dict_idx > 0) {
|
if (dict_idx > 0) {
|
||||||
pt->pt_dict = argvars[dict_idx].vval.v_dict;
|
// The dict is bound explicitly, pt_auto is false
|
||||||
(pt->pt_dict->dv_refcount)++;
|
pt->pt_dict = argvars[dict_idx].vval.v_dict;
|
||||||
|
(pt->pt_dict->dv_refcount)++;
|
||||||
} else if (arg_pt != NULL) {
|
} else if (arg_pt != NULL) {
|
||||||
|
// If the dict was bound automatically the result is also
|
||||||
|
// bound automatically.
|
||||||
pt->pt_dict = arg_pt->pt_dict;
|
pt->pt_dict = arg_pt->pt_dict;
|
||||||
|
pt->pt_auto = arg_pt->pt_auto;
|
||||||
if (pt->pt_dict != NULL) {
|
if (pt->pt_dict != NULL) {
|
||||||
(pt->pt_dict->dv_refcount)++;
|
(pt->pt_dict->dv_refcount)++;
|
||||||
}
|
}
|
||||||
@ -18424,8 +18427,14 @@ handle_subscript (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rettv->v_type == VAR_FUNC || rettv->v_type == VAR_PARTIAL)
|
// Turn "dict.Func" into a partial for "Func" bound to "dict".
|
||||||
&& selfdict != NULL) {
|
// Don't do this when "Func" is already a partial that was bound
|
||||||
|
// explicitly (pt_auto is false).
|
||||||
|
if (self != NULL
|
||||||
|
&& (rettv->v_type == VAR_FUNC
|
||||||
|
|| (rettv->v_type == VAR_PARTIAL
|
||||||
|
&& (rettv->vval.v_partial->pt_auto
|
||||||
|
|| rettv->vval.v_partial->pt_dict == NULL)))) {
|
||||||
char_u *fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
|
char_u *fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
|
||||||
: rettv->vval.v_partial->pt_name;
|
: rettv->vval.v_partial->pt_name;
|
||||||
char_u *tofree = NULL;
|
char_u *tofree = NULL;
|
||||||
@ -18446,6 +18455,7 @@ handle_subscript (
|
|||||||
if (pt != NULL) {
|
if (pt != NULL) {
|
||||||
pt->pt_refcount = 1;
|
pt->pt_refcount = 1;
|
||||||
pt->pt_dict = selfdict;
|
pt->pt_dict = selfdict;
|
||||||
|
pt->pt_auto = true;
|
||||||
selfdict = NULL;
|
selfdict = NULL;
|
||||||
if (rettv->v_type == VAR_FUNC) {
|
if (rettv->v_type == VAR_FUNC) {
|
||||||
// Just a function: Take over the function name and use
|
// Just a function: Take over the function name and use
|
||||||
|
@ -150,6 +150,8 @@ struct dictvar_S {
|
|||||||
struct partial_S {
|
struct partial_S {
|
||||||
int pt_refcount; ///< Reference count.
|
int pt_refcount; ///< Reference count.
|
||||||
char_u *pt_name; ///< Function name.
|
char_u *pt_name; ///< Function name.
|
||||||
|
bool pt_auto; ///< when true the partial was created for using
|
||||||
|
///< dict.member in handle_subscript().
|
||||||
int pt_argc; ///< Number of arguments.
|
int pt_argc; ///< Number of arguments.
|
||||||
typval_T *pt_argv; ///< Arguments in allocated array.
|
typval_T *pt_argv; ///< Arguments in allocated array.
|
||||||
dict_T *pt_dict; ///< Dict for "self".
|
dict_T *pt_dict; ///< Dict for "self".
|
||||||
|
@ -604,9 +604,8 @@ static int included_patches[] = {
|
|||||||
// 1839,
|
// 1839,
|
||||||
// 1838,
|
// 1838,
|
||||||
// 1837,
|
// 1837,
|
||||||
// 1836,
|
1836,
|
||||||
1835,
|
1835,
|
||||||
// 1834,
|
|
||||||
1833,
|
1833,
|
||||||
1832,
|
1832,
|
||||||
1831,
|
1831,
|
||||||
|
Loading…
Reference in New Issue
Block a user