To: vim_dev@googlegroups.com Subject: Patch 7.4.1577 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1577 Problem: Cannot pass "dict.Myfunc" around as a partial. Solution: Create a partial when expected. Files: src/eval.c, src/testdir/test_partial.vim *** ../vim-7.4.1576/src/eval.c 2016-03-15 13:33:50.709244886 +0100 --- src/eval.c 2016-03-15 19:19:48.733981126 +0100 *************** *** 110,115 **** --- 110,116 ---- #ifdef FEAT_FLOAT static char *e_float_as_string = N_("E806: using Float as a String"); #endif + static char *e_dict_both = N_("E924: can't have both a \"self\" dict and a partial: %s"); #define NAMESPACE_CHAR (char_u *)"abglstvw" *************** *** 8912,8919 **** name); break; case ERROR_BOTH: ! emsg_funcname(N_("E924: can't have both a \"self\" dict and a partial: %s"), ! name); break; } } --- 8913,8919 ---- name); break; case ERROR_BOTH: ! emsg_funcname(e_dict_both, name); break; } } *************** *** 11782,11793 **** { char_u *s; char_u *name; ! s = get_tv_string(&argvars[0]); ! if (s == NULL || *s == NUL || VIM_ISDIGIT(*s)) EMSG2(_(e_invarg2), s); /* Don't check an autoload name for existence here. */ ! else if (vim_strchr(s, AUTOLOAD_CHAR) == NULL && !function_exists(s)) EMSG2(_("E700: Unknown function: %s"), s); else { --- 11782,11810 ---- { char_u *s; char_u *name; + int use_string = FALSE; ! if (argvars[0].v_type == VAR_FUNC) ! { ! /* function(MyFunc, [arg], dict) */ ! s = argvars[0].vval.v_string; ! } ! else if (argvars[0].v_type == VAR_PARTIAL ! && argvars[0].vval.v_partial != NULL) ! /* function(dict.MyFunc, [arg]) */ ! s = argvars[0].vval.v_partial->pt_name; ! else ! { ! /* function('MyFunc', [arg], dict) */ ! s = get_tv_string(&argvars[0]); ! 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)) EMSG2(_("E700: Unknown function: %s"), s); else { *************** *** 11837,11842 **** --- 11854,11865 ---- vim_free(name); return; } + if (argvars[0].v_type == VAR_PARTIAL) + { + EMSG2(_(e_dict_both), name); + vim_free(name); + return; + } if (argvars[dict_idx].vval.v_dict == NULL) dict_idx = 0; } *************** *** 11880,11886 **** } } ! if (dict_idx > 0) { pt->pt_dict = argvars[dict_idx].vval.v_dict; ++pt->pt_dict->dv_refcount; --- 11903,11914 ---- } } ! if (argvars[0].v_type == VAR_PARTIAL) ! { ! pt->pt_dict = argvars[0].vval.v_partial->pt_dict; ! ++pt->pt_dict->dv_refcount; ! } ! else if (dict_idx > 0) { pt->pt_dict = argvars[dict_idx].vval.v_dict; ++pt->pt_dict->dv_refcount; *************** *** 21533,21539 **** rettv->v_type = VAR_UNKNOWN; /* Invoke the function. Recursive! */ ! if (rettv->v_type == VAR_PARTIAL) { pt = functv.vval.v_partial; s = pt->pt_name; --- 21561,21567 ---- rettv->v_type = VAR_UNKNOWN; /* Invoke the function. Recursive! */ ! if (functv.v_type == VAR_PARTIAL) { pt = functv.vval.v_partial; s = pt->pt_name; *************** *** 21582,21587 **** --- 21610,21632 ---- } } } + + 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_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; + } + } + dict_unref(selfdict); return ret; } *** ../vim-7.4.1576/src/testdir/test_partial.vim 2016-03-15 12:36:04.417428858 +0100 --- src/testdir/test_partial.vim 2016-03-15 19:29:43.767744915 +0100 *************** *** 50,52 **** --- 50,70 ---- call assert_equal("hello/xxx/yyy", Cb("xxx", "yyy")) call assert_fails('Cb("fff")', 'E492:') endfunc + + func Test_partial_implicit() + let dict = {'name': 'foo'} + func dict.MyFunc(arg) dict + return self.name . '/' . a:arg + endfunc + + call assert_equal('foo/bar', dict.MyFunc('bar')) + + call assert_fails('let func = dict.MyFunc', 'E704:') + let Func = dict.MyFunc + call assert_equal('foo/aaa', Func('aaa')) + + let Func = function(dict.MyFunc, ['bbb']) + call assert_equal('foo/bbb', Func()) + + call assert_fails('call function(dict.MyFunc, ["bbb"], dict)', 'E924:') + endfunc *** ../vim-7.4.1576/src/version.c 2016-03-15 18:23:50.464921252 +0100 --- src/version.c 2016-03-15 19:20:57.225262978 +0100 *************** *** 745,746 **** --- 745,748 ---- { /* Add new patch number below this line */ + /**/ + 1577, /**/ -- Never go to the toilet in a paperless office. /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 ///