Patch 7.4.1581
Problem:    Using ":call dict.func()" where the function is a partial does
            not work.  Using "dict.func()" where the function does not take a
            Dictionary does not work.
Solution:   Handle partial properly in ":call". (Yasuhiro Matsumoto)
Files:      src/eval.c, src/testdir/test_partial.vim, src/testdir/test55.ok


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

-- 
"I don’t know how to make a screenshot" - Richard Stallman, July 2002
(when asked to send a screenshot of his desktop for unix.se)

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui