diff src/eval.c @ 9416:cbf052ccb120 v7.4.1989

commit https://github.com/vim/vim/commit/b33c7eb5b813cb631b2b0ca5c4029e1788a09bde Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jul 4 22:29:49 2016 +0200 patch 7.4.1989 Problem: filter() and map() only accept a string argument. Solution: Implement using a Funcref argument (Yasuhiro Matsumoto, Ken Takata)
author Christian Brabandt <cb@256bit.org>
date Mon, 04 Jul 2016 22:30:05 +0200
parents 32e34e574716
children f93704b11e43
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -6375,7 +6375,8 @@ tv_equal(
 	return TRUE;
     }
 
-    /* For VAR_FUNC and VAR_PARTIAL only compare the function name. */
+    /* For VAR_FUNC and VAR_PARTIAL compare the function name, bound dict and
+     * arguments. */
     if ((tv1->v_type == VAR_FUNC
 		|| (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
 	    && (tv2->v_type == VAR_FUNC
@@ -11852,7 +11853,7 @@ findfilendir(
 }
 
 static void filter_map(typval_T *argvars, typval_T *rettv, int map);
-static int filter_map_one(typval_T *tv, char_u *expr, int map, int *remp);
+static int filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp);
 
 /*
  * Implementation of map() and filter().
@@ -11860,8 +11861,7 @@ static int filter_map_one(typval_T *tv, 
     static void
 filter_map(typval_T *argvars, typval_T *rettv, int map)
 {
-    char_u	buf[NUMBUFLEN];
-    char_u	*expr;
+    typval_T	*expr;
     listitem_T	*li, *nli;
     list_T	*l = NULL;
     dictitem_T	*di;
@@ -11896,14 +11896,13 @@ filter_map(typval_T *argvars, typval_T *
 	return;
     }
 
-    expr = get_tv_string_buf_chk(&argvars[1], buf);
+    expr = &argvars[1];
     /* On type errors, the preceding call has already displayed an error
      * message.  Avoid a misleading error message for an empty string that
      * was not passed as argument. */
-    if (expr != NULL)
+    if (expr->v_type != VAR_UNKNOWN)
     {
 	prepare_vimvar(VV_VAL, &save_val);
-	expr = skipwhite(expr);
 
 	/* We reset "did_emsg" to be able to detect whether an error
 	 * occurred during evaluation of the expression. */
@@ -11975,21 +11974,44 @@ filter_map(typval_T *argvars, typval_T *
 }
 
     static int
-filter_map_one(typval_T *tv, char_u *expr, int map, int *remp)
+filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp)
 {
     typval_T	rettv;
+    typval_T	argv[3];
     char_u	*s;
     int		retval = FAIL;
+    int		dummy;
 
     copy_tv(tv, &vimvars[VV_VAL].vv_tv);
-    s = expr;
-    if (eval1(&s, &rettv, TRUE) == FAIL)
-	goto theend;
-    if (*s != NUL)  /* check for trailing chars after expr */
-    {
-	EMSG2(_(e_invexpr2), s);
-	clear_tv(&rettv);
-	goto theend;
+    argv[0] = vimvars[VV_KEY].vv_tv;
+    argv[1] = vimvars[VV_VAL].vv_tv;
+    s = expr->vval.v_string;
+    if (expr->v_type == VAR_FUNC)
+    {
+	if (call_func(s, (int)STRLEN(s),
+		    &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL, NULL) == FAIL)
+	    goto theend;
+    }
+    else if (expr->v_type == VAR_PARTIAL)
+    {
+	partial_T   *partial = expr->vval.v_partial;
+
+	s = partial->pt_name;
+	if (call_func(s, (int)STRLEN(s),
+		    &rettv, 2, argv, 0L, 0L, &dummy, TRUE, partial, NULL)
+								      == FAIL)
+	    goto theend;
+    }
+    else
+    {
+	s = skipwhite(s);
+	if (eval1(&s, &rettv, TRUE) == FAIL)
+	    goto theend;
+	if (*s != NUL)  /* check for trailing chars after expr */
+	{
+	    EMSG2(_(e_invexpr2), s);
+	    goto theend;
+	}
     }
     if (map)
     {