diff options
author | Michael Ennen <mike.ennen@gmail.com> | 2016-10-28 12:38:36 -0700 |
---|---|---|
committer | James McCoy <jamessan@jamessan.com> | 2016-12-12 10:17:35 -0500 |
commit | c82dc7a6fd4987fee72320133579b008815b28d1 (patch) | |
tree | 26768dfc53a53eb1070d577cedb7459894feeab1 | |
parent | eb337c9949d679eeb9f0995963c639fdf7772fd4 (diff) | |
download | rneovim-c82dc7a6fd4987fee72320133579b008815b28d1.tar.gz rneovim-c82dc7a6fd4987fee72320133579b008815b28d1.tar.bz2 rneovim-c82dc7a6fd4987fee72320133579b008815b28d1.zip |
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.
https://github.com/vim/vim/commit/1d429610bf9e99a6252be8abbc910d6667e4d1da
-rw-r--r-- | runtime/doc/eval.txt | 41 | ||||
-rw-r--r-- | src/nvim/eval.c | 30 | ||||
-rw-r--r-- | src/nvim/eval_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/version.c | 3 |
4 files changed, 63 insertions, 13 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index f377ebdf31..133f35990c 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,6 +1,5 @@ *eval.txt* For Vim version 7.4. Last change: 2016 Jun 04 - 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|. 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|. 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 arguments: > :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 ~ diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 2888ddc82d..14e6003ca0 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7099,12 +7099,11 @@ call_func( *doesrange = FALSE; if (partial != NULL) { - if (partial->pt_dict != NULL) { - // When the function has a partial with a dict and there is a dict - // argument, use the dict argument. That is backwards compatible. - if (selfdict_in == NULL) { - selfdict = partial->pt_dict; - } + // When the function has a partial with a dict and there is a dict + // argument, use the dict argument. That is backwards compatible. + // When the dict was bound explicitly use the one from the partial. + if (partial->pt_dict != NULL + && (selfdict_in == NULL || !partial->pt_auto)) { selfdict = partial->pt_dict; } 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 // use "dict". That is backwards compatible. if (dict_idx > 0) { - pt->pt_dict = argvars[dict_idx].vval.v_dict; - (pt->pt_dict->dv_refcount)++; + // The dict is bound explicitly, pt_auto is false + pt->pt_dict = argvars[dict_idx].vval.v_dict; + (pt->pt_dict->dv_refcount)++; } 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_auto = arg_pt->pt_auto; if (pt->pt_dict != NULL) { (pt->pt_dict->dv_refcount)++; } @@ -18424,8 +18427,14 @@ handle_subscript ( } } - if ((rettv->v_type == VAR_FUNC || rettv->v_type == VAR_PARTIAL) - && selfdict != NULL) { + // Turn "dict.Func" into a partial for "Func" bound to "dict". + // 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 : rettv->vval.v_partial->pt_name; char_u *tofree = NULL; @@ -18446,6 +18455,7 @@ handle_subscript ( if (pt != NULL) { pt->pt_refcount = 1; pt->pt_dict = selfdict; + pt->pt_auto = true; selfdict = NULL; if (rettv->v_type == VAR_FUNC) { // Just a function: Take over the function name and use diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h index a33ac10e61..74d0782356 100644 --- a/src/nvim/eval_defs.h +++ b/src/nvim/eval_defs.h @@ -150,6 +150,8 @@ struct dictvar_S { struct partial_S { int pt_refcount; ///< Reference count. 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. typval_T *pt_argv; ///< Arguments in allocated array. dict_T *pt_dict; ///< Dict for "self". diff --git a/src/nvim/version.c b/src/nvim/version.c index f091b12810..88c0185f57 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -604,9 +604,8 @@ static int included_patches[] = { // 1839, // 1838, // 1837, - // 1836, + 1836, 1835, - // 1834, 1833, 1832, 1831, |