blob: 9a7e6751f5987d0146ffaf3505cea73103e24145 [file] [log] [blame]
xbeefe34222014-03-16 00:14:26 -07001#include <stdbool.h>
John R. Lenton3b0bd872014-01-12 15:56:25 +00002#include <string.h>
Damiend99b0522013-12-21 18:17:45 +00003#include <assert.h>
4
5#include "nlr.h"
6#include "misc.h"
7#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +00008#include "qstr.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "obj.h"
Damien George71c51812014-01-04 20:21:15 +000010#include "runtime.h"
John R. Lentonc1bef212014-01-11 12:39:33 +000011#include "runtime0.h"
Damiend99b0522013-12-21 18:17:45 +000012
13typedef struct _mp_obj_set_t {
14 mp_obj_base_t base;
15 mp_set_t set;
16} mp_obj_set_t;
17
John R. Lenton0ce03b42014-01-12 15:17:42 +000018typedef struct _mp_obj_set_it_t {
19 mp_obj_base_t base;
20 mp_obj_set_t *set;
21 machine_uint_t cur;
22} mp_obj_set_it_t;
23
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020024STATIC mp_obj_t set_it_iternext(mp_obj_t self_in);
John R. Lenton0ce03b42014-01-12 15:17:42 +000025
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020026STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
Damiend99b0522013-12-21 18:17:45 +000027 mp_obj_set_t *self = self_in;
John R. Lenton7244a142014-01-12 23:37:45 +000028 if (self->set.used == 0) {
29 print(env, "set()");
30 return;
31 }
Damiend99b0522013-12-21 18:17:45 +000032 bool first = true;
33 print(env, "{");
34 for (int i = 0; i < self->set.alloc; i++) {
Damien George8b0535e2014-04-05 21:53:54 +010035 if (MP_SET_SLOT_IS_FILLED(&self->set, i)) {
Damiend99b0522013-12-21 18:17:45 +000036 if (!first) {
37 print(env, ", ");
38 }
39 first = false;
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020040 mp_obj_print_helper(print, env, self->set.table[i], PRINT_REPR);
Damiend99b0522013-12-21 18:17:45 +000041 }
42 }
43 print(env, "}");
44}
45
John R. Lentonc1bef212014-01-11 12:39:33 +000046
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020047STATIC mp_obj_t set_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
Damien George20006db2014-01-18 14:10:48 +000048 // TODO check n_kw == 0
49
Damien George71c51812014-01-04 20:21:15 +000050 switch (n_args) {
51 case 0:
52 // return a new, empty set
53 return mp_obj_new_set(0, NULL);
54
55 case 1:
56 {
57 // 1 argument, an iterable from which we make a new set
58 mp_obj_t set = mp_obj_new_set(0, NULL);
Damien Georged17926d2014-03-30 13:35:08 +010059 mp_obj_t iterable = mp_getiter(args[0]);
Damien George71c51812014-01-04 20:21:15 +000060 mp_obj_t item;
Damien Georged17926d2014-03-30 13:35:08 +010061 while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) {
Damien George71c51812014-01-04 20:21:15 +000062 mp_obj_set_store(set, item);
63 }
64 return set;
65 }
66
67 default:
Damien Georgeea13f402014-04-05 18:32:08 +010068 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "set takes at most 1 argument, %d given", n_args));
Damien George71c51812014-01-04 20:21:15 +000069 }
70}
71
Damien George3e1a5c12014-03-29 13:43:38 +000072const mp_obj_type_t mp_type_set_it = {
Damien Georgec5966122014-02-15 16:10:44 +000073 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +000074 .name = MP_QSTR_iterator,
Paul Sokolovskyf7eaf602014-03-30 22:00:12 +030075 .getiter = mp_identity,
John R. Lenton0ce03b42014-01-12 15:17:42 +000076 .iternext = set_it_iternext,
77};
78
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020079STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
Damien George3e1a5c12014-03-29 13:43:38 +000080 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set_it));
John R. Lenton0ce03b42014-01-12 15:17:42 +000081 mp_obj_set_it_t *self = self_in;
82 machine_uint_t max = self->set->set.alloc;
Damien George8b0535e2014-04-05 21:53:54 +010083 mp_set_t *set = &self->set->set;
John R. Lenton0ce03b42014-01-12 15:17:42 +000084
85 for (machine_uint_t i = self->cur; i < max; i++) {
Damien George8b0535e2014-04-05 21:53:54 +010086 if (MP_SET_SLOT_IS_FILLED(set, i)) {
John R. Lenton0ce03b42014-01-12 15:17:42 +000087 self->cur = i + 1;
Damien George8b0535e2014-04-05 21:53:54 +010088 return set->table[i];
John R. Lenton0ce03b42014-01-12 15:17:42 +000089 }
90 }
91
Damien George66eaf842014-03-26 19:27:58 +000092 return MP_OBJ_NULL;
John R. Lenton0ce03b42014-01-12 15:17:42 +000093}
94
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020095STATIC mp_obj_t set_getiter(mp_obj_t set_in) {
John R. Lenton0ce03b42014-01-12 15:17:42 +000096 mp_obj_set_it_t *o = m_new_obj(mp_obj_set_it_t);
Damien George3e1a5c12014-03-29 13:43:38 +000097 o->base.type = &mp_type_set_it;
John R. Lenton0ce03b42014-01-12 15:17:42 +000098 o->set = (mp_obj_set_t *)set_in;
99 o->cur = 0;
100 return o;
101}
102
John R. Lenton19b14d32014-01-12 15:29:11 +0000103
104/******************************************************************************/
105/* set methods */
106
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200107STATIC mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) {
Damien George3e1a5c12014-03-29 13:43:38 +0000108 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lenton19b14d32014-01-12 15:29:11 +0000109 mp_obj_set_t *self = self_in;
John R. Lenton2a241722014-01-12 16:39:39 +0000110 mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
John R. Lenton19b14d32014-01-12 15:29:11 +0000111 return mp_const_none;
112}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200113STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add);
John R. Lenton19b14d32014-01-12 15:29:11 +0000114
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200115STATIC mp_obj_t set_clear(mp_obj_t self_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000116 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lenton1d7fb2f2014-01-12 15:44:26 +0000117 mp_obj_set_t *self = self_in;
118
119 mp_set_clear(&self->set);
120
121 return mp_const_none;
122}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200123STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear);
John R. Lenton1d7fb2f2014-01-12 15:44:26 +0000124
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200125STATIC mp_obj_t set_copy(mp_obj_t self_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000126 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lenton3b0bd872014-01-12 15:56:25 +0000127 mp_obj_set_t *self = self_in;
128
129 mp_obj_set_t *other = m_new_obj(mp_obj_set_t);
Damien George3e1a5c12014-03-29 13:43:38 +0000130 other->base.type = &mp_type_set;
John R. Lenton7244a142014-01-12 23:37:45 +0000131 mp_set_init(&other->set, self->set.alloc - 1);
John R. Lenton3b0bd872014-01-12 15:56:25 +0000132 other->set.used = self->set.used;
133 memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t));
134
135 return other;
136}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200137STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy);
John R. Lenton3b0bd872014-01-12 15:56:25 +0000138
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200139STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) {
Damien George3e1a5c12014-03-29 13:43:38 +0000140 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lenton2a241722014-01-12 16:39:39 +0000141 mp_obj_set_t *self = self_in;
142 mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
143 return mp_const_none;
144}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200145STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard);
John R. Lenton19b14d32014-01-12 15:29:11 +0000146
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200147STATIC mp_obj_t set_diff_int(int n_args, const mp_obj_t *args, bool update) {
John R. Lenton032129f2014-01-12 17:07:17 +0000148 assert(n_args > 0);
Damien George3e1a5c12014-03-29 13:43:38 +0000149 assert(MP_OBJ_IS_TYPE(args[0], &mp_type_set));
John R. Lenton032129f2014-01-12 17:07:17 +0000150 mp_obj_set_t *self;
151 if (update) {
152 self = args[0];
153 } else {
154 self = set_copy(args[0]);
155 }
156
157
158 for (int i = 1; i < n_args; i++) {
159 mp_obj_t other = args[i];
160 if (self == other) {
161 set_clear(self);
162 } else {
Damien Georged17926d2014-03-30 13:35:08 +0100163 mp_obj_t iter = mp_getiter(other);
John R. Lenton032129f2014-01-12 17:07:17 +0000164 mp_obj_t next;
Damien Georged17926d2014-03-30 13:35:08 +0100165 while ((next = mp_iternext(iter)) != MP_OBJ_NULL) {
John R. Lenton032129f2014-01-12 17:07:17 +0000166 set_discard(self, next);
167 }
168 }
169 }
170
171 return self;
172}
173
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200174STATIC mp_obj_t set_diff(uint n_args, const mp_obj_t *args) {
John R. Lenton032129f2014-01-12 17:07:17 +0000175 return set_diff_int(n_args, args, false);
176}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200177STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_obj, 1, set_diff);
John R. Lenton032129f2014-01-12 17:07:17 +0000178
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200179STATIC mp_obj_t set_diff_update(uint n_args, const mp_obj_t *args) {
John R. Lenton032129f2014-01-12 17:07:17 +0000180 set_diff_int(n_args, args, true);
181 return mp_const_none;
182}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200183STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_update_obj, 1, set_diff_update);
John R. Lenton032129f2014-01-12 17:07:17 +0000184
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200185STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) {
Damien George3e1a5c12014-03-29 13:43:38 +0000186 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lentonf1ae6b42014-01-12 17:54:03 +0000187 if (self_in == other) {
188 return update ? mp_const_none : set_copy(self_in);
189 }
190
191 mp_obj_set_t *self = self_in;
192 mp_obj_set_t *out = mp_obj_new_set(0, NULL);
193
Damien Georged17926d2014-03-30 13:35:08 +0100194 mp_obj_t iter = mp_getiter(other);
John R. Lentonf1ae6b42014-01-12 17:54:03 +0000195 mp_obj_t next;
Damien Georged17926d2014-03-30 13:35:08 +0100196 while ((next = mp_iternext(iter)) != MP_OBJ_NULL) {
John R. Lentonf1ae6b42014-01-12 17:54:03 +0000197 if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
198 set_add(out, next);
199 }
200 }
201
202 if (update) {
203 m_del(mp_obj_t, self->set.table, self->set.alloc);
204 self->set.alloc = out->set.alloc;
205 self->set.used = out->set.used;
206 self->set.table = out->set.table;
207 }
208
209 return update ? mp_const_none : out;
210}
211
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200212STATIC mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) {
John R. Lentonf1ae6b42014-01-12 17:54:03 +0000213 return set_intersect_int(self_in, other, false);
214}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200215STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_obj, set_intersect);
John R. Lentonf1ae6b42014-01-12 17:54:03 +0000216
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200217STATIC mp_obj_t set_intersect_update(mp_obj_t self_in, mp_obj_t other) {
John R. Lentonf1ae6b42014-01-12 17:54:03 +0000218 return set_intersect_int(self_in, other, true);
219}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200220STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update);
John R. Lentonf1ae6b42014-01-12 17:54:03 +0000221
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200222STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) {
Damien George3e1a5c12014-03-29 13:43:38 +0000223 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lenton4a080672014-01-12 18:03:21 +0000224 mp_obj_set_t *self = self_in;
225
Damien Georged17926d2014-03-30 13:35:08 +0100226 mp_obj_t iter = mp_getiter(other);
John R. Lenton4a080672014-01-12 18:03:21 +0000227 mp_obj_t next;
Damien Georged17926d2014-03-30 13:35:08 +0100228 while ((next = mp_iternext(iter)) != MP_OBJ_NULL) {
John R. Lenton4a080672014-01-12 18:03:21 +0000229 if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
230 return mp_const_false;
231 }
232 }
233 return mp_const_true;
234}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200235STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_isdisjoint_obj, set_isdisjoint);
John R. Lenton4a080672014-01-12 18:03:21 +0000236
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200237STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool proper) {
John R. Lentonae00d332014-01-12 18:23:36 +0000238 mp_obj_set_t *self;
239 bool cleanup_self = false;
Damien George3e1a5c12014-03-29 13:43:38 +0000240 if (MP_OBJ_IS_TYPE(self_in, &mp_type_set)) {
John R. Lentonae00d332014-01-12 18:23:36 +0000241 self = self_in;
242 } else {
Damien George3e1a5c12014-03-29 13:43:38 +0000243 self = set_make_new((mp_obj_t)&mp_type_set, 1, 0, &self_in);
John R. Lentonae00d332014-01-12 18:23:36 +0000244 cleanup_self = true;
245 }
246
247 mp_obj_set_t *other;
248 bool cleanup_other = false;
Damien George3e1a5c12014-03-29 13:43:38 +0000249 if (MP_OBJ_IS_TYPE(other_in, &mp_type_set)) {
John R. Lentonae00d332014-01-12 18:23:36 +0000250 other = other_in;
251 } else {
Damien George3e1a5c12014-03-29 13:43:38 +0000252 other = set_make_new((mp_obj_t)&mp_type_set, 1, 0, &other_in);
John R. Lentonae00d332014-01-12 18:23:36 +0000253 cleanup_other = true;
254 }
John R. Lentonbe790f92014-01-12 23:09:10 +0000255 bool out = true;
256 if (proper && self->set.used == other->set.used) {
257 out = false;
258 } else {
259 mp_obj_t iter = set_getiter(self);
260 mp_obj_t next;
Damien George66eaf842014-03-26 19:27:58 +0000261 while ((next = set_it_iternext(iter)) != MP_OBJ_NULL) {
John R. Lentonbe790f92014-01-12 23:09:10 +0000262 if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {
263 out = false;
264 break;
265 }
John R. Lentonae00d332014-01-12 18:23:36 +0000266 }
267 }
268 if (cleanup_self) {
269 set_clear(self);
270 }
271 if (cleanup_other) {
272 set_clear(other);
273 }
John R. Lentonbe790f92014-01-12 23:09:10 +0000274 return MP_BOOL(out);
275}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200276STATIC mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) {
John R. Lentonbe790f92014-01-12 23:09:10 +0000277 return set_issubset_internal(self_in, other_in, false);
John R. Lentonae00d332014-01-12 18:23:36 +0000278}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200279STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issubset_obj, set_issubset);
John R. Lentonae00d332014-01-12 18:23:36 +0000280
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200281STATIC mp_obj_t set_issubset_proper(mp_obj_t self_in, mp_obj_t other_in) {
John R. Lentonbe790f92014-01-12 23:09:10 +0000282 return set_issubset_internal(self_in, other_in, true);
283}
284
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200285STATIC mp_obj_t set_issuperset(mp_obj_t self_in, mp_obj_t other_in) {
John R. Lentonbe790f92014-01-12 23:09:10 +0000286 return set_issubset_internal(other_in, self_in, false);
John R. Lentonae00d332014-01-12 18:23:36 +0000287}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200288STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issuperset_obj, set_issuperset);
John R. Lentonae00d332014-01-12 18:23:36 +0000289
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200290STATIC mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) {
John R. Lentonbe790f92014-01-12 23:09:10 +0000291 return set_issubset_internal(other_in, self_in, true);
292}
293
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200294STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000295 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lentonbe790f92014-01-12 23:09:10 +0000296 mp_obj_set_t *self = self_in;
Damien George3e1a5c12014-03-29 13:43:38 +0000297 if (!MP_OBJ_IS_TYPE(other_in, &mp_type_set)) {
John R. Lentonbe790f92014-01-12 23:09:10 +0000298 return mp_const_false;
299 }
300 mp_obj_set_t *other = other_in;
301 if (self->set.used != other->set.used) {
302 return mp_const_false;
303 }
304 return set_issubset(self_in, other_in);
305}
306
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200307STATIC mp_obj_t set_pop(mp_obj_t self_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000308 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lentonae00d332014-01-12 18:23:36 +0000309 mp_obj_set_t *self = self_in;
Damien George95004e52014-04-05 17:17:19 +0100310 mp_obj_t obj = mp_set_remove_first(&self->set);
311 if (obj == MP_OBJ_NULL) {
Damien Georgeea13f402014-04-05 18:32:08 +0100312 nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "pop from an empty set"));
John R. Lentonae00d332014-01-12 18:23:36 +0000313 }
John R. Lentonae00d332014-01-12 18:23:36 +0000314 return obj;
315}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200316STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop);
John R. Lentonae00d332014-01-12 18:23:36 +0000317
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200318STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) {
Damien George3e1a5c12014-03-29 13:43:38 +0000319 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lentonae00d332014-01-12 18:23:36 +0000320 mp_obj_set_t *self = self_in;
321 if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) {
Damien Georgeea13f402014-04-05 18:32:08 +0100322 nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
John R. Lentonae00d332014-01-12 18:23:36 +0000323 }
324 return mp_const_none;
325}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200326STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove);
John R. Lenton032129f2014-01-12 17:07:17 +0000327
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200328STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000329 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lenton0de386b2014-01-12 19:39:48 +0000330 mp_obj_set_t *self = self_in;
Damien Georged17926d2014-03-30 13:35:08 +0100331 mp_obj_t iter = mp_getiter(other_in);
John R. Lenton0de386b2014-01-12 19:39:48 +0000332 mp_obj_t next;
Damien Georged17926d2014-03-30 13:35:08 +0100333 while ((next = mp_iternext(iter)) != MP_OBJ_NULL) {
John R. Lenton0de386b2014-01-12 19:39:48 +0000334 mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
335 }
336 return mp_const_none;
337}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200338STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update);
John R. Lenton0de386b2014-01-12 19:39:48 +0000339
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200340STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000341 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lenton0de386b2014-01-12 19:39:48 +0000342 self_in = set_copy(self_in);
343 set_symmetric_difference_update(self_in, other_in);
344 return self_in;
345}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200346STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference);
John R. Lenton0de386b2014-01-12 19:39:48 +0000347
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200348STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {
Damien Georged17926d2014-03-30 13:35:08 +0100349 mp_obj_t iter = mp_getiter(other_in);
John R. Lenton0de386b2014-01-12 19:39:48 +0000350 mp_obj_t next;
Damien Georged17926d2014-03-30 13:35:08 +0100351 while ((next = mp_iternext(iter)) != MP_OBJ_NULL) {
John R. Lenton0de386b2014-01-12 19:39:48 +0000352 mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
353 }
354}
355
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200356STATIC mp_obj_t set_update(uint n_args, const mp_obj_t *args) {
John R. Lenton0de386b2014-01-12 19:39:48 +0000357 assert(n_args > 0);
Damien George3e1a5c12014-03-29 13:43:38 +0000358 assert(MP_OBJ_IS_TYPE(args[0], &mp_type_set));
John R. Lenton0de386b2014-01-12 19:39:48 +0000359
360 for (int i = 1; i < n_args; i++) {
361 set_update_int(args[0], args[i]);
362 }
363
364 return mp_const_none;
365}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200366STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update);
John R. Lenton0de386b2014-01-12 19:39:48 +0000367
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200368STATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000369 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
John R. Lenton0de386b2014-01-12 19:39:48 +0000370 mp_obj_set_t *self = set_copy(self_in);
371 set_update_int(self, other_in);
372 return self;
373}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200374STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union);
John R. Lenton0de386b2014-01-12 19:39:48 +0000375
Damien George95004e52014-04-05 17:17:19 +0100376STATIC mp_obj_t set_unary_op(int op, mp_obj_t self_in) {
377 mp_obj_set_t *self = self_in;
378 switch (op) {
379 case MP_UNARY_OP_BOOL: return MP_BOOL(self->set.used != 0);
380 case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->set.used);
381 default: return MP_OBJ_NULL; // op not supported for None
382 }
383}
John R. Lenton0de386b2014-01-12 19:39:48 +0000384
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200385STATIC mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
John R. Lentonbe790f92014-01-12 23:09:10 +0000386 mp_obj_t args[] = {lhs, rhs};
387 switch (op) {
Damien Georged17926d2014-03-30 13:35:08 +0100388 case MP_BINARY_OP_OR:
John R. Lentonbe790f92014-01-12 23:09:10 +0000389 return set_union(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100390 case MP_BINARY_OP_XOR:
John R. Lentonbe790f92014-01-12 23:09:10 +0000391 return set_symmetric_difference(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100392 case MP_BINARY_OP_AND:
John R. Lentonbe790f92014-01-12 23:09:10 +0000393 return set_intersect(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100394 case MP_BINARY_OP_SUBTRACT:
John R. Lentonbe790f92014-01-12 23:09:10 +0000395 return set_diff(2, args);
Damien Georged17926d2014-03-30 13:35:08 +0100396 case MP_BINARY_OP_INPLACE_OR:
John R. Lentonbe790f92014-01-12 23:09:10 +0000397 return set_union(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100398 case MP_BINARY_OP_INPLACE_XOR:
John R. Lentonbe790f92014-01-12 23:09:10 +0000399 return set_symmetric_difference(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100400 case MP_BINARY_OP_INPLACE_AND:
John R. Lentonbe790f92014-01-12 23:09:10 +0000401 return set_intersect(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100402 case MP_BINARY_OP_INPLACE_SUBTRACT:
John R. Lentonbe790f92014-01-12 23:09:10 +0000403 return set_diff(2, args);
Damien Georged17926d2014-03-30 13:35:08 +0100404 case MP_BINARY_OP_LESS:
John R. Lentonbe790f92014-01-12 23:09:10 +0000405 return set_issubset_proper(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100406 case MP_BINARY_OP_MORE:
John R. Lentonbe790f92014-01-12 23:09:10 +0000407 return set_issuperset_proper(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100408 case MP_BINARY_OP_EQUAL:
John R. Lentonbe790f92014-01-12 23:09:10 +0000409 return set_equal(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100410 case MP_BINARY_OP_LESS_EQUAL:
John R. Lentonbe790f92014-01-12 23:09:10 +0000411 return set_issubset(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100412 case MP_BINARY_OP_MORE_EQUAL:
John R. Lentonbe790f92014-01-12 23:09:10 +0000413 return set_issuperset(lhs, rhs);
Damien Georged17926d2014-03-30 13:35:08 +0100414 case MP_BINARY_OP_NOT_EQUAL:
John R. Lentonbe790f92014-01-12 23:09:10 +0000415 return MP_BOOL(set_equal(lhs, rhs) == mp_const_false);
Damien Georged17926d2014-03-30 13:35:08 +0100416 case MP_BINARY_OP_IN:
John R. Lenton189c8e12014-01-13 00:52:06 +0000417 {
418 mp_obj_set_t *o = lhs;
419 mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP);
Damien George9aa2a522014-02-01 23:04:09 +0000420 return MP_BOOL(elem != NULL);
John R. Lenton189c8e12014-01-13 00:52:06 +0000421 }
John R. Lentonbe790f92014-01-12 23:09:10 +0000422 default:
423 // op not supported
424 return NULL;
425 }
426}
John R. Lenton0de386b2014-01-12 19:39:48 +0000427
John R. Lenton19b14d32014-01-12 15:29:11 +0000428/******************************************************************************/
429/* set constructors & public C API */
430
431
Damien George9b196cd2014-03-26 21:47:19 +0000432STATIC const mp_map_elem_t set_locals_dict_table[] = {
433 { MP_OBJ_NEW_QSTR(MP_QSTR_add), (mp_obj_t)&set_add_obj },
434 { MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&set_clear_obj },
435 { MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&set_copy_obj },
436 { MP_OBJ_NEW_QSTR(MP_QSTR_discard), (mp_obj_t)&set_discard_obj },
437 { MP_OBJ_NEW_QSTR(MP_QSTR_difference), (mp_obj_t)&set_diff_obj },
438 { MP_OBJ_NEW_QSTR(MP_QSTR_difference_update), (mp_obj_t)&set_diff_update_obj },
439 { MP_OBJ_NEW_QSTR(MP_QSTR_intersection), (mp_obj_t)&set_intersect_obj },
440 { MP_OBJ_NEW_QSTR(MP_QSTR_intersection_update), (mp_obj_t)&set_intersect_update_obj },
441 { MP_OBJ_NEW_QSTR(MP_QSTR_isdisjoint), (mp_obj_t)&set_isdisjoint_obj },
442 { MP_OBJ_NEW_QSTR(MP_QSTR_issubset), (mp_obj_t)&set_issubset_obj },
443 { MP_OBJ_NEW_QSTR(MP_QSTR_issuperset), (mp_obj_t)&set_issuperset_obj },
444 { MP_OBJ_NEW_QSTR(MP_QSTR_pop), (mp_obj_t)&set_pop_obj },
445 { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&set_remove_obj },
446 { MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference), (mp_obj_t)&set_symmetric_difference_obj },
447 { MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference_update), (mp_obj_t)&set_symmetric_difference_update_obj },
448 { MP_OBJ_NEW_QSTR(MP_QSTR_union), (mp_obj_t)&set_union_obj },
449 { MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&set_update_obj },
John R. Lenton19b14d32014-01-12 15:29:11 +0000450};
451
Damien George9b196cd2014-03-26 21:47:19 +0000452STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table);
453
Damien George3e1a5c12014-03-29 13:43:38 +0000454const mp_obj_type_t mp_type_set = {
Damien Georgec5966122014-02-15 16:10:44 +0000455 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +0000456 .name = MP_QSTR_set,
Damien George97209d32014-01-07 15:58:30 +0000457 .print = set_print,
458 .make_new = set_make_new,
Damien George95004e52014-04-05 17:17:19 +0100459 .unary_op = set_unary_op,
John R. Lentonbe790f92014-01-12 23:09:10 +0000460 .binary_op = set_binary_op,
John R. Lenton0ce03b42014-01-12 15:17:42 +0000461 .getiter = set_getiter,
Damien George9b196cd2014-03-26 21:47:19 +0000462 .locals_dict = (mp_obj_t)&set_locals_dict,
Damiend99b0522013-12-21 18:17:45 +0000463};
464
465mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) {
466 mp_obj_set_t *o = m_new_obj(mp_obj_set_t);
Damien George3e1a5c12014-03-29 13:43:38 +0000467 o->base.type = &mp_type_set;
Damiend99b0522013-12-21 18:17:45 +0000468 mp_set_init(&o->set, n_args);
469 for (int i = 0; i < n_args; i++) {
John R. Lenton2a241722014-01-12 16:39:39 +0000470 mp_set_lookup(&o->set, items[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
Damiend99b0522013-12-21 18:17:45 +0000471 }
472 return o;
473}
474
475void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
Damien George3e1a5c12014-03-29 13:43:38 +0000476 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
Damiend99b0522013-12-21 18:17:45 +0000477 mp_obj_set_t *self = self_in;
John R. Lenton2a241722014-01-12 16:39:39 +0000478 mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
Damiend99b0522013-12-21 18:17:45 +0000479}