comparison src/eval.c @ 9183:988c8ab557bf v7.4.1875

commit https://github.com/vim/vim/commit/8e759ba8651428995b338b66c615367259f79766 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jun 2 17:46:20 2016 +0200 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 https://github.com/vim/vim/issues/813)
author Christian Brabandt <cb@256bit.org>
date Thu, 02 Jun 2016 18:00:07 +0200
parents 0ea97a753a2d
children 9495e43a800d
comparison
equal deleted inserted replaced
9182:d0a54c4069ab 9183:988c8ab557bf
4625 EMSG(_("E694: Invalid operation for Funcrefs")); 4625 EMSG(_("E694: Invalid operation for Funcrefs"));
4626 clear_tv(rettv); 4626 clear_tv(rettv);
4627 clear_tv(&var2); 4627 clear_tv(&var2);
4628 return FAIL; 4628 return FAIL;
4629 } 4629 }
4630 n1 = tv_equal(rettv, &var2, FALSE, FALSE); 4630 if ((rettv->v_type == VAR_PARTIAL
4631 && rettv->vval.v_partial == NULL)
4632 || (var2.v_type == VAR_PARTIAL
4633 && var2.vval.v_partial == NULL))
4634 /* when a partial is NULL assume not equal */
4635 n1 = FALSE;
4636 else if (type_is)
4637 {
4638 if (rettv->v_type == VAR_FUNC && var2.v_type == VAR_FUNC)
4639 /* strings are considered the same if their value is
4640 * the same */
4641 n1 = tv_equal(rettv, &var2, ic, FALSE);
4642 else if (rettv->v_type == VAR_PARTIAL
4643 && var2.v_type == VAR_PARTIAL)
4644 n1 = (rettv->vval.v_partial == var2.vval.v_partial);
4645 else
4646 n1 = FALSE;
4647 }
4648 else
4649 n1 = tv_equal(rettv, &var2, ic, FALSE);
4631 if (type == TYPE_NEQUAL) 4650 if (type == TYPE_NEQUAL)
4632 n1 = !n1; 4651 n1 = !n1;
4633 } 4652 }
4634 4653
4635 #ifdef FEAT_FLOAT 4654 #ifdef FEAT_FLOAT
6256 return TRUE; 6275 return TRUE;
6257 } 6276 }
6258 6277
6259 static int tv_equal_recurse_limit; 6278 static int tv_equal_recurse_limit;
6260 6279
6280 static int
6281 func_equal(
6282 typval_T *tv1,
6283 typval_T *tv2,
6284 int ic) /* ignore case */
6285 {
6286 char_u *s1, *s2;
6287 dict_T *d1, *d2;
6288 int a1, a2;
6289 int i;
6290
6291 /* empty and NULL function name considered the same */
6292 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
6293 : tv1->vval.v_partial->pt_name;
6294 if (s1 != NULL && *s1 == NUL)
6295 s1 = NULL;
6296 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
6297 : tv2->vval.v_partial->pt_name;
6298 if (s2 != NULL && *s2 == NUL)
6299 s2 = NULL;
6300 if (s1 == NULL || s2 == NULL)
6301 {
6302 if (s1 != s2)
6303 return FALSE;
6304 }
6305 else if (STRCMP(s1, s2) != 0)
6306 return FALSE;
6307
6308 /* empty dict and NULL dict is different */
6309 d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
6310 d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
6311 if (d1 == NULL || d2 == NULL)
6312 {
6313 if (d1 != d2)
6314 return FALSE;
6315 }
6316 else if (!dict_equal(d1, d2, ic, TRUE))
6317 return FALSE;
6318
6319 /* empty list and no list considered the same */
6320 a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
6321 a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
6322 if (a1 != a2)
6323 return FALSE;
6324 for (i = 0; i < a1; ++i)
6325 if (!tv_equal(tv1->vval.v_partial->pt_argv + i,
6326 tv2->vval.v_partial->pt_argv + i, ic, TRUE))
6327 return FALSE;
6328
6329 return TRUE;
6330 }
6331
6261 /* 6332 /*
6262 * Return TRUE if "tv1" and "tv2" have the same value. 6333 * Return TRUE if "tv1" and "tv2" have the same value.
6263 * Compares the items just like "==" would compare them, but strings and 6334 * Compares the items just like "==" would compare them, but strings and
6264 * numbers are different. Floats and numbers are also different. 6335 * numbers are different. Floats and numbers are also different.
6265 */ 6336 */
6272 { 6343 {
6273 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN]; 6344 char_u buf1[NUMBUFLEN], buf2[NUMBUFLEN];
6274 char_u *s1, *s2; 6345 char_u *s1, *s2;
6275 static int recursive_cnt = 0; /* catch recursive loops */ 6346 static int recursive_cnt = 0; /* catch recursive loops */
6276 int r; 6347 int r;
6277
6278 /* For VAR_FUNC and VAR_PARTIAL only compare the function name. */
6279 if ((tv1->v_type == VAR_FUNC
6280 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
6281 && (tv2->v_type == VAR_FUNC
6282 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
6283 {
6284 s1 = tv1->v_type == VAR_FUNC ? tv1->vval.v_string
6285 : tv1->vval.v_partial->pt_name;
6286 s2 = tv2->v_type == VAR_FUNC ? tv2->vval.v_string
6287 : tv2->vval.v_partial->pt_name;
6288 return (s1 != NULL && s2 != NULL && STRCMP(s1, s2) == 0);
6289 }
6290
6291 if (tv1->v_type != tv2->v_type)
6292 return FALSE;
6293 6348
6294 /* Catch lists and dicts that have an endless loop by limiting 6349 /* Catch lists and dicts that have an endless loop by limiting
6295 * recursiveness to a limit. We guess they are equal then. 6350 * recursiveness to a limit. We guess they are equal then.
6296 * A fixed limit has the problem of still taking an awful long time. 6351 * A fixed limit has the problem of still taking an awful long time.
6297 * Reduce the limit every time running into it. That should work fine for 6352 * Reduce the limit every time running into it. That should work fine for
6302 if (recursive_cnt >= tv_equal_recurse_limit) 6357 if (recursive_cnt >= tv_equal_recurse_limit)
6303 { 6358 {
6304 --tv_equal_recurse_limit; 6359 --tv_equal_recurse_limit;
6305 return TRUE; 6360 return TRUE;
6306 } 6361 }
6362
6363 /* For VAR_FUNC and VAR_PARTIAL only compare the function name. */
6364 if ((tv1->v_type == VAR_FUNC
6365 || (tv1->v_type == VAR_PARTIAL && tv1->vval.v_partial != NULL))
6366 && (tv2->v_type == VAR_FUNC
6367 || (tv2->v_type == VAR_PARTIAL && tv2->vval.v_partial != NULL)))
6368 {
6369 ++recursive_cnt;
6370 r = func_equal(tv1, tv2, ic);
6371 --recursive_cnt;
6372 return r;
6373 }
6374
6375 if (tv1->v_type != tv2->v_type)
6376 return FALSE;
6307 6377
6308 switch (tv1->v_type) 6378 switch (tv1->v_type)
6309 { 6379 {
6310 case VAR_LIST: 6380 case VAR_LIST:
6311 ++recursive_cnt; 6381 ++recursive_cnt;