1
0
forked from aniani/vim

patch 9.0.1134: comparing objects uses identity instead of equality

Problem:    Comparing objects uses identity instead of equality.
Solution:   Compare the object values.
This commit is contained in:
Bram Moolenaar
2023-01-02 20:32:24 +00:00
parent a9fa8c58fb
commit bcf31ec36b
8 changed files with 178 additions and 10 deletions

View File

@@ -1310,6 +1310,24 @@ typval_compare(
}
n1 = res;
}
else if (tv1->v_type == VAR_CLASS || tv2->v_type == VAR_CLASS)
{
if (typval_compare_class(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
return FAIL;
}
n1 = res;
}
else if (tv1->v_type == VAR_OBJECT || tv2->v_type == VAR_OBJECT)
{
if (typval_compare_object(tv1, tv2, type, ic, &res) == FAIL)
{
clear_tv(tv1);
return FAIL;
}
n1 = res;
}
else if (tv1->v_type == VAR_DICT || tv2->v_type == VAR_DICT)
{
if (typval_compare_dict(tv1, tv2, type, ic, &res) == FAIL)
@@ -1579,6 +1597,77 @@ typval_compare_blob(
return OK;
}
/*
* Compare "tv1" to "tv2" as classes according to "type".
* Put the result, false or true, in "res".
* Return FAIL and give an error message when the comparison can't be done.
*/
int
typval_compare_class(
typval_T *tv1,
typval_T *tv2,
exprtype_T type UNUSED,
int ic UNUSED,
int *res)
{
// TODO: use "type"
*res = tv1->vval.v_class == tv2->vval.v_class;
return OK;
}
/*
* Compare "tv1" to "tv2" as objects according to "type".
* Put the result, false or true, in "res".
* Return FAIL and give an error message when the comparison can't be done.
*/
int
typval_compare_object(
typval_T *tv1,
typval_T *tv2,
exprtype_T type,
int ic,
int *res)
{
int res_match = type == EXPR_EQUAL || type == EXPR_IS ? TRUE : FALSE;
if (tv1->vval.v_object == NULL && tv2->vval.v_object == NULL)
{
*res = res_match;
return OK;
}
if (tv1->vval.v_object == NULL || tv2->vval.v_object == NULL)
{
*res = !res_match;
return OK;
}
class_T *cl1 = tv1->vval.v_object->obj_class;
class_T *cl2 = tv2->vval.v_object->obj_class;
if (cl1 != cl2 || cl1 == NULL || cl2 == NULL)
{
*res = !res_match;
return OK;
}
object_T *obj1 = tv1->vval.v_object;
object_T *obj2 = tv2->vval.v_object;
if (type == EXPR_IS || type == EXPR_ISNOT)
{
*res = obj1 == obj2 ? res_match : !res_match;
return OK;
}
for (int i = 0; i < cl1->class_obj_member_count; ++i)
if (!tv_equal((typval_T *)(obj1 + 1) + i,
(typval_T *)(obj2 + 1) + i, ic, TRUE))
{
*res = !res_match;
return OK;
}
*res = res_match;
return OK;
}
/*
* Compare "tv1" to "tv2" as dictionaries according to "type" and "ic".
* Put the result, false or true, in "res".
@@ -1920,11 +2009,12 @@ tv_equal(
return tv1->vval.v_instr == tv2->vval.v_instr;
case VAR_CLASS:
// A class only exists once, equality is identity.
return tv1->vval.v_class == tv2->vval.v_class;
case VAR_OBJECT:
// TODO: compare values
return tv1->vval.v_object == tv2->vval.v_object;
(void)typval_compare_object(tv1, tv2, EXPR_EQUAL, ic, &r);
return r;
case VAR_PARTIAL:
return tv1->vval.v_partial == tv2->vval.v_partial;