Skip to content

Commit 97eb73c

Browse files
committed
Merge pull request adafruit#148 from pfalcon/list-cmp
Implement type virtual equality method support and implement comparisons for lists
2 parents 0226302 + 1945e60 commit 97eb73c

3 files changed

Lines changed: 121 additions & 0 deletions

File tree

py/obj.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
117117
} else if (MP_OBJ_IS_TYPE(o1, &str_type) && MP_OBJ_IS_TYPE(o2, &str_type)) {
118118
return mp_obj_str_get(o1) == mp_obj_str_get(o2);
119119
} else {
120+
mp_obj_base_t *o = o1;
121+
if (o->type->binary_op != NULL) {
122+
mp_obj_t r = o->type->binary_op(RT_COMPARE_OP_EQUAL, o1, o2);
123+
if (r != MP_OBJ_NULL) {
124+
return r == mp_const_true ? true : false;
125+
}
126+
}
120127
// TODO: Debugging helper
121128
printf("Equality for '%s' and '%s' types not yet implemented\n", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2));
122129
assert(0);

py/objlist.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,61 @@ static mp_obj_t list_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args
6262
return NULL;
6363
}
6464

65+
// Don't pass RT_COMPARE_OP_NOT_EQUAL here
66+
static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
67+
assert(MP_OBJ_IS_TYPE(self_in, &list_type));
68+
if (!MP_OBJ_IS_TYPE(another_in, &list_type)) {
69+
return false;
70+
}
71+
mp_obj_list_t *self = self_in;
72+
mp_obj_list_t *another = another_in;
73+
if (op == RT_COMPARE_OP_EQUAL && self->len != another->len) {
74+
return false;
75+
}
76+
77+
// Let's deal only with > & >=
78+
if (op == RT_COMPARE_OP_LESS || op == RT_COMPARE_OP_LESS_EQUAL) {
79+
mp_obj_t t = self;
80+
self = another;
81+
another = t;
82+
if (op == RT_COMPARE_OP_LESS) {
83+
op = RT_COMPARE_OP_MORE;
84+
} else {
85+
op = RT_COMPARE_OP_MORE_EQUAL;
86+
}
87+
}
88+
89+
int len = self->len < another->len ? self->len : another->len;
90+
bool eq_status = true; // empty lists are equal
91+
bool rel_status;
92+
for (int i = 0; i < len; i++) {
93+
eq_status = mp_obj_equal(self->items[i], another->items[i]);
94+
if (op == RT_COMPARE_OP_EQUAL && !eq_status) {
95+
return false;
96+
}
97+
rel_status = (rt_binary_op(op, self->items[i], another->items[i]) == mp_const_true);
98+
if (!eq_status && !rel_status) {
99+
return false;
100+
}
101+
}
102+
103+
// If we had tie in the last element...
104+
if (eq_status) {
105+
// ... and we have lists of different lengths...
106+
if (self->len != another->len) {
107+
if (self->len < another->len) {
108+
// ... then longer list length wins (we deal only with >)
109+
return false;
110+
}
111+
} else if (op == RT_COMPARE_OP_MORE) {
112+
// Otherwise, if we have strict relation, equality means failure
113+
return false;
114+
}
115+
}
116+
117+
return true;
118+
}
119+
65120
static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
66121
mp_obj_list_t *o = lhs;
67122
switch (op) {
@@ -105,6 +160,15 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
105160
}
106161
return s;
107162
}
163+
case RT_COMPARE_OP_EQUAL:
164+
case RT_COMPARE_OP_LESS:
165+
case RT_COMPARE_OP_LESS_EQUAL:
166+
case RT_COMPARE_OP_MORE:
167+
case RT_COMPARE_OP_MORE_EQUAL:
168+
return MP_BOOL(list_cmp_helper(op, lhs, rhs));
169+
case RT_COMPARE_OP_NOT_EQUAL:
170+
return MP_BOOL(!list_cmp_helper(RT_COMPARE_OP_EQUAL, lhs, rhs));
171+
108172
default:
109173
// op not supported
110174
return NULL;

tests/basics/tests/list_compare.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
print([] == [])
2+
print([] > [])
3+
print([] < [])
4+
print([] == [1])
5+
print([1] == [])
6+
print([] > [1])
7+
print([1] > [])
8+
print([] < [1])
9+
print([1] < [])
10+
print([] >= [1])
11+
print([1] >= [])
12+
print([] <= [1])
13+
print([1] <= [])
14+
15+
print([1] == [1])
16+
print([1] != [1])
17+
print([1] == [2])
18+
print([1] == [1, 0])
19+
20+
print([1] > [1])
21+
print([1] > [2])
22+
print([2] > [1])
23+
print([1, 0] > [1])
24+
print([1, -1] > [1])
25+
print([1] > [1, 0])
26+
print([1] > [1, -1])
27+
28+
print([1] < [1])
29+
print([2] < [1])
30+
print([1] < [2])
31+
print([1] < [1, 0])
32+
print([1] < [1, -1])
33+
print([1, 0] < [1])
34+
print([1, -1] < [1])
35+
36+
print([1] >= [1])
37+
print([1] >= [2])
38+
print([2] >= [1])
39+
print([1, 0] >= [1])
40+
print([1, -1] >= [1])
41+
print([1] >= [1, 0])
42+
print([1] >= [1, -1])
43+
44+
print([1] <= [1])
45+
print([2] <= [1])
46+
print([1] <= [2])
47+
print([1] <= [1, 0])
48+
print([1] <= [1, -1])
49+
print([1, 0] <= [1])
50+
print([1, -1] <= [1])

0 commit comments

Comments
 (0)