Patch 7.4.2137
Problem:    Using function() with a name will find another function when it is
            redefined.
Solution:   Add funcref().  Refer to lambda using a partial.  Fix several
            reference counting issues.
Files:      src/vim.h, src/structs.h, src/userfunc.c, src/eval.c,
            src/evalfunc.c, src/channel.c, src/proto/eval.pro,
            src/proto/userfunc.pro, src/if_mzsch.c, src/regexp.c, src/misc2.c,
            src/if_py_both.h, src/testdir/test_lambda.vim,
            src/testdir/test_expr.vim, runtime/doc/eval.txt


*** ../vim-7.4.2136/src/vim.h   2016-07-31 14:11:55.178542370 +0200
--- src/vim.h   2016-07-31 20:50:02.276310616 +0200
***************
*** 2475,2480 ****
--- 2475,2481 ----
  #define ERROR_DICT    4
  #define ERROR_NONE    5
  #define ERROR_OTHER   6
+ #define ERROR_DELETED 7
  
  /* flags for find_name_end() */
  #define FNE_INCL_BR   1       /* include [] in name */
*** ../vim-7.4.2136/src/structs.h       2016-07-22 21:49:36.666031534 +0200
--- src/structs.h       2016-07-31 21:51:09.928269249 +0200
***************
*** 1295,1304 ****
      dict_T    *dv_used_prev;  /* previous dict in used dicts list */
  };
  
  struct partial_S
  {
      int               pt_refcount;    /* reference count */
!     char_u    *pt_name;       /* function name */
      int               pt_auto;        /* when TRUE the partial was created 
for using
                                   dict.member in handle_subscript() */
      int               pt_argc;        /* number of arguments */
--- 1295,1394 ----
      dict_T    *dv_used_prev;  /* previous dict in used dicts list */
  };
  
+ #if defined(FEAT_EVAL) || defined(PROTO)
+ typedef struct funccall_S funccall_T;
+ 
+ /*
+  * Structure to hold info for a user function.
+  */
+ typedef struct
+ {
+     int               uf_varargs;     /* variable nr of arguments */
+     int               uf_flags;
+     int               uf_calls;       /* nr of active calls */
+     garray_T  uf_args;        /* arguments */
+     garray_T  uf_lines;       /* function lines */
+ #ifdef FEAT_PROFILE
+     int               uf_profiling;   /* TRUE when func is being profiled */
+     /* profiling the function as a whole */
+     int               uf_tm_count;    /* nr of calls */
+     proftime_T        uf_tm_total;    /* time spent in function + children */
+     proftime_T        uf_tm_self;     /* time spent in function itself */
+     proftime_T        uf_tm_children; /* time spent in children this call */
+     /* profiling the function per line */
+     int               *uf_tml_count;  /* nr of times line was executed */
+     proftime_T        *uf_tml_total;  /* time spent in a line + children */
+     proftime_T        *uf_tml_self;   /* time spent in a line itself */
+     proftime_T        uf_tml_start;   /* start time for current line */
+     proftime_T        uf_tml_children; /* time spent in children for this 
line */
+     proftime_T        uf_tml_wait;    /* start wait time for current line */
+     int               uf_tml_idx;     /* index of line being timed; -1 if 
none */
+     int               uf_tml_execed;  /* line being timed was executed */
+ #endif
+     scid_T    uf_script_ID;   /* ID of script where function was defined,
+                                  used for s: variables */
+     int               uf_refcount;    /* for numbered function: reference 
count */
+     funccall_T        *uf_scoped;     /* l: local variables for closure */
+     char_u    uf_name[1];     /* name of function (actually longer); can
+                                  start with <SNR>123_ (<SNR> is K_SPECIAL
+                                  KS_EXTRA KE_SNR) */
+ } ufunc_T;
+ 
+ #define MAX_FUNC_ARGS 20      /* maximum number of function arguments */
+ #define VAR_SHORT_LEN 20      /* short variable name length */
+ #define FIXVAR_CNT    12      /* number of fixed variables */
+ 
+ /* structure to hold info for a function that is currently being executed. */
+ struct funccall_S
+ {
+     ufunc_T   *func;          /* function being called */
+     int               linenr;         /* next line to be executed */
+     int               returned;       /* ":return" used */
+     struct                    /* fixed variables for arguments */
+     {
+       dictitem_T      var;            /* variable (without room for name) */
+       char_u  room[VAR_SHORT_LEN];    /* room for the name */
+     } fixvar[FIXVAR_CNT];
+     dict_T    l_vars;         /* l: local function variables */
+     dictitem_T        l_vars_var;     /* variable for l: scope */
+     dict_T    l_avars;        /* a: argument variables */
+     dictitem_T        l_avars_var;    /* variable for a: scope */
+     list_T    l_varlist;      /* list for a:000 */
+     listitem_T        l_listitems[MAX_FUNC_ARGS];     /* listitems for a:000 
*/
+     typval_T  *rettv;         /* return value */
+     linenr_T  breakpoint;     /* next line with breakpoint or zero */
+     int               dbg_tick;       /* debug_tick when breakpoint was set */
+     int               level;          /* top nesting level of executed 
function */
+ #ifdef FEAT_PROFILE
+     proftime_T        prof_child;     /* time spent in a child */
+ #endif
+     funccall_T        *caller;        /* calling function or NULL */
+ 
+     /* for closure */
+     int               fc_refcount;
+     int               fc_copyID;      /* for garbage collection */
+     garray_T  fc_funcs;       /* list of ufunc_T* which refer this */
+ };
+ 
+ /*
+  * Struct used by trans_function_name()
+  */
+ typedef struct
+ {
+     dict_T    *fd_dict;       /* Dictionary used */
+     char_u    *fd_newkey;     /* new key in "dict" in allocated memory */
+     dictitem_T        *fd_di;         /* Dictionary item used */
+ } funcdict_T;
+ 
+ #endif
+ 
  struct partial_S
  {
      int               pt_refcount;    /* reference count */
!     char_u    *pt_name;       /* function name; when NULL use
!                                * pt_func->uf_name */
!     ufunc_T   *pt_func;       /* function pointer; when NULL lookup function
!                                * with pt_name */
      int               pt_auto;        /* when TRUE the partial was created 
for using
                                   dict.member in handle_subscript() */
      int               pt_argc;        /* number of arguments */
*** ../vim-7.4.2136/src/userfunc.c      2016-07-31 18:30:19.037018267 +0200
--- src/userfunc.c      2016-08-01 13:06:05.408001028 +0200
***************
*** 14,65 ****
  #include "vim.h"
  
  #if defined(FEAT_EVAL) || defined(PROTO)
- 
- typedef struct funccall_S funccall_T;
- 
- /*
-  * Structure to hold info for a user function.
-  */
- typedef struct ufunc ufunc_T;
- 
- struct ufunc
- {
-     int               uf_varargs;     /* variable nr of arguments */
-     int               uf_flags;
-     int               uf_calls;       /* nr of active calls */
-     garray_T  uf_args;        /* arguments */
-     garray_T  uf_lines;       /* function lines */
- #ifdef FEAT_PROFILE
-     int               uf_profiling;   /* TRUE when func is being profiled */
-     /* profiling the function as a whole */
-     int               uf_tm_count;    /* nr of calls */
-     proftime_T        uf_tm_total;    /* time spent in function + children */
-     proftime_T        uf_tm_self;     /* time spent in function itself */
-     proftime_T        uf_tm_children; /* time spent in children this call */
-     /* profiling the function per line */
-     int               *uf_tml_count;  /* nr of times line was executed */
-     proftime_T        *uf_tml_total;  /* time spent in a line + children */
-     proftime_T        *uf_tml_self;   /* time spent in a line itself */
-     proftime_T        uf_tml_start;   /* start time for current line */
-     proftime_T        uf_tml_children; /* time spent in children for this 
line */
-     proftime_T        uf_tml_wait;    /* start wait time for current line */
-     int               uf_tml_idx;     /* index of line being timed; -1 if 
none */
-     int               uf_tml_execed;  /* line being timed was executed */
- #endif
-     scid_T    uf_script_ID;   /* ID of script where function was defined,
-                                  used for s: variables */
-     int               uf_refcount;    /* for numbered function: reference 
count */
-     funccall_T        *uf_scoped;     /* l: local variables for closure */
-     char_u    uf_name[1];     /* name of function (actually longer); can
-                                  start with <SNR>123_ (<SNR> is K_SPECIAL
-                                  KS_EXTRA KE_SNR) */
- };
- 
  /* function flags */
  #define FC_ABORT    1         /* abort function on error */
  #define FC_RANGE    2         /* function accepts range */
  #define FC_DICT           4           /* Dict function, uses "self" */
  #define FC_CLOSURE  8         /* closure, uses outer scope variables */
  
  /* From user function to hashitem and back. */
  #define UF2HIKEY(fp) ((fp)->uf_name)
--- 14,25 ----
  #include "vim.h"
  
  #if defined(FEAT_EVAL) || defined(PROTO)
  /* function flags */
  #define FC_ABORT    1         /* abort function on error */
  #define FC_RANGE    2         /* function accepts range */
  #define FC_DICT           4           /* Dict function, uses "self" */
  #define FC_CLOSURE  8         /* closure, uses outer scope variables */
+ #define FC_DELETED  16                /* :delfunction used while uf_refcount 
> 0 */
  
  /* From user function to hashitem and back. */
  #define UF2HIKEY(fp) ((fp)->uf_name)
***************
*** 69,120 ****
  #define FUNCARG(fp, j)        ((char_u **)(fp->uf_args.ga_data))[j]
  #define FUNCLINE(fp, j)       ((char_u **)(fp->uf_lines.ga_data))[j]
  
- #define MAX_FUNC_ARGS 20      /* maximum number of function arguments */
- #define VAR_SHORT_LEN 20      /* short variable name length */
- #define FIXVAR_CNT    12      /* number of fixed variables */
- 
- /* structure to hold info for a function that is currently being executed. */
- struct funccall_S
- {
-     ufunc_T   *func;          /* function being called */
-     int               linenr;         /* next line to be executed */
-     int               returned;       /* ":return" used */
-     struct                    /* fixed variables for arguments */
-     {
-       dictitem_T      var;            /* variable (without room for name) */
-       char_u  room[VAR_SHORT_LEN];    /* room for the name */
-     } fixvar[FIXVAR_CNT];
-     dict_T    l_vars;         /* l: local function variables */
-     dictitem_T        l_vars_var;     /* variable for l: scope */
-     dict_T    l_avars;        /* a: argument variables */
-     dictitem_T        l_avars_var;    /* variable for a: scope */
-     list_T    l_varlist;      /* list for a:000 */
-     listitem_T        l_listitems[MAX_FUNC_ARGS];     /* listitems for a:000 
*/
-     typval_T  *rettv;         /* return value */
-     linenr_T  breakpoint;     /* next line with breakpoint or zero */
-     int               dbg_tick;       /* debug_tick when breakpoint was set */
-     int               level;          /* top nesting level of executed 
function */
- #ifdef FEAT_PROFILE
-     proftime_T        prof_child;     /* time spent in a child */
- #endif
-     funccall_T        *caller;        /* calling function or NULL */
- 
-     /* for closure */
-     int               fc_refcount;
-     int               fc_copyID;      /* for garbage collection */
-     garray_T  fc_funcs;       /* list of ufunc_T* which refer this */
- };
- 
- /*
-  * Struct used by trans_function_name()
-  */
- typedef struct
- {
-     dict_T    *fd_dict;       /* Dictionary used */
-     char_u    *fd_newkey;     /* new key in "dict" in allocated memory */
-     dictitem_T        *fd_di;         /* Dictionary item used */
- } funcdict_T;
- 
  /*
   * All user-defined functions are found in this hashtable.
   */
--- 29,34 ----
***************
*** 271,277 ****
        return FAIL;
      ((ufunc_T **)current_funccal->fc_funcs.ga_data)
        [current_funccal->fc_funcs.ga_len++] = fp;
!     func_ref(current_funccal->func->uf_name);
      return OK;
  }
  
--- 185,191 ----
        return FAIL;
      ((ufunc_T **)current_funccal->fc_funcs.ga_data)
        [current_funccal->fc_funcs.ga_len++] = fp;
!     func_ptr_ref(current_funccal->func);
      return OK;
  }
  
***************
*** 288,294 ****
      ufunc_T   *fp = NULL;
      int               varargs;
      int               ret;
-     char_u    name[20];
      char_u    *start = skipwhite(*arg + 1);
      char_u    *s, *e;
      static int        lambda_no = 0;
--- 202,207 ----
***************
*** 331,344 ****
  
      if (evaluate)
      {
!       int     len, flags = 0;
!       char_u  *p;
  
        sprintf((char*)name, "<lambda>%d", ++lambda_no);
  
        fp = (ufunc_T *)alloc_clear((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
        if (fp == NULL)
            goto errret;
  
        ga_init2(&newlines, (int)sizeof(char_u *), 1);
        if (ga_grow(&newlines, 1) == FAIL)
--- 244,265 ----
  
      if (evaluate)
      {
!       int         len, flags = 0;
!       char_u      *p;
!       char_u      name[20];
!       partial_T   *pt;
  
        sprintf((char*)name, "<lambda>%d", ++lambda_no);
  
        fp = (ufunc_T *)alloc_clear((unsigned)(sizeof(ufunc_T) + STRLEN(name)));
        if (fp == NULL)
            goto errret;
+       pt = (partial_T *)alloc_clear((unsigned)sizeof(partial_T));
+       if (pt == NULL)
+       {
+           vim_free(fp);
+           goto errret;
+       }
  
        ga_init2(&newlines, (int)sizeof(char_u *), 1);
        if (ga_grow(&newlines, 1) == FAIL)
***************
*** 380,387 ****
        fp->uf_calls = 0;
        fp->uf_script_ID = current_SID;
  
!       rettv->vval.v_string = vim_strsave(name);
!       rettv->v_type = VAR_FUNC;
      }
  
      eval_lavars_used = old_eval_lavars;
--- 301,310 ----
        fp->uf_calls = 0;
        fp->uf_script_ID = current_SID;
  
!       pt->pt_func = fp;
!       pt->pt_refcount = 1;
!       rettv->vval.v_partial = pt;
!       rettv->v_type = VAR_PARTIAL;
      }
  
      eval_lavars_used = old_eval_lavars;
***************
*** 406,411 ****
--- 329,335 ----
  {
      dictitem_T        *v;
      int               cc;
+     char_u    *s;
  
      if (partialp != NULL)
        *partialp = NULL;
***************
*** 421,428 ****
            *lenp = 0;
            return (char_u *)"";        /* just in case */
        }
!       *lenp = (int)STRLEN(v->di_tv.vval.v_string);
!       return v->di_tv.vval.v_string;
      }
  
      if (v != NULL && v->di_tv.v_type == VAR_PARTIAL)
--- 345,353 ----
            *lenp = 0;
            return (char_u *)"";        /* just in case */
        }
!       s = v->di_tv.vval.v_string;
!       *lenp = (int)STRLEN(s);
!       return s;
      }
  
      if (v != NULL && v->di_tv.v_type == VAR_PARTIAL)
***************
*** 436,443 ****
        }
        if (partialp != NULL)
            *partialp = pt;
!       *lenp = (int)STRLEN(pt->pt_name);
!       return pt->pt_name;
      }
  
      return name;
--- 361,369 ----
        }
        if (partialp != NULL)
            *partialp = pt;
!       s = partial_name(pt);
!       *lenp = (int)STRLEN(s);
!       return s;
      }
  
      return name;
***************
*** 611,617 ****
   * Find a function by name, return pointer to it in ufuncs.
   * Return NULL for unknown function.
   */
!     static ufunc_T *
  find_func(char_u *name)
  {
      hashitem_T        *hi;
--- 537,543 ----
   * Find a function by name, return pointer to it in ufuncs.
   * Return NULL for unknown function.
   */
!     ufunc_T *
  find_func(char_u *name)
  {
      hashitem_T        *hi;
***************
*** 678,684 ****
             * funccall_T, don't clear it then. */
            if (fp->uf_scoped == fc)
                fp->uf_scoped = NULL;
!           func_unref(fc->func->uf_name);
        }
      }
      ga_clear(&fc->fc_funcs);
--- 604,610 ----
             * funccall_T, don't clear it then. */
            if (fp->uf_scoped == fc)
                fp->uf_scoped = NULL;
!           func_ptr_unref(fc->func);
        }
      }
      ga_clear(&fc->fc_funcs);
***************
*** 695,701 ****
        for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
            clear_tv(&li->li_tv);
  
!     func_unref(fc->func->uf_name);
      vim_free(fc);
  }
  
--- 621,627 ----
        for (li = fc->l_varlist.lv_first; li != NULL; li = li->li_next)
            clear_tv(&li->li_tv);
  
!     func_ptr_unref(fc->func);
      vim_free(fc);
  }
  
***************
*** 759,765 ****
      fc->fc_refcount = 0;
      fc->fc_copyID = 0;
      ga_init2(&fc->fc_funcs, sizeof(ufunc_T *), 1);
!     func_ref(fp->uf_name);
  
      if (STRNCMP(fp->uf_name, "<lambda>", 8) == 0)
        islambda = TRUE;
--- 685,691 ----
      fc->fc_refcount = 0;
      fc->fc_copyID = 0;
      ga_init2(&fc->fc_funcs, sizeof(ufunc_T *), 1);
!     func_ptr_ref(fp);
  
      if (STRNCMP(fp->uf_name, "<lambda>", 8) == 0)
        islambda = TRUE;
***************
*** 1112,1135 ****
  
      if (--fc->fc_refcount <= 0)
      {
!       for (pfc = &previous_funccal; *pfc != NULL; )
        {
!           if (fc == *pfc
!                   && fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
                    && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
                    && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
!           {
!               *pfc = fc->caller;
!               free_funccal(fc, TRUE);
!               freed = TRUE;
            }
-           else
-               pfc = &(*pfc)->caller;
        }
      }
      if (!freed)
      {
!       func_unref(fc->func->uf_name);
  
        if (fp != NULL)
            for (i = 0; i < fc->fc_funcs.ga_len; ++i)
--- 1038,1062 ----
  
      if (--fc->fc_refcount <= 0)
      {
!       for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller)
        {
!           if (fc == *pfc)
!           {
!               if (fc->l_varlist.lv_refcount == DO_NOT_FREE_CNT
                    && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT
                    && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT)
!               {
!                   *pfc = fc->caller;
!                   free_funccal(fc, TRUE);
!                   freed = TRUE;
!               }
!               break;
            }
        }
      }
      if (!freed)
      {
!       func_ptr_unref(fc->func);
  
        if (fp != NULL)
            for (i = 0; i < fc->fc_funcs.ga_len; ++i)
***************
*** 1141,1153 ****
  }
  
  /*
   * Free a function and remove it from the list of functions.
   */
      static void
  func_free(ufunc_T *fp)
  {
-     hashitem_T        *hi;
- 
      /* clear this function */
      ga_clear_strings(&(fp->uf_args));
      ga_clear_strings(&(fp->uf_lines));
--- 1068,1091 ----
  }
  
  /*
+  * Remove the function from the function hashtable.  If the function was
+  * deleted while it still has references this was already done.
+  */
+     static void
+ func_remove(ufunc_T *fp)
+ {
+     hashitem_T        *hi = hash_find(&func_hashtab, UF2HIKEY(fp));
+ 
+     if (!HASHITEM_EMPTY(hi))
+       hash_remove(&func_hashtab, hi);
+ }
+ 
+ /*
   * Free a function and remove it from the list of functions.
   */
      static void
  func_free(ufunc_T *fp)
  {
      /* clear this function */
      ga_clear_strings(&(fp->uf_args));
      ga_clear_strings(&(fp->uf_lines));
***************
*** 1156,1168 ****
      vim_free(fp->uf_tml_total);
      vim_free(fp->uf_tml_self);
  #endif
! 
!     /* remove the function from the function hashtable */
!     hi = hash_find(&func_hashtab, UF2HIKEY(fp));
!     if (HASHITEM_EMPTY(hi))
!       EMSG2(_(e_intern2), "func_free()");
!     else
!       hash_remove(&func_hashtab, hi);
  
      funccal_unref(fp->uf_scoped, fp);
  
--- 1094,1100 ----
      vim_free(fp->uf_tml_total);
      vim_free(fp->uf_tml_self);
  #endif
!     func_remove(fp);
  
      funccal_unref(fp->uf_scoped, fp);
  
***************
*** 1333,1339 ****
            /*
             * User defined function.
             */
!           fp = find_func(rfname);
  
  #ifdef FEAT_AUTOCMD
            /* Trigger FuncUndefined event, may load the function. */
--- 1265,1274 ----
            /*
             * User defined function.
             */
!           if (partial != NULL && partial->pt_func != NULL)
!               fp = partial->pt_func;
!           else
!               fp = find_func(rfname);
  
  #ifdef FEAT_AUTOCMD
            /* Trigger FuncUndefined event, may load the function. */
***************
*** 1353,1359 ****
                fp = find_func(rfname);
            }
  
!           if (fp != NULL)
            {
                if (argv_func != NULL)
                    argcount = argv_func(argcount, argvars, fp->uf_args.ga_len);
--- 1288,1296 ----
                fp = find_func(rfname);
            }
  
!           if (fp != NULL && (fp->uf_flags & FC_DELETED))
!               error = ERROR_DELETED;
!           else if (fp != NULL)
            {
                if (argv_func != NULL)
                    argcount = argv_func(argcount, argvars, fp->uf_args.ga_len);
***************
*** 1387,1395 ****
                    call_user_func(fp, argcount, argvars, rettv,
                                               firstline, lastline,
                                  (fp->uf_flags & FC_DICT) ? selfdict : NULL);
!                   if (--fp->uf_calls <= 0 && (isdigit(*fp->uf_name)
!                               || STRNCMP(fp->uf_name, "<lambda>", 8) == 0)
!                                                     && fp->uf_refcount <= 0)
                        /* Function was unreferenced while being used, free it
                         * now. */
                        func_free(fp);
--- 1324,1330 ----
                    call_user_func(fp, argcount, argvars, rettv,
                                               firstline, lastline,
                                  (fp->uf_flags & FC_DICT) ? selfdict : NULL);
!                   if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
                        /* Function was unreferenced while being used, free it
                         * now. */
                        func_free(fp);
***************
*** 1433,1438 ****
--- 1368,1376 ----
            case ERROR_UNKNOWN:
                    emsg_funcname(N_("E117: Unknown function: %s"), name);
                    break;
+           case ERROR_DELETED:
+                   emsg_funcname(N_("E933: Function was deleted: %s"), name);
+                   break;
            case ERROR_TOOMANY:
                    emsg_funcname((char *)e_toomanyarg, name);
                    break;
***************
*** 1516,1522 ****
   * TFN_NO_DEREF:    do not dereference a Funcref
   * Advances "pp" to just after the function name (if no error).
   */
!     static char_u *
  trans_function_name(
      char_u    **pp,
      int               skip,           /* only find the end, don't evaluate */
--- 1454,1460 ----
   * TFN_NO_DEREF:    do not dereference a Funcref
   * Advances "pp" to just after the function name (if no error).
   */
!     char_u *
  trans_function_name(
      char_u    **pp,
      int               skip,           /* only find the end, don't evaluate */
***************
*** 1595,1601 ****
        else if (lv.ll_tv->v_type == VAR_PARTIAL
                                          && lv.ll_tv->vval.v_partial != NULL)
        {
!           name = vim_strsave(lv.ll_tv->vval.v_partial->pt_name);
            *pp = end;
            if (partial != NULL)
                *partial = lv.ll_tv->vval.v_partial;
--- 1533,1539 ----
        else if (lv.ll_tv->v_type == VAR_PARTIAL
                                          && lv.ll_tv->vval.v_partial != NULL)
        {
!           name = vim_strsave(partial_name(lv.ll_tv->vval.v_partial));
            *pp = end;
            if (partial != NULL)
                *partial = lv.ll_tv->vval.v_partial;
***************
*** 1752,1757 ****
--- 1690,1696 ----
      int               varargs = FALSE;
      int               flags = 0;
      ufunc_T   *fp;
+     int               overwrite = FALSE;
      int               indent;
      int               nesting;
      char_u    *skip_until = NULL;
***************
*** 2214,2224 ****
                                                                        name);
                goto erret;
            }
!           /* redefine existing function */
!           ga_clear_strings(&(fp->uf_args));
!           ga_clear_strings(&(fp->uf_lines));
!           vim_free(name);
!           name = NULL;
        }
      }
      else
--- 2153,2174 ----
                                                                        name);
                goto erret;
            }
