summaryrefslogtreecommitdiff
path: root/src/eval.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-06-02 17:46:20 +0200
committerBram Moolenaar <Bram@vim.org>2016-06-02 17:46:20 +0200
commit8e759ba8651428995b338b66c615367259f79766 (patch)
tree01e5e8849eb048d9709fc5176888a8b34bd045e0 /src/eval.c
parentae3f33040ba752e7f6b722d2fe2b2ebeeb8c56b4 (diff)
downloadvim-8e759ba8651428995b338b66c615367259f79766.zip
patch 7.4.1875
Problem: Comparing functions and partials doesn't work well. Solution: Add tests. (Nikolai Pavlov) Compare the dict and arguments in the partial. (closes #813)
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c104
1 files changed, 87 insertions, 17 deletions
diff --git a/src/eval.c b/src/eval.c
index 50d1cbae8..9adaa419f 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -4627,7 +4627,26 @@ eval4(char_u **arg, typval_T *rettv, int evaluate)
clear_tv(&var2);
return FAIL;
}
- n1 = tv_equal(rettv, &var2, FALSE, FALSE);
+ if ((rettv->v_type == VAR_PARTIAL
+ && rettv->vval.v_partial == NULL)
+ || (var2.v_type == VAR_PARTIAL
+ && var2.vval.v_partial == NULL))
+ /* when a partial is NULL assume not equal */
+ n1 = FALSE;
+ else if (type_is)
+ {
+ if (rettv->v_type == VAR_FUNC && var2.v_type == VAR_FUNC)
+ /* strings are considered the same if their value is
+ * the same */
+ n1 = tv_equal(rettv, &var2, ic, FALSE);
+ else if (rettv->v_type == VAR_PARTIAL
+ && var2.v_type == VAR_PARTIAL)
+ n1 = (rettv->vval.v_partial == var2.vval.v_partial);
+ else
+ n1 = FALSE;
+ }
+ else
+ n1 = tv_equal(rettv, &var2, ic, FALSE);
if (type == TYPE_NEQUAL)
n1 = !n1;
}
@@ -6258,6 +6277,58 @@ dict_equal(
static int tv_equal_recurse_limit;
+ static int
+func_equal(
+ typval_T *tv1,
+ typval_T *tv2,
+ int ic) /* ignore case */
+{
+ char_u *s1, *s2;
+ dict_T *d1, *d2;
+ int a1, a2;
+ int i;
+
+ /* 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)
+ {
+ if (s1 != s2)
+ return FALSE;
+ }
+ else if (STRCMP(s1, s2) != 0)
+ return FALSE;
+
+ /* empty dict and NULL dict is different */
+ d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
+ d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
+ if (d1 == NULL || d2 == NULL)
+ {
+ if (d1 != d2)
+ return FALSE;
+ }
+ else if (!dict_equal(d1, d2, ic, TRUE))
+ return FALSE;
+
+ /* empty list and no list considered the same */
+ a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
+ a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
+ if (a1 != a2)
+ return FALSE;
+ for (i = 0; i < a1; ++i)
+ if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
+ tv2->vval.v_partial->pt_argv + i, ic, TRUE))
+ return FALSE;
+
+ return TRUE;
+}
+
/*
* Return TRUE if "tv1" and "tv2" have the same value.
* Compares the items just like "==" would compare them, but strings and
@@ -6275,22 +6346,6 @@ tv_equal(
static int recursive_cnt = 0; /* catch recursive loops */
int r;
- /* For VAR_FUNC and VAR_PARTIAL only compare the function name. */
- if ((tv1->v_type == VAR_FUNC
- || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
- && (tv2->v_type == VAR_FUNC
- || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
- {
- s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
- : tv1->vval.v_partial->pt_name;
- s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
- : tv2->vval.v_partial->pt_name;
- return (s1 != NULL && s2 != NULL && STRCMP(s1, s2) == 0);
- }
-
- if (tv1->v_type != tv2->v_type)
- return FALSE;
-
/* Catch lists and dicts that have an endless loop by limiting
* recursiveness to a limit. We guess they are equal then.
* A fixed limit has the problem of still taking an awful long time.
@@ -6305,6 +6360,21 @@ tv_equal(
return TRUE;
}
+ /* For VAR_FUNC and VAR_PARTIAL only compare the function name. */
+ if ((tv1->v_type == VAR_FUNC
+ || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
+ && (tv2->v_type == VAR_FUNC
+ || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
+ {
+ ++recursive_cnt;
+ r = func_equal(tv1, tv2, ic);
+ --recursive_cnt;
+ return r;
+ }
+
+ if (tv1->v_type != tv2->v_type)
+ return FALSE;
+
switch (tv1->v_type)
{
case VAR_LIST: