0
0
mirror of https://github.com/vim/vim.git synced 2025-09-29 04:34:16 -04:00

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)
This commit is contained in:
Bram Moolenaar
2016-06-02 17:46:20 +02:00
parent ae3f33040b
commit 8e759ba865
3 changed files with 152 additions and 17 deletions

View File

@@ -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:

View File

@@ -316,3 +316,66 @@ func Test_get_partial_items()
call assert_equal([], get(Func, 'args'))
call assert_true(empty( get(Func, 'dict')))
endfunc
func Test_compare_partials()
let d1 = {}
let d2 = {}
function d1.f1() dict
endfunction
function d1.f2() dict
endfunction
let F1 = get(d1, 'f1')
let F2 = get(d1, 'f2')
let F1d1 = function(F1, d1)
let F2d1 = function(F2, d2)
let F1d1a1 = function(F1d1, [1])
let F1d1a12 = function(F1d1, [1, 2])
let F1a1 = function(F1, [1])
let F1a2 = function(F1, [2])
let F1d2 = function(F1, d2)
let d3 = {'f1': F1, 'f2': F2}
let F1d3 = function(F1, d3)
let F1ad1 = function(F1, [d1])
let F1ad3 = function(F1, [d3])
call assert_match('^function(''\d\+'')$', string(F1)) " Not a partial
call assert_match('^function(''\d\+'')$', string(F2)) " Not a partial
call assert_match('^function(''\d\+'', {.*})$', string(F1d1)) " A partial
call assert_match('^function(''\d\+'', {.*})$', string(F2d1)) " A partial
call assert_match('^function(''\d\+'', \[.*\])$', string(F1a1)) " No dict
" !=
let X = F1
call assert_false(F1 != X) " same function
let X = F1d1
call assert_false(F1d1 != X) " same partial
let X = F1d1a1
call assert_false(F1d1a1 != X) " same partial
let X = F1a1
call assert_false(F1a1 != X) " same partial
call assert_true(F1 != F2) " Different functions
call assert_true(F1 != F1d1) " Partial /= non-partial
call assert_true(F1d1a1 != F1d1a12) " Different number of arguments
call assert_true(F1a1 != F1d1a12) " One has no dict
call assert_true(F1a1 != F1a2) " Different arguments
call assert_true(F1d2 != F1d1) " Different dictionaries
call assert_false(F1d1 != F1d3) " Equal dictionaries, even though d1 isnot d3
" isnot, option 1
call assert_true(F1 isnot# F2) " Different functions
call assert_true(F1 isnot# F1d1) " Partial /= non-partial
call assert_true(F1d1 isnot# F1d3) " d1 isnot d3, even though d1 == d3
call assert_true(F1a1 isnot# F1d1a12) " One has no dict
call assert_true(F1a1 isnot# F1a2) " Different number of arguments
call assert_true(F1ad1 isnot# F1ad3) " In arguments d1 isnot d3
" isnot, option 2
call assert_true(F1 isnot# F2) " Different functions
call assert_true(F1 isnot# F1d1) " Partial /= non-partial
call assert_true(d1.f1 isnot# d1.f1) " handle_subscript creates new partial each time
endfunc

View File

@@ -753,6 +753,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1875,
/**/
1874,
/**/