!           if (fp->uf_refcount > 1)
!           {
!               /* This function is referenced somewhere, don't redefine it but
!                * create a new one. */
!               --fp->uf_refcount;
!               fp = NULL;
!               overwrite = TRUE;
!           }
!           else
!           {
!               /* redefine existing function */
!               ga_clear_strings(&(fp->uf_args));
!               ga_clear_strings(&(fp->uf_lines));
!               vim_free(name);
!               name = NULL;
!           }
        }
      }
      else
***************
*** 2308,2314 ****
            fudi.fd_di->di_tv.v_type = VAR_FUNC;
            fudi.fd_di->di_tv.v_lock = 0;
            fudi.fd_di->di_tv.vval.v_string = vim_strsave(name);
-           fp->uf_refcount = 1;
  
            /* behave like "dict" was used */
            flags |= FC_DICT;
--- 2258,2263 ----
***************
*** 2316,2332 ****
  
        /* insert the new function in the function list */
        STRCPY(fp->uf_name, name);
!       if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL)
        {
            vim_free(fp);
            goto erret;
        }
      }
      fp->uf_args = newargs;
      fp->uf_lines = newlines;
      if ((flags & FC_CLOSURE) != 0)
      {
-       ++fp->uf_refcount;
        if (register_closure(fp) == FAIL)
            goto erret;
      }
--- 2265,2286 ----
  
        /* insert the new function in the function list */
        STRCPY(fp->uf_name, name);
!       if (overwrite)
!       {
!           hi = hash_find(&func_hashtab, name);
!           hi->hi_key = UF2HIKEY(fp);
!       }
!       else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL)
        {
            vim_free(fp);
            goto erret;
        }
+       fp->uf_refcount = 1;
      }
      fp->uf_args = newargs;
      fp->uf_lines = newlines;
      if ((flags & FC_CLOSURE) != 0)
      {
        if (register_closure(fp) == FAIL)
            goto erret;
      }
***************
*** 2750,2762 ****
            dictitem_remove(fudi.fd_dict, fudi.fd_di);
        }
        else
!           func_free(fp);
      }
  }
  
  /*
   * Unreference a Function: decrement the reference count and free it when it
!  * becomes zero.  Only for numbered functions.
   */
      void
  func_unref(char_u *name)
--- 2704,2733 ----
            dictitem_remove(fudi.fd_dict, fudi.fd_di);
        }
        else
!       {
!           /* Normal functions (not numbered functions and lambdas) have a
!            * refcount of 1 for the entry in the hashtable.  When deleting
!            * them and the refcount is more than one, it should be kept.
!            * Numbered functions and lambdas snould be kept if the refcount is
!            * one or more. */
!           if (fp->uf_refcount > (isdigit(fp->uf_name[0])
!                                            || fp->uf_name[0] == '<') ? 0 : 1)
!           {
!               /* Function is still referenced somewhere.  Don't free it but
!                * do remove it from the hashtable. */
!               func_remove(fp);
!               fp->uf_flags |= FC_DELETED;
!               fp->uf_refcount--;
!           }
!           else
!               func_free(fp);
!       }
      }
  }
  
  /*
   * Unreference a Function: decrement the reference count and free it when it
!  * becomes zero.
   */
      void
  func_unref(char_u *name)
***************
*** 2765,2786 ****
  
      if (name == NULL)
        return;
!     if (isdigit(*name))
      {
-       fp = find_func(name);
-       if (fp == NULL)
-       {
  #ifdef EXITFREE
!           if (!entered_free_all_mem)
  #endif
!               EMSG2(_(e_intern2), "func_unref()");
!       }
      }
!     else if (STRNCMP(name, "<lambda>", 8) == 0)
      {
!       /* fail silently, when lambda function isn't found. */
!       fp = find_func(name);
      }
      if (fp != NULL && --fp->uf_refcount <= 0)
      {
        /* Only delete it when it's not being used.  Otherwise it's done
--- 2736,2765 ----
  
      if (name == NULL)
        return;
!     fp = find_func(name);
!     if (fp == NULL && isdigit(*name))
      {
  #ifdef EXITFREE
!       if (!entered_free_all_mem)
  #endif
!           EMSG2(_(e_intern2), "func_unref()");
      }
!     if (fp != NULL && --fp->uf_refcount <= 0)
      {
!       /* Only delete it when it's not being used.  Otherwise it's done
!        * when "uf_calls" becomes zero. */
!       if (fp->uf_calls == 0)
!           func_free(fp);
      }
+ }
+ 
+ /*
+  * Unreference a Function: decrement the reference count and free it when it
+  * becomes zero.
+  */
+     void
+ func_ptr_unref(ufunc_T *fp)
+ {
      if (fp != NULL && --fp->uf_refcount <= 0)
      {
        /* Only delete it when it's not being used.  Otherwise it's done
***************
*** 2800,2820 ****
  
      if (name == NULL)
        return;
      else if (isdigit(*name))
!     {
!       fp = find_func(name);
!       if (fp == NULL)
!           EMSG2(_(e_intern2), "func_ref()");
!       else
!           ++fp->uf_refcount;
!     }
!     else if (STRNCMP(name, "<lambda>", 8) == 0)
!     {
!       /* fail silently, when lambda function isn't found. */
!       fp = find_func(name);
!       if (fp != NULL)
!           ++fp->uf_refcount;
!     }
  }
  
  /*
--- 2779,2801 ----
  
      if (name == NULL)
        return;
+     fp = find_func(name);
+     if (fp != NULL)
+       ++fp->uf_refcount;
      else if (isdigit(*name))
!       /* Only give an error for a numbered function.
!        * Fail silently, when named or lambda function isn't found. */
!       EMSG2(_(e_intern2), "func_ref()");
! }
! 
! /*
!  * Count a reference to a Function.
!  */
!     void
! func_ptr_ref(ufunc_T *fp)
! {
!     if (fp != NULL)
!       ++fp->uf_refcount;
  }
  
  /*
***************
*** 3298,3315 ****
      dict_T *
  make_partial(dict_T *selfdict_in, typval_T *rettv)
  {
!     char_u    *fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
!                                        : rettv->vval.v_partial->pt_name;
      char_u    *tofree = NULL;
      ufunc_T   *fp;
      char_u    fname_buf[FLEN_FIXED + 1];
      int               error;
      dict_T    *selfdict = selfdict_in;
  
!     /* Translate "s:func" to the stored function name. */
!     fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
!     fp = find_func(fname);
!     vim_free(tofree);
  
      if (fp != NULL && (fp->uf_flags & FC_DICT))
      {
--- 3279,3302 ----
      dict_T *
  make_partial(dict_T *selfdict_in, typval_T *rettv)
  {
!     char_u    *fname;
      char_u    *tofree = NULL;
      ufunc_T   *fp;
      char_u    fname_buf[FLEN_FIXED + 1];
      int               error;
      dict_T    *selfdict = selfdict_in;
  
!     if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != 
NULL)
!       fp = rettv->vval.v_partial->pt_func;
!     else
!     {
!       fname = rettv->v_type == VAR_FUNC ? rettv->vval.v_string
!                                             : rettv->vval.v_partial->pt_name;
!       /* Translate "s:func" to the stored function name. */
!       fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
!       fp = find_func(fname);
!       vim_free(tofree);
!     }
  
      if (fp != NULL && (fp->uf_flags & FC_DICT))
      {
***************
*** 3335,3342 ****
                /* Partial: copy the function name, use selfdict and copy
                 * args.  Can't take over name or args, the partial might
                 * be referenced elsewhere. */
!               pt->pt_name = vim_strsave(ret_pt->pt_name);
!               func_ref(pt->pt_name);
                if (ret_pt->pt_argc > 0)
                {
                    pt->pt_argv = (typval_T *)alloc(
--- 3322,3337 ----
                /* Partial: copy the function name, use selfdict and copy
                 * args.  Can't take over name or args, the partial might
                 * be referenced elsewhere. */
!               if (ret_pt->pt_name != NULL)
!               {
!                   pt->pt_name = vim_strsave(ret_pt->pt_name);
!                   func_ref(pt->pt_name);
!               }
!               else
!               {
!                   pt->pt_func = ret_pt->pt_func;
!                   func_ptr_ref(pt->pt_func);
!               }
                if (ret_pt->pt_argc > 0)
                {
                    pt->pt_argv = (typval_T *)alloc(
***************
*** 3703,3722 ****
   * Returns TRUE if setting references failed somehow.
   */
      int
! set_ref_in_func(char_u *name, int copyID)
  {
!     ufunc_T   *fp;
      funccall_T        *fc;
      int               error = ERROR_NONE;
      char_u    fname_buf[FLEN_FIXED + 1];
      char_u    *tofree = NULL;
      char_u    *fname;
  
!     if (name == NULL)
        return FALSE;
  
!     fname = fname_trans_sid(name, fname_buf, &tofree, &error);
!     fp = find_func(fname);
      if (fp != NULL)
      {
        for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped)
--- 3698,3720 ----
   * Returns TRUE if setting references failed somehow.
   */
      int
! set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
  {
!     ufunc_T   *fp = fp_in;
      funccall_T        *fc;
      int               error = ERROR_NONE;
      char_u    fname_buf[FLEN_FIXED + 1];
      char_u    *tofree = NULL;
      char_u    *fname;
  
!     if (name == NULL && fp_in == NULL)
        return FALSE;
  
!     if (fp_in == NULL)
!     {
!       fname = fname_trans_sid(name, fname_buf, &tofree, &error);
!       fp = find_func(fname);
!     }
      if (fp != NULL)
      {
        for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped)
*** ../vim-7.4.2136/src/eval.c  2016-07-31 14:11:55.174542407 +0200
--- src/eval.c  2016-07-31 19:48:04.116443706 +0200
***************
*** 5011,5016 ****
--- 5011,5027 ----
      return OK;
  }
  
+ /*
+  * Return the function name of the partial.
+  */
+     char_u *
+ partial_name(partial_T *pt)
+ {
+     if (pt->pt_name != NULL)
+       return pt->pt_name;
+     return pt->pt_func->uf_name;
+ }
+ 
      static void
  partial_free(partial_T *pt)
  {
***************
*** 5020,5027 ****
        clear_tv(&pt->pt_argv[i]);
      vim_free(pt->pt_argv);
      dict_unref(pt->pt_dict);
!     func_unref(pt->pt_name);
!     vim_free(pt->pt_name);
      vim_free(pt);
  }
  
--- 5031,5043 ----
        clear_tv(&pt->pt_argv[i]);
      vim_free(pt->pt_argv);
      dict_unref(pt->pt_dict);
!     if (pt->pt_name != NULL)
!     {
!       func_unref(pt->pt_name);
!       vim_free(pt->pt_name);
!     }
!     else
!       func_ptr_unref(pt->pt_func);
      vim_free(pt);
  }
  
***************
*** 5051,5061 ****
  
      /* empty and NULL function name considered the same */
      s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
!                                          : tv1->vval.v_partial->pt_name;
      if (s1 != NULL && *s1 == NUL)
        s1 = NULL;
      s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
!                                          : tv2->vval.v_partial->pt_name;
      if (s2 != NULL && *s2 == NUL)
        s2 = NULL;
      if (s1 == NULL || s2 == NULL)
--- 5067,5077 ----
  
      /* empty and NULL function name considered the same */
      s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
!                                          : partial_name(tv1->vval.v_partial);
      if (s1 != NULL && *s1 == NUL)
        s1 = NULL;
      s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
!                                          : partial_name(tv2->vval.v_partial);
      if (s2 != NULL && *s2 == NUL)
        s2 = NULL;
      if (s1 == NULL || s2 == NULL)
***************
*** 5550,5556 ****
      }
      else if (tv->v_type == VAR_FUNC)
      {
!       abort = set_ref_in_func(tv->vval.v_string, copyID);
      }
      else if (tv->v_type == VAR_PARTIAL)
      {
--- 5566,5572 ----
      }
      else if (tv->v_type == VAR_FUNC)
      {
!       abort = set_ref_in_func(tv->vval.v_string, NULL, copyID);
      }
      else if (tv->v_type == VAR_PARTIAL)
      {
***************
*** 5561,5567 ****
         */
        if (pt != NULL)
        {
!           abort = set_ref_in_func(pt->pt_name, copyID);
  
            if (pt->pt_dict != NULL)
            {
--- 5577,5583 ----
         */
        if (pt != NULL)
        {
!           abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
  
            if (pt->pt_dict != NULL)
            {
***************
*** 5735,5741 ****
            {
                partial_T   *pt = tv->vval.v_partial;
                char_u      *fname = string_quote(pt == NULL ? NULL
!                                                       : pt->pt_name, FALSE);
                garray_T    ga;
                int         i;
                char_u      *tf;
--- 5751,5757 ----
            {
                partial_T   *pt = tv->vval.v_partial;
                char_u      *fname = string_quote(pt == NULL ? NULL
!                                                   : partial_name(pt), FALSE);
                garray_T    ga;
                int         i;
                char_u      *tf;
***************
*** 6871,6877 ****
                if (functv.v_type == VAR_PARTIAL)
                {
                    pt = functv.vval.v_partial;
!                   s = pt->pt_name;
                }
                else
                    s = functv.vval.v_string;
--- 6887,6893 ----
                if (functv.v_type == VAR_PARTIAL)
                {
                    pt = functv.vval.v_partial;
!                   s = partial_name(pt);
                }
                else
                    s = functv.vval.v_string;
***************
*** 10025,10031 ****
      {
        partial_T   *partial = expr->vval.v_partial;
  
!       s = partial->pt_name;
        if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL,
                                  0L, 0L, &dummy, TRUE, partial, NULL) == FAIL)
            goto theend;
--- 10041,10047 ----
      {
        partial_T   *partial = expr->vval.v_partial;
  
!       s = partial_name(partial);
        if (call_func(s, (int)STRLEN(s), &rettv, 2, argv, NULL,
                                  0L, 0L, &dummy, TRUE, partial, NULL) == FAIL)
            goto theend;
*** ../vim-7.4.2136/src/evalfunc.c      2016-07-31 14:11:55.178542370 +0200
--- src/evalfunc.c      2016-08-01 15:27:58.610785732 +0200
***************
*** 148,153 ****
--- 148,154 ----
  static void f_foldtext(typval_T *argvars, typval_T *rettv);
  static void f_foldtextresult(typval_T *argvars, typval_T *rettv);
  static void f_foreground(typval_T *argvars, typval_T *rettv);
+ static void f_funcref(typval_T *argvars, typval_T *rettv);
  static void f_function(typval_T *argvars, typval_T *rettv);
  static void f_garbagecollect(typval_T *argvars, typval_T *rettv);
  static void f_get(typval_T *argvars, typval_T *rettv);
***************
*** 563,568 ****
--- 564,570 ----
      {"foldtext",      0, 0, f_foldtext},
      {"foldtextresult",        1, 1, f_foldtextresult},
      {"foreground",    0, 0, f_foreground},
+     {"funcref",               1, 3, f_funcref},
      {"function",      1, 3, f_function},
      {"garbagecollect",        0, 1, f_garbagecollect},
      {"get",           2, 3, f_get},
***************
*** 1723,1729 ****
      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]);
--- 1725,1731 ----
      else if (argvars[0].v_type == VAR_PARTIAL)
      {
        partial = argvars[0].vval.v_partial;
!       func = partial_name(partial);
      }
      else
        func = get_tv_string(&argvars[0]);
***************
*** 3543,3558 ****
  #endif
  }
  
- /*
-  * "function()" function
-  */
      static void
! f_function(typval_T *argvars, typval_T *rettv)
  {
      char_u    *s;
      char_u    *name;
      int               use_string = FALSE;
      partial_T   *arg_pt = NULL;
  
      if (argvars[0].v_type == VAR_FUNC)
      {
--- 3545,3558 ----
  #endif
  }
  
      static void
! common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
  {
      char_u    *s;
      char_u    *name;
      int               use_string = FALSE;
      partial_T   *arg_pt = NULL;
+     char_u    *trans_name = NULL;
  
      if (argvars[0].v_type == VAR_FUNC)
      {
***************
*** 3564,3570 ****
      {
        /* function(dict.MyFunc, [arg]) */
        arg_pt = argvars[0].vval.v_partial;
!       s = arg_pt->pt_name;
      }
      else
      {
--- 3564,3570 ----
      {
        /* function(dict.MyFunc, [arg]) */
        arg_pt = argvars[0].vval.v_partial;
!       s = partial_name(arg_pt);
      }
      else
      {
***************
*** 3573,3583 ****
        use_string = TRUE;
      }
  
      if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s)))
        EMSG2(_(e_invarg2), s);
      /* Don't check an autoload name for existence here. */
!     else if (use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL
!                                               && !function_exists(s, TRUE))
        EMSG2(_("E700: Unknown function: %s"), s);
      else
      {
--- 3573,3594 ----
        use_string = TRUE;
      }
  
+     if (((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL)
+                                  || is_funcref))
+     {
+       name = s;
+       trans_name = trans_function_name(&name, FALSE,
+            TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
+       if (*name != NUL)
+           s = NULL;
+     }
+ 
      if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s)))
        EMSG2(_(e_invarg2), s);
      /* Don't check an autoload name for existence here. */
!     else if (trans_name != NULL && (is_funcref
!                               ? find_func(trans_name) == NULL
!                               : !translated_function_exists(trans_name)))
        EMSG2(_("E700: Unknown function: %s"), s);
      else
      {
***************
*** 3625,3631 ****
                {
                    EMSG(_("E922: expected a dict"));
                    vim_free(name);
!                   return;
                }
                if (argvars[dict_idx].vval.v_dict == NULL)
                    dict_idx = 0;
--- 3636,3642 ----
                {
                    EMSG(_("E922: expected a dict"));
                    vim_free(name);
!                   goto theend;
                }
                if (argvars[dict_idx].vval.v_dict == NULL)
                    dict_idx = 0;
***************
*** 3636,3649 ****
                {
                    EMSG(_("E923: Second argument of function() must be a list 
or a dict"));
                    vim_free(name);
!                   return;
                }
                list = argvars[arg_idx].vval.v_list;
                if (list == NULL || list->lv_len == 0)
                    arg_idx = 0;
            }
        }
!       if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL)
        {
            partial_T   *pt = (partial_T *)alloc_clear(sizeof(partial_T));
  
--- 3647,3660 ----
                {
                    EMSG(_("E923: Second argument of function() must be a list 
or a dict"));
                    vim_free(name);
!                   goto theend;
                }
                list = argvars[arg_idx].vval.v_list;
                if (list == NULL || list->lv_len == 0)
                    arg_idx = 0;
            }
        }
!       if (dict_idx > 0 || arg_idx > 0 || arg_pt != NULL || is_funcref)
        {
            partial_T   *pt = (partial_T *)alloc_clear(sizeof(partial_T));
  
***************
*** 3670,3686 ****
                    {
                        vim_free(pt);
                        vim_free(name);
!                       return;
!                   }
!                   else
!                   {
!                       for (i = 0; i < arg_len; i++)
!                           copy_tv(&arg_pt->pt_argv[i], &pt->pt_argv[i]);
!                       if (lv_len > 0)
!                           for (li = list->lv_first; li != NULL;
!                                                            li = li->li_next)
!                               copy_tv(&li->li_tv, &pt->pt_argv[i++]);
                    }
                }
  
                /* For "function(dict.func, [], dict)" and "func" is a partial
--- 3681,3694 ----
                    {
                        vim_free(pt);
                        vim_free(name);
!                       goto theend;
                    }
+                   for (i = 0; i < arg_len; i++)
+                       copy_tv(&arg_pt->pt_argv[i], &pt->pt_argv[i]);
+                   if (lv_len > 0)
+                       for (li = list->lv_first; li != NULL;
+                                                        li = li->li_next)
+                           copy_tv(&li->li_tv, &pt->pt_argv[i++]);
                }
  
                /* For "function(dict.func, [], dict)" and "func" is a partial
***************
*** 3702,3709 ****
                }
  
                pt->pt_refcount = 1;
!               pt->pt_name = name;
!               func_ref(pt->pt_name);
            }
            rettv->v_type = VAR_PARTIAL;
            rettv->vval.v_partial = pt;
--- 3710,3732 ----
                }
  
                pt->pt_refcount = 1;
!               if (arg_pt != NULL && arg_pt->pt_func != NULL)
!               {
!                   pt->pt_func = arg_pt->pt_func;
!                   func_ptr_ref(pt->pt_func);
!                   vim_free(name);
!               }
!               else if (is_funcref)
!               {
!                   pt->pt_func = find_func(trans_name);
!                   func_ptr_ref(pt->pt_func);
!                   vim_free(name);
!               }
!               else
!               {
!                   pt->pt_name = name;
!                   func_ref(name);
!               }
            }
            rettv->v_type = VAR_PARTIAL;
            rettv->vval.v_partial = pt;
***************
*** 3716,3721 ****
--- 3739,3764 ----
            func_ref(name);
        }
      }
+ theend:
+     vim_free(trans_name);
+ }
+ 
+ /*
+  * "funcref()" function
+  */
+     static void
+ f_funcref(typval_T *argvars, typval_T *rettv)
+ {
+     common_function(argvars, rettv, TRUE);
+ }
+ 
+ /*
+  * "function()" function
+  */
+     static void
+ f_function(typval_T *argvars, typval_T *rettv)
+ {
+     common_function(argvars, rettv, FALSE);
  }
  
  /*
***************
*** 3781,3794 ****
        if (pt != NULL)
        {
            char_u *what = get_tv_string(&argvars[1]);
  
            if (STRCMP(what, "func") == 0 || STRCMP(what, "name") == 0)
            {
                rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING);
!               if (pt->pt_name == NULL)
                    rettv->vval.v_string = NULL;
                else
!                   rettv->vval.v_string = vim_strsave(pt->pt_name);
            }
            else if (STRCMP(what, "dict") == 0)
            {
--- 3824,3843 ----
        if (pt != NULL)
        {
            char_u *what = get_tv_string(&argvars[1]);
+           char_u *n;
  
            if (STRCMP(what, "func") == 0 || STRCMP(what, "name") == 0)
            {
                rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING);
!               n = partial_name(pt);
!               if (n == NULL)
                    rettv->vval.v_string = NULL;
                else
!               {
!                   rettv->vval.v_string = vim_strsave(n);
!                   if (rettv->v_type == VAR_FUNC)
!                       func_ref(rettv->vval.v_string);
!               }
            }
            else if (STRCMP(what, "dict") == 0)
            {
***************
*** 10104,10110 ****
      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. */
--- 10153,10159 ----
      if (partial == NULL)
        func_name = sortinfo->item_compare_func;
      else
!       func_name = partial_name(partial);
  
      /* 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. */
***************
*** 11863,11878 ****
      {
        *pp = arg->vval.v_partial;
        ++(*pp)->pt_refcount;
!       return (*pp)->pt_name;
      }
      *pp = NULL;
!     if (arg->v_type == VAR_FUNC)
      {
        func_ref(arg->vval.v_string);
        return arg->vval.v_string;
      }
-     if (arg->v_type == VAR_STRING)
-       return arg->vval.v_string;
      if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
        return (char_u *)"";
      EMSG(_("E921: Invalid callback argument"));
--- 11912,11925 ----
      {
        *pp = arg->vval.v_partial;
        ++(*pp)->pt_refcount;
!       return partial_name(*pp);
      }
      *pp = NULL;
!     if (arg->v_type == VAR_FUNC || arg->v_type == VAR_STRING)
      {
        func_ref(arg->vval.v_string);
        return arg->vval.v_string;
      }
      if (arg->v_type == VAR_NUMBER && arg->vval.v_number == 0)
        return (char_u *)"";
      EMSG(_("E921: Invalid callback argument"));
*** ../vim-7.4.2136/src/channel.c       2016-07-30 23:05:04.720679001 +0200
--- src/channel.c       2016-08-01 13:52:46.034799279 +0200
***************
*** 1124,1138 ****
      if (callback != NULL && *callback != NUL)
      {
        if (partial != NULL)
!           *cbp = partial->pt_name;
        else
            *cbp = vim_strsave(callback);
      }
      else
        *cbp = NULL;
      *pp = partial;
!     if (*pp != NULL)
!       ++(*pp)->pt_refcount;
  }
  
  /*
--- 1124,1141 ----
      if (callback != NULL && *callback != NUL)
      {
        if (partial != NULL)
!           *cbp = partial_name(partial);
        else
+       {
            *cbp = vim_strsave(callback);
+           func_ref(*cbp);
+       }
      }
      else
        *cbp = NULL;
      *pp = partial;
!     if (partial != NULL)
!       ++partial->pt_refcount;
  }
  
  /*
***************
*** 1279,1285 ****
--- 1282,1291 ----
            item->cq_callback = callback;
        }
        else
+       {
            item->cq_callback = vim_strsave(callback);
+           func_ref(item->cq_callback);
+       }
        item->cq_seq_nr = id;
        item->cq_prev = head->cq_prev;
        head->cq_prev = item;
***************
*** 3923,3936 ****
--- 3929,3952 ----
  {
      if (opt->jo_partial != NULL)
        partial_unref(opt->jo_partial);
+     else if (opt->jo_callback != NULL)
+       func_unref(opt->jo_callback);
      if (opt->jo_out_partial != NULL)
        partial_unref(opt->jo_out_partial);
+     else if (opt->jo_out_cb != NULL)
+       func_unref(opt->jo_out_cb);
      if (opt->jo_err_partial != NULL)
        partial_unref(opt->jo_err_partial);
+     else if (opt->jo_err_cb != NULL)
+       func_unref(opt->jo_err_cb);
      if (opt->jo_close_partial != NULL)
        partial_unref(opt->jo_close_partial);
+     else if (opt->jo_close_cb != NULL)
+       func_unref(opt->jo_close_cb);
      if (opt->jo_exit_partial != NULL)
        partial_unref(opt->jo_exit_partial);
+     else if (opt->jo_exit_cb != NULL)
+       func_unref(opt->jo_exit_cb);
  }
  
  /*
***************
*** 4476,4482 ****
--- 4492,4501 ----
                ++job->jv_exit_partial->pt_refcount;
            }
            else
+           {
                job->jv_exit_cb = vim_strsave(opt->jo_exit_cb);
+               func_ref(job->jv_exit_cb);
+           }
        }
      }
  }
*** ../vim-7.4.2136/src/proto/eval.pro  2016-07-29 22:14:39.035998293 +0200
--- src/proto/eval.pro  2016-07-31 19:47:47.492588175 +0200
***************
*** 40,45 ****
--- 40,46 ----
  int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate);
  int eval1(char_u **arg, typval_T *rettv, int evaluate);
  int get_option_tv(char_u **arg, typval_T *rettv, int evaluate);
+ char_u *partial_name(partial_T *pt);
  void partial_unref(partial_T *pt);
  int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive);
  int get_copyID(void);
*** ../vim-7.4.2136/src/proto/userfunc.pro      2016-07-31 14:11:55.178542370 
+0200
--- src/proto/userfunc.pro      2016-07-31 21:51:37.416028064 +0200
***************
*** 3,11 ****
--- 3,13 ----
  int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate);
  char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int 
no_autoload);
  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);
+ ufunc_T *find_func(char_u *name);
  void free_all_functions(void);
  int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T 
*selfdict, typval_T *rettv);
  int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, 
typval_T *argvars_in, int (*argv_func)(int, typval_T *, int), linenr_T 
firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, 
dict_T *selfdict_in);
+ char_u *trans_function_name(char_u **pp, int skip, int flags, funcdict_T 
*fdp, partial_T **partial);
  void ex_function(exarg_T *eap);
  int eval_fname_script(char_u *p);
  int translated_function_exists(char_u *name);
***************
*** 17,23 ****
--- 19,27 ----
  char_u *get_user_func_name(expand_T *xp, int idx);
  void ex_delfunction(exarg_T *eap);
  void func_unref(char_u *name);
+ void func_ptr_unref(ufunc_T *fp);
  void func_ref(char_u *name);
+ void func_ptr_ref(ufunc_T *fp);
  void ex_return(exarg_T *eap);
  void ex_call(exarg_T *eap);
  int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv);
***************
*** 51,55 ****
  int set_ref_in_previous_funccal(int copyID);
  int set_ref_in_call_stack(int copyID);
  int set_ref_in_func_args(int copyID);
! int set_ref_in_func(char_u *name, int copyID);
  /* vim: set ft=c : */
--- 55,59 ----
  int set_ref_in_previous_funccal(int copyID);
  int set_ref_in_call_stack(int copyID);
  int set_ref_in_func_args(int copyID);
! int set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID);
  /* vim: set ft=c : */
*** ../vim-7.4.2136/src/if_mzsch.c      2016-07-24 21:58:39.704057634 +0200
--- src/if_mzsch.c      2016-07-31 19:39:28.032924413 +0200
***************
*** 3134,3140 ****
            /* FIXME: func_ref() and func_unref() are needed. */
            /* TODO: Support pt_dict and pt_argv. */
            funcname = scheme_make_byte_string(
!                   (char *)vim_value->vval.v_partial->pt_name);
            MZ_GC_CHECK();
            result = scheme_make_closed_prim_w_arity(vim_funcref, funcname,
                    (const char *)BYTE_STRING_VALUE(funcname), 0, -1);
--- 3134,3140 ----
            /* FIXME: func_ref() and func_unref() are needed. */
            /* TODO: Support pt_dict and pt_argv. */
            funcname = scheme_make_byte_string(
!                             (char *)partial_name(vim_value->vval.v_partial));
            MZ_GC_CHECK();
            result = scheme_make_closed_prim_w_arity(vim_funcref, funcname,
                    (const char *)BYTE_STRING_VALUE(funcname), 0, -1);
*** ../vim-7.4.2136/src/regexp.c        2016-07-22 21:49:36.678031435 +0200
--- src/regexp.c        2016-07-31 19:39:49.816735470 +0200
***************
*** 7499,7505 ****
                    {
                        partial_T   *partial = expr->vval.v_partial;
  
!                       s = partial->pt_name;
                        call_func(s, (int)STRLEN(s), &rettv,
                                        1, argv, fill_submatch_list,
                                          0L, 0L, &dummy, TRUE, partial, NULL);
--- 7499,7505 ----
                    {
                        partial_T   *partial = expr->vval.v_partial;
  
!                       s = partial_name(partial);
                        call_func(s, (int)STRLEN(s), &rettv,
                                        1, argv, fill_submatch_list,
                                          0L, 0L, &dummy, TRUE, partial, NULL);
*** ../vim-7.4.2136/src/misc2.c 2016-07-30 22:47:44.322520729 +0200
--- src/misc2.c 2016-07-31 20:10:26.272891113 +0200
***************
*** 1217,1232 ****
        if (delete_first_msg() == FAIL)
            break;
  
- # ifdef FEAT_EVAL
-     eval_clear();
- # endif
  # ifdef FEAT_JOB_CHANNEL
      channel_free_all();
-     job_free_all();
  # endif
  #ifdef FEAT_TIMERS
      timer_free_all();
  #endif
  
      free_termoptions();
  
--- 1217,1236 ----
        if (delete_first_msg() == FAIL)
            break;
  
  # ifdef FEAT_JOB_CHANNEL
      channel_free_all();
  # endif
  #ifdef FEAT_TIMERS
      timer_free_all();
  #endif
+ # ifdef FEAT_EVAL
+     /* must be after channel_free_all() with unrefs partials */
+     eval_clear();
+ # endif
+ # ifdef FEAT_JOB_CHANNEL
+     /* must be after eval_clear() with unrefs jobs */
+     job_free_all();
+ # endif
  
      free_termoptions();
  
*** ../vim-7.4.2136/src/if_py_both.h    2016-07-10 22:11:11.878751222 +0200
--- src/if_py_both.h    2016-07-31 19:42:27.039371291 +0200
***************
*** 6310,6316 ****
            if (tv->vval.v_partial->pt_dict != NULL)
                tv->vval.v_partial->pt_dict->dv_refcount++;
            return NEW_FUNCTION(tv->vval.v_partial == NULL
!                               ? (char_u *)"" : tv->vval.v_partial->pt_name,
                                tv->vval.v_partial->pt_argc, argv,
                                tv->vval.v_partial->pt_dict,
                                tv->vval.v_partial->pt_auto);
--- 6310,6316 ----
            if (tv->vval.v_partial->pt_dict != NULL)
                tv->vval.v_partial->pt_dict->dv_refcount++;
            return NEW_FUNCTION(tv->vval.v_partial == NULL
!                            ? (char_u *)"" : partial_name(tv->vval.v_partial),
                                tv->vval.v_partial->pt_argc, argv,
                                tv->vval.v_partial->pt_dict,
                                tv->vval.v_partial->pt_auto);
*** ../vim-7.4.2136/src/testdir/test_lambda.vim 2016-07-31 18:30:19.041018233 
+0200
--- src/testdir/test_lambda.vim 2016-08-01 14:37:05.886717455 +0200
***************
*** 152,158 ****
    endfunction
  
    let l:F = s:gen()
!   call assert_fails(':call l:F()', 'E117:')
  endfunction
  
  function! Test_lambda_scope()
--- 152,158 ----
    endfunction
  
    let l:F = s:gen()
!   call assert_fails(':call l:F()', 'E933:')
  endfunction
  
  function! Test_lambda_scope()
*** ../vim-7.4.2136/src/testdir/test_expr.vim   2016-07-31 14:11:55.178542370 
+0200
--- src/testdir/test_expr.vim   2016-08-01 15:22:51.561635890 +0200
***************
*** 179,181 ****
--- 179,196 ----
    call assert_equal(v:t_string, s:fref('x'))
    call assert_fails("call function('s:f')", 'E700:')
  endfunc
+ 
+ func Test_funcref()
+   func! One()
+     return 1
+   endfunc
+   let OneByName = function('One')
+   let OneByRef = funcref('One')
+   func! One()
+     return 2
+   endfunc
+   call assert_equal(2, OneByName())
+   call assert_equal(1, OneByRef())
+   let OneByRef = funcref('One')
+   call assert_equal(2, OneByRef())
+ endfunc
*** ../vim-7.4.2136/runtime/doc/eval.txt        2016-07-29 22:36:40.207701429 
+0200
--- runtime/doc/eval.txt        2016-07-31 21:23:15.218976743 +0200
***************
*** 2052,2059 ****
  foldtext()                    String  line displayed for closed fold
  foldtextresult({lnum})                String  text for closed fold at {lnum}
  foreground()                  Number  bring the Vim window to the foreground
  function({name} [, {arglist}] [, {dict}])
!                               Funcref reference to function {name}
  garbagecollect([{atexit}])    none    free memory, breaking cyclic references
  get({list}, {idx} [, {def}])  any     get item {idx} from {list} or {def}
  get({dict}, {key} [, {def}])  any     get item {key} from {dict} or {def}
--- 2073,2082 ----
  foldtext()                    String  line displayed for closed fold
  foldtextresult({lnum})                String  text for closed fold at {lnum}
  foreground()                  Number  bring the Vim window to the foreground
+ funcref({name} [, {arglist}] [, {dict}])
+                               Funcref reference to function {name}
  function({name} [, {arglist}] [, {dict}])
!                               Funcref named reference to function {name}
  garbagecollect([{atexit}])    none    free memory, breaking cyclic references
  get({list}, {idx} [, {def}])  any     get item {idx} from {list} or {def}
  get({dict}, {key} [, {def}])  any     get item {key} from {dict} or {def}
***************
*** 3829,3842 ****
                {only in the Win32, Athena, Motif and GTK GUI versions and the
                Win32 console version}
  
  
                                        *function()* *E700* *E922* *E923*
  function({name} [, {arglist}] [, {dict}])
                Return a |Funcref| variable that refers to function {name}.
!               {name} can be a user defined function or an internal function.
  
                When {arglist} or {dict} is present this creates a partial.
!               That mans the argument list and/or the dictionary is stored in
                the Funcref and will be used when the Funcref is called.
                
                The arguments are passed to the function in front of other
--- 3854,3887 ----
                {only in the Win32, Athena, Motif and GTK GUI versions and the
                Win32 console version}
  
+                                               *funcref()*
+ funcref({name} [, {arglist}] [, {dict}])
+               Just like |function()|, but the returned Funcref will lookup
+               the function by reference, not by name.  This matters when the
+               function {name} is redefined later.
+ 
+               Unlike |function()|, {name} must be an existing user function.
+               Also for autoloaded functions. {name} cannot be a builtin
+               function.
  
                                        *function()* *E700* *E922* *E923*
  function({name} [, {arglist}] [, {dict}])
                Return a |Funcref| variable that refers to function {name}.
!               {name} can be the name of a user defined function or an
!               internal function.
! 
!               {name} can also be a Funcref or a partial.  When it is a
!               partial the dict stored in it will be used and the {dict}
!               argument is not allowed. E.g.: >
!                       let FuncWithArg = function(dict.Func, [arg])
!                       let Broken = function(dict.Func, [arg], dict)
! <
!               When using the Funcref the function will be found by {name},
!               also when it was redefined later.  Use |funcref()| to keep the
!               same function.
  
                When {arglist} or {dict} is present this creates a partial.
!               That means the argument list and/or the dictionary is stored in
                the Funcref and will be used when the Funcref is called.
                
                The arguments are passed to the function in front of other
***************
*** 3849,3854 ****
--- 3894,3911 ----
  <             Invokes the function as with: >
                        call Callback('one', 'two', 'name')
  
+ <             The function() call can be nested to add more arguments to the
+               Funcref.  The extra arguments are appended to the list of
+               arguments.  Example: >
+                       func Callback(arg1, arg2, name)
+                       ...
+                       let Func = function('Callback', ['one'])
+                       let Func2 = function(Func, ['two'])
+                       ...
+                       call Func2('name')
+ <             Invokes the function as with: >
+                       call Callback('one', 'two', 'name')
+ 
  <             The Dictionary is only useful when calling a "dict" function.
                In that case the {dict} is passed in as "self". Example: >
                        function Callback() dict
***************
*** 3859,3864 ****
--- 3916,3925 ----
                        let Func = function('Callback', context)
                        ...
                        call Func()     " will echo: called for example
+ <             The use of function() is not needed when there are no extra
+               arguments, these two are equivalent: >
+                       let Func = function('Callback', context)
+                       let Func = context.Callback
  
  <             The argument list and the Dictionary can be combined: >
                        function Callback(arg1, count) dict
*** ../vim-7.4.2136/src/version.c       2016-07-31 18:30:19.041018233 +0200
--- src/version.c       2016-08-01 15:24:17.452838262 +0200
***************
*** 765,766 ****
--- 765,768 ----
  {   /* Add new patch number below this line */
+ /**/
+     2137,
  /**/

-- 
MICHAEL PALIN PLAYED: 1ST SOLDIER WITH A KEEN INTEREST IN BIRDS, DENNIS, MR
                      DUCK (A VILLAGE CARPENTER WHO IS ALMOST KEENER THAN
                      ANYONE ELSE TO BURN WITCHES), THREE-HEADED KNIGHT, SIR
                      GALAHAD, KING OF SWAMP CASTLE, BROTHER MAYNARD'S ROOMATE
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// 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.

Raspunde prin e-mail lui