From 7ccd1a2e858dbb2ac7fb09971dfcbfad62baa677 Mon Sep 17 00:00:00 2001 From: Yinzuo Jiang Date: Thu, 4 Jul 2024 17:20:53 +0200 Subject: patch 9.1.0524: the recursive parameter in the *_equal functions can be removed Problem: the recursive parameter in the *_equal functions can be removed Solution: Remove the recursive parameter in dict_equal(), list_equal() object_equal and tv_equal(). Use a comparison of the static var recursive_cnt == 0 to determine whether or not tv_equal() has been called recursively (Yinzuo Jiang). closes: #15070 Signed-off-by: Yinzuo Jiang Signed-off-by: Christian Brabandt --- src/dict.c | 7 +++---- src/evalfunc.c | 4 ++-- src/list.c | 7 +++---- src/proto/dict.pro | 2 +- src/proto/list.pro | 2 +- src/proto/typval.pro | 2 +- src/proto/vim9class.pro | 2 +- src/testdir/test_listdict.vim | 13 +++++++++++++ src/testing.c | 4 ++-- src/typval.c | 26 ++++++++++++-------------- src/version.c | 2 ++ src/vim9class.c | 5 ++--- 12 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/dict.c b/src/dict.c index bf45b0b928..d3636f3bc9 100644 --- a/src/dict.c +++ b/src/dict.c @@ -1222,8 +1222,7 @@ dict_lookup(hashitem_T *hi) dict_equal( dict_T *d1, dict_T *d2, - int ic, // ignore case for strings - int recursive) // TRUE when used recursively + int ic) // ignore case for strings { hashitem_T *hi; dictitem_T *item2; @@ -1247,7 +1246,7 @@ dict_equal( item2 = dict_find(d2, hi->hi_key, -1); if (item2 == NULL) return FALSE; - if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic, recursive)) + if (!tv_equal(&HI2DI(hi)->di_tv, &item2->di_tv, ic)) return FALSE; --todo; } @@ -1275,7 +1274,7 @@ dict_count(dict_T *d, typval_T *needle, int ic) if (!HASHITEM_EMPTY(hi)) { --todo; - if (tv_equal(&HI2DI(hi)->di_tv, needle, ic, FALSE)) + if (tv_equal(&HI2DI(hi)->di_tv, needle, ic)) ++n; } } diff --git a/src/evalfunc.c b/src/evalfunc.c index d18d50a284..c9480f9f64 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -7535,7 +7535,7 @@ f_index(typval_T *argvars, typval_T *rettv) { tv.v_type = VAR_NUMBER; tv.vval.v_number = blob_get(b, idx); - if (tv_equal(&tv, &argvars[1], ic, FALSE)) + if (tv_equal(&tv, &argvars[1], ic)) { rettv->vval.v_number = idx; return; @@ -7568,7 +7568,7 @@ f_index(typval_T *argvars, typval_T *rettv) } for ( ; item != NULL; item = item->li_next, ++idx) - if (tv_equal(&item->li_tv, &argvars[1], ic, FALSE)) + if (tv_equal(&item->li_tv, &argvars[1], ic)) { rettv->vval.v_number = idx; break; diff --git a/src/list.c b/src/list.c index 9479b4b6ab..36ce494df8 100644 --- a/src/list.c +++ b/src/list.c @@ -365,8 +365,7 @@ list_len(list_T *l) list_equal( list_T *l1, list_T *l2, - int ic, // ignore case for strings - int recursive) // TRUE when used recursively + int ic) // ignore case for strings { listitem_T *item1, *item2; @@ -386,7 +385,7 @@ list_equal( for (item1 = l1->lv_first, item2 = l2->lv_first; item1 != NULL && item2 != NULL; item1 = item1->li_next, item2 = item2->li_next) - if (!tv_equal(&item1->li_tv, &item2->li_tv, ic, recursive)) + if (!tv_equal(&item1->li_tv, &item2->li_tv, ic)) return FALSE; return item1 == NULL && item2 == NULL; } @@ -2727,7 +2726,7 @@ list_count(list_T *l, typval_T *needle, long idx, int ic) } for ( ; li != NULL; li = li->li_next) - if (tv_equal(&li->li_tv, needle, ic, FALSE)) + if (tv_equal(&li->li_tv, needle, ic)) ++n; return n; diff --git a/src/proto/dict.pro b/src/proto/dict.pro index 346e1d5411..b1ceeccd4c 100644 --- a/src/proto/dict.pro +++ b/src/proto/dict.pro @@ -40,7 +40,7 @@ int eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal); int eval_lit_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg); void dict_extend(dict_T *d1, dict_T *d2, char_u *action, char *func_name); dictitem_T *dict_lookup(hashitem_T *hi); -int dict_equal(dict_T *d1, dict_T *d2, int ic, int recursive); +int dict_equal(dict_T *d1, dict_T *d2, int ic); long dict_count(dict_T *d, typval_T *needle, int ic); void dict_extend_func(typval_T *argvars, type_T *type, char *func_name, char_u *arg_errmsg, int is_new, typval_T *rettv); void dict_filter_map(dict_T *d, filtermap_T filtermap, type_T *argtype, char *func_name, char_u *arg_errmsg, typval_T *expr, typval_T *rettv); diff --git a/src/proto/list.pro b/src/proto/list.pro index 1659b8fded..27bea5e878 100644 --- a/src/proto/list.pro +++ b/src/proto/list.pro @@ -16,7 +16,7 @@ listitem_T *listitem_alloc(void); void listitem_free(list_T *l, listitem_T *item); void listitem_remove(list_T *l, listitem_T *item); long list_len(list_T *l); -int list_equal(list_T *l1, list_T *l2, int ic, int recursive); +int list_equal(list_T *l1, list_T *l2, int ic); listitem_T *list_find(list_T *l, long n); long list_find_nr(list_T *l, long idx, int *errorp); char_u *list_find_str(list_T *l, long idx); diff --git a/src/proto/typval.pro b/src/proto/typval.pro index b6ea1310fd..c25a949e4a 100644 --- a/src/proto/typval.pro +++ b/src/proto/typval.pro @@ -75,7 +75,7 @@ int typval_compare_func(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, i int typval_compare_string(typval_T *tv1, typval_T *tv2, exprtype_T type, int ic, int *res); char_u *typval_tostring(typval_T *arg, int quotes); int tv_islocked(typval_T *tv); -int tv_equal(typval_T *tv1, typval_T *tv2, int ic, int recursive); +int tv_equal(typval_T *tv1, typval_T *tv2, int ic); int eval_option(char_u **arg, typval_T *rettv, int evaluate); int eval_number(char_u **arg, typval_T *rettv, int evaluate, int want_string); int eval_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate); diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro index 4c733d5235..c87fffbc8a 100644 --- a/src/proto/vim9class.pro +++ b/src/proto/vim9class.pro @@ -40,7 +40,7 @@ int is_class_name(char_u *name, typval_T *rettv); void protected_method_access_errmsg(char_u *method_name); int object_empty(object_T *obj); int object_len(object_T *obj); -int object_equal(object_T *o1, object_T *o2, int ic, int recursive); +int object_equal(object_T *o1, object_T *o2, int ic); char_u *object2string(object_T *obj, char_u *numbuf, int copyID, int echo_style, int restore_copyID, int composite_val); int class_instance_of(class_T *cl, class_T *other_cl); void f_instanceof(typval_T *argvars, typval_T *rettv); diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim index f2d4a3e753..0a4f88c4e5 100644 --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -1147,6 +1147,19 @@ func Test_listdict_compare() call assert_fails('echo {} =~ {}', 'E736:') endfunc +func Test_recursive_listdict_compare() + let l1 = [0, 1] + let l1[0] = l1 + let l2 = [0, 1] + let l2[0] = l2 + call assert_true(l1 == l2) + let d1 = {0: 0, 1: 1} + let d1[0] = d1 + let d2 = {0: 0, 1: 1} + let d2[0] = d2 + call assert_true(d1 == d2) +endfunc + " compare complex recursively linked list and dict func Test_listdict_compare_complex() let lines =<< trim END diff --git a/src/testing.c b/src/testing.c index 3e9e07704b..18b8e788eb 100644 --- a/src/testing.c +++ b/src/testing.c @@ -187,7 +187,7 @@ fill_assert_error( { item2 = dict_find(got_d, hi->hi_key, -1); if (item2 == NULL || !tv_equal(&HI2DI(hi)->di_tv, - &item2->di_tv, FALSE, FALSE)) + &item2->di_tv, FALSE)) { // item of exp_d not present in got_d or values differ. dict_add_tv(exp_tv->vval.v_dict, @@ -262,7 +262,7 @@ assert_equal_common(typval_T *argvars, assert_type_T atype) { garray_T ga; - if (tv_equal(&argvars[0], &argvars[1], FALSE, FALSE) + if (tv_equal(&argvars[0], &argvars[1], FALSE) != (atype == ASSERT_EQUAL)) { prepare_assert_error(&ga); diff --git a/src/typval.c b/src/typval.c index d1fa227d1d..164b7a98ba 100644 --- a/src/typval.c +++ b/src/typval.c @@ -1605,8 +1605,7 @@ typval_compare_list( } else { - val = list_equal(tv1->vval.v_list, tv2->vval.v_list, - ic, FALSE); + val = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic); if (type == EXPR_NEQUAL) val = !val; } @@ -1750,7 +1749,7 @@ typval_compare_object( return OK; } - *res = object_equal(obj1, obj2, ic, FALSE) ? res_match : !res_match; + *res = object_equal(obj1, obj2, ic) ? res_match : !res_match; return OK; } @@ -1787,7 +1786,7 @@ typval_compare_dict( } else { - val = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, FALSE); + val = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic); if (type == EXPR_NEQUAL) val = !val; } @@ -1826,14 +1825,14 @@ typval_compare_func( if (tv1->v_type == VAR_FUNC && tv2->v_type == VAR_FUNC) // strings are considered the same if their value is // the same - val = tv_equal(tv1, tv2, ic, FALSE); + val = tv_equal(tv1, tv2, ic); else if (tv1->v_type == VAR_PARTIAL && tv2->v_type == VAR_PARTIAL) val = (tv1->vval.v_partial == tv2->vval.v_partial); else val = FALSE; } else - val = tv_equal(tv1, tv2, ic, FALSE); + val = tv_equal(tv1, tv2, ic); if (type == EXPR_NEQUAL || type == EXPR_ISNOT) val = !val; *res = val; @@ -1988,7 +1987,7 @@ func_equal( if (d1 != d2) return FALSE; } - else if (!dict_equal(d1, d2, ic, TRUE)) + else if (!dict_equal(d1, d2, ic)) return FALSE; // empty list and no list considered the same @@ -1998,7 +1997,7 @@ func_equal( 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)) + tv2->vval.v_partial->pt_argv + i, ic)) return FALSE; return TRUE; @@ -2013,8 +2012,7 @@ func_equal( tv_equal( typval_T *tv1, typval_T *tv2, - int ic, // ignore case - int recursive) // TRUE when used recursively + int ic) // ignore case { char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; char_u *s1, *s2; @@ -2028,7 +2026,7 @@ tv_equal( // Reduce the limit every time running into it. That should work fine for // deeply linked structures that are not recursively linked and catch // recursiveness quickly. - if (!recursive) + if (recursive_cnt == 0) tv_equal_recurse_limit = 1000; if (recursive_cnt >= tv_equal_recurse_limit) { @@ -2058,13 +2056,13 @@ tv_equal( { case VAR_LIST: ++recursive_cnt; - r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic, TRUE); + r = list_equal(tv1->vval.v_list, tv2->vval.v_list, ic); --recursive_cnt; return r; case VAR_DICT: ++recursive_cnt; - r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic, TRUE); + r = dict_equal(tv1->vval.v_dict, tv2->vval.v_dict, ic); --recursive_cnt; return r; @@ -2100,7 +2098,7 @@ tv_equal( case VAR_OBJECT: ++recursive_cnt; - r = object_equal(tv1->vval.v_object, tv2->vval.v_object, ic, TRUE); + r = object_equal(tv1->vval.v_object, tv2->vval.v_object, ic); --recursive_cnt; return r; diff --git a/src/version.c b/src/version.c index 6588f2f9ad..47b60760be 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 524, /**/ 523, /**/ diff --git a/src/vim9class.c b/src/vim9class.c index 78f5ab8ada..933708288f 100644 --- a/src/vim9class.c +++ b/src/vim9class.c @@ -3849,8 +3849,7 @@ object_len(object_T *obj) object_equal( object_T *o1, object_T *o2, - int ic, // ignore case for strings - int recursive) // TRUE when used recursively + int ic) // ignore case for strings { class_T *cl1, *cl2; @@ -3866,7 +3865,7 @@ object_equal( return FALSE; for (int i = 0; i < cl1->class_obj_member_count; ++i) - if (!tv_equal((typval_T *)(o1 + 1) + i, (typval_T *)(o2 + 1) + i, ic, recursive)) + if (!tv_equal((typval_T *)(o1 + 1) + i, (typval_T *)(o2 + 1) + i, ic)) return FALSE; return TRUE; -- cgit v1.2.3