objset.c 18.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * This file is part of the Micro Python project, http://micropython.org/
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013, 2014 Damien P. George
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

xbe's avatar
xbe committed
27
#include <stdbool.h>
John R. Lenton's avatar
John R. Lenton committed
28
#include <string.h>
29
30
#include <assert.h>

31
#include "mpconfig.h"
32
33
#include "nlr.h"
#include "misc.h"
34
#include "qstr.h"
35
#include "obj.h"
36
#include "runtime.h"
37
#include "runtime0.h"
38
#include "builtin.h"
39

40
41
#if MICROPY_PY_BUILTINS_SET

42
43
44
45
46
typedef struct _mp_obj_set_t {
    mp_obj_base_t base;
    mp_set_t set;
} mp_obj_set_t;

John R. Lenton's avatar
John R. Lenton committed
47
48
49
typedef struct _mp_obj_set_it_t {
    mp_obj_base_t base;
    mp_obj_set_t *set;
50
    mp_uint_t cur;
John R. Lenton's avatar
John R. Lenton committed
51
52
} mp_obj_set_it_t;

53
STATIC mp_obj_t set_it_iternext(mp_obj_t self_in);
John R. Lenton's avatar
John R. Lenton committed
54

55
STATIC bool is_set_or_frozenset(mp_obj_t o) {
56
    return MP_OBJ_IS_TYPE(o, &mp_type_set)
57
#if MICROPY_PY_BUILTINS_FROZENSET
58
59
60
        || MP_OBJ_IS_TYPE(o, &mp_type_frozenset)
#endif
    ;
61
62
}

63
#if MICROPY_PY_BUILTINS_FROZENSET
64
65
66
67
68
STATIC void check_set_or_frozenset(mp_obj_t o) {
    if (!is_set_or_frozenset(o)) {
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'set' object required"));
    }
}
69
70
71
#else
#define check_set_or_frozenset(o) check_set(o)
#endif
72
73
74
75
76

STATIC void check_set(mp_obj_t o) {
    if (!MP_OBJ_IS_TYPE(o, &mp_type_set)) {
        // Emulate CPython behavior
        // AttributeError: 'frozenset' object has no attribute 'add'
77
        #if MICROPY_PY_BUILTINS_FROZENSET
78
79
80
        if (MP_OBJ_IS_TYPE(o, &mp_type_frozenset)) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "'frozenset' has no such attribute"));
        }
81
        #endif
82
83
84
85
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'set' object required"));
    }
}

86
STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
87
    mp_obj_set_t *self = self_in;
88
    #if MICROPY_PY_BUILTINS_FROZENSET
89
    bool is_frozen = MP_OBJ_IS_TYPE(self_in, &mp_type_frozenset);
90
    #endif
91
    if (self->set.used == 0) {
92
        #if MICROPY_PY_BUILTINS_FROZENSET
93
94
95
        if (is_frozen) {
            print(env, "frozen");
        }
96
        #endif
97
98
99
        print(env, "set()");
        return;
    }
100
    bool first = true;
101
    #if MICROPY_PY_BUILTINS_FROZENSET
102
103
104
    if (is_frozen) {
        print(env, "frozenset(");
    }
105
    #endif
106
107
    print(env, "{");
    for (int i = 0; i < self->set.alloc; i++) {
108
        if (MP_SET_SLOT_IS_FILLED(&self->set, i)) {
109
110
111
112
            if (!first) {
                print(env, ", ");
            }
            first = false;
113
            mp_obj_print_helper(print, env, self->set.table[i], PRINT_REPR);
114
115
116
        }
    }
    print(env, "}");
117
    #if MICROPY_PY_BUILTINS_FROZENSET
118
119
120
    if (is_frozen) {
        print(env, ")");
    }
121
    #endif
122
123
}

124

125
STATIC mp_obj_t set_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
126
    mp_arg_check_num(n_args, n_kw, 0, 1, false);
127

128
    switch (n_args) {
129
130
131
132
133
134
135
        case 0: {
            // create a new, empty set
            mp_obj_set_t *set = mp_obj_new_set(0, NULL);
            // set actual set/frozenset type
            set->base.type = type_in;
            return set;
        }
136
137

        case 1:
138
        default: { // can only be 0 or 1 arg
139
            // 1 argument, an iterable from which we make a new set
140
            mp_obj_set_t *set = mp_obj_new_set(0, NULL);
Damien George's avatar
Damien George committed
141
            mp_obj_t iterable = mp_getiter(args[0]);
142
            mp_obj_t item;
143
            while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
144
145
                mp_obj_set_store(set, item);
            }
146
147
            // Set actual set/frozenset type
            set->base.type = type_in;
148
149
150
151
152
            return set;
        }
    }
}

153
const mp_obj_type_t mp_type_set_it = {
154
    { &mp_type_type },
155
    .name = MP_QSTR_iterator,
156
    .getiter = mp_identity,
John R. Lenton's avatar
John R. Lenton committed
157
158
159
    .iternext = set_it_iternext,
};

160
STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
161
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set_it));
John R. Lenton's avatar
John R. Lenton committed
162
    mp_obj_set_it_t *self = self_in;
163
    mp_uint_t max = self->set->set.alloc;
164
    mp_set_t *set = &self->set->set;
John R. Lenton's avatar
John R. Lenton committed
165

166
    for (mp_uint_t i = self->cur; i < max; i++) {
167
        if (MP_SET_SLOT_IS_FILLED(set, i)) {
John R. Lenton's avatar
John R. Lenton committed
168
            self->cur = i + 1;
169
            return set->table[i];
John R. Lenton's avatar
John R. Lenton committed
170
171
172
        }
    }

173
    return MP_OBJ_STOP_ITERATION;
John R. Lenton's avatar
John R. Lenton committed
174
175
}

176
STATIC mp_obj_t set_getiter(mp_obj_t set_in) {
John R. Lenton's avatar
John R. Lenton committed
177
    mp_obj_set_it_t *o = m_new_obj(mp_obj_set_it_t);
178
    o->base.type = &mp_type_set_it;
John R. Lenton's avatar
John R. Lenton committed
179
180
181
182
183
    o->set = (mp_obj_set_t *)set_in;
    o->cur = 0;
    return o;
}

John R. Lenton's avatar
John R. Lenton committed
184
185
186
187

/******************************************************************************/
/* set methods                                                                */

188
STATIC mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) {
189
    check_set(self_in);
John R. Lenton's avatar
John R. Lenton committed
190
    mp_obj_set_t *self = self_in;
John R. Lenton's avatar
John R. Lenton committed
191
    mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
John R. Lenton's avatar
John R. Lenton committed
192
193
    return mp_const_none;
}
194
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add);
John R. Lenton's avatar
John R. Lenton committed
195

196
STATIC mp_obj_t set_clear(mp_obj_t self_in) {
197
    check_set(self_in);
John R. Lenton's avatar
John R. Lenton committed
198
199
200
201
202
203
    mp_obj_set_t *self = self_in;

    mp_set_clear(&self->set);

    return mp_const_none;
}
204
STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear);
John R. Lenton's avatar
John R. Lenton committed
205

206
STATIC mp_obj_t set_copy_as_mutable(mp_obj_t self_in) {
John R. Lenton's avatar
John R. Lenton committed
207
208
209
    mp_obj_set_t *self = self_in;

    mp_obj_set_t *other = m_new_obj(mp_obj_set_t);
210
    other->base.type = &mp_type_set;
211
    mp_set_init(&other->set, self->set.alloc);
John R. Lenton's avatar
John R. Lenton committed
212
213
214
215
216
    other->set.used = self->set.used;
    memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t));

    return other;
}
217
218
219
220
221
222
223
224
225
226

STATIC mp_obj_t set_copy(mp_obj_t self_in) {
    check_set_or_frozenset(self_in);
    mp_obj_set_t *self = self_in;

    mp_obj_set_t *other = set_copy_as_mutable(self);
    other->base.type = self->base.type;

    return other;
}
227
STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy);
John R. Lenton's avatar
John R. Lenton committed
228

229
STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) {
230
    check_set(self_in);
John R. Lenton's avatar
John R. Lenton committed
231
232
233
234
    mp_obj_set_t *self = self_in;
    mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
    return mp_const_none;
}
235
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard);
John R. Lenton's avatar
John R. Lenton committed
236

237
STATIC mp_obj_t set_diff_int(int n_args, const mp_obj_t *args, bool update) {
238
    assert(n_args > 0);
239

240
241
    mp_obj_set_t *self;
    if (update) {
242
        check_set(args[0]);
243
244
        self = args[0];
    } else {
245
246
        check_set_or_frozenset(args[0]);
        self = set_copy_as_mutable(args[0]);
247
248
249
250
251
252
253
254
    }


    for (int i = 1; i < n_args; i++) {
        mp_obj_t other = args[i];
        if (self == other) {
            set_clear(self);
        } else {
Damien George's avatar
Damien George committed
255
            mp_obj_t iter = mp_getiter(other);
256
            mp_obj_t next;
257
            while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
258
259
260
261
262
                set_discard(self, next);
            }
        }
    }

263
    self->base.type = ((mp_obj_set_t*)args[0])->base.type;
264
265
266
    return self;
}

267
STATIC mp_obj_t set_diff(uint n_args, const mp_obj_t *args) {
268
269
    return set_diff_int(n_args, args, false);
}
270
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_obj, 1, set_diff);
271

272
STATIC mp_obj_t set_diff_update(uint n_args, const mp_obj_t *args) {
273
274
275
    set_diff_int(n_args, args, true);
    return mp_const_none;
}
276
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_update_obj, 1, set_diff_update);
277

278
STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) {
279
280
281
282
283
284
    if (update) {
        check_set(self_in);
    } else {
        check_set_or_frozenset(self_in);
    }

285
286
287
288
289
290
291
    if (self_in == other) {
        return update ? mp_const_none : set_copy(self_in);
    }

    mp_obj_set_t *self = self_in;
    mp_obj_set_t *out = mp_obj_new_set(0, NULL);

Damien George's avatar
Damien George committed
292
    mp_obj_t iter = mp_getiter(other);
293
    mp_obj_t next;
294
    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
        if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
            set_add(out, next);
        }
    }

    if (update) {
        m_del(mp_obj_t, self->set.table, self->set.alloc);
        self->set.alloc = out->set.alloc;
        self->set.used = out->set.used;
        self->set.table = out->set.table;
    }

    return update ? mp_const_none : out;
}

310
STATIC mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) {
311
312
    return set_intersect_int(self_in, other, false);
}
313
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_obj, set_intersect);
314

315
STATIC mp_obj_t set_intersect_update(mp_obj_t self_in, mp_obj_t other) {
316
317
    return set_intersect_int(self_in, other, true);
}
318
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update);
319

320
STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) {
321
    check_set_or_frozenset(self_in);
John R. Lenton's avatar
John R. Lenton committed
322
323
    mp_obj_set_t *self = self_in;

Damien George's avatar
Damien George committed
324
    mp_obj_t iter = mp_getiter(other);
John R. Lenton's avatar
John R. Lenton committed
325
    mp_obj_t next;
326
    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
John R. Lenton's avatar
John R. Lenton committed
327
328
329
330
331
332
        if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
            return mp_const_false;
        }
    }
    return mp_const_true;
}
333
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_isdisjoint_obj, set_isdisjoint);
John R. Lenton's avatar
John R. Lenton committed
334

335
STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool proper) {
John R. Lenton's avatar
John R. Lenton committed
336
337
    mp_obj_set_t *self;
    bool cleanup_self = false;
338
    if (is_set_or_frozenset(self_in)) {
John R. Lenton's avatar
John R. Lenton committed
339
340
        self = self_in;
    } else {
341
        self = set_make_new((mp_obj_t)&mp_type_set, 1, 0, &self_in);
John R. Lenton's avatar
John R. Lenton committed
342
343
344
345
346
        cleanup_self = true;
    }

    mp_obj_set_t *other;
    bool cleanup_other = false;
347
    if (is_set_or_frozenset(other_in)) {
John R. Lenton's avatar
John R. Lenton committed
348
349
        other = other_in;
    } else {
350
        other = set_make_new((mp_obj_t)&mp_type_set, 1, 0, &other_in);
John R. Lenton's avatar
John R. Lenton committed
351
352
        cleanup_other = true;
    }
John R. Lenton's avatar
John R. Lenton committed
353
354
355
356
357
358
    bool out = true;
    if (proper && self->set.used == other->set.used) {
        out = false;
    } else {
        mp_obj_t iter = set_getiter(self);
        mp_obj_t next;
359
        while ((next = set_it_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
John R. Lenton's avatar
John R. Lenton committed
360
361
362
363
            if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {
                out = false;
                break;
            }
John R. Lenton's avatar
John R. Lenton committed
364
365
        }
    }
366
    // TODO: Should free objects altogether
John R. Lenton's avatar
John R. Lenton committed
367
368
369
370
371
372
    if (cleanup_self) {
        set_clear(self);
    }
    if (cleanup_other) {
        set_clear(other);
    }
John R. Lenton's avatar
John R. Lenton committed
373
374
    return MP_BOOL(out);
}
375
STATIC mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) {
John R. Lenton's avatar
John R. Lenton committed
376
    return set_issubset_internal(self_in, other_in, false);
John R. Lenton's avatar
John R. Lenton committed
377
}
378
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issubset_obj, set_issubset);
John R. Lenton's avatar
John R. Lenton committed
379

380
STATIC mp_obj_t set_issubset_proper(mp_obj_t self_in, mp_obj_t other_in) {
John R. Lenton's avatar
John R. Lenton committed
381
382
383
    return set_issubset_internal(self_in, other_in, true);
}

384
STATIC mp_obj_t set_issuperset(mp_obj_t self_in, mp_obj_t other_in) {
John R. Lenton's avatar
John R. Lenton committed
385
    return set_issubset_internal(other_in, self_in, false);
John R. Lenton's avatar
John R. Lenton committed
386
}
387
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issuperset_obj, set_issuperset);
John R. Lenton's avatar
John R. Lenton committed
388

389
STATIC mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) {
John R. Lenton's avatar
John R. Lenton committed
390
391
392
    return set_issubset_internal(other_in, self_in, true);
}

393
STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) {
394
    check_set_or_frozenset(self_in);
John R. Lenton's avatar
John R. Lenton committed
395
    mp_obj_set_t *self = self_in;
396
    if (!is_set_or_frozenset(other_in)) {
John R. Lenton's avatar
John R. Lenton committed
397
398
399
400
401
402
403
404
405
        return mp_const_false;
    }
    mp_obj_set_t *other = other_in;
    if (self->set.used != other->set.used) {
        return mp_const_false;
    }
    return set_issubset(self_in, other_in);
}

406
STATIC mp_obj_t set_pop(mp_obj_t self_in) {
407
    check_set(self_in);
John R. Lenton's avatar
John R. Lenton committed
408
    mp_obj_set_t *self = self_in;
409
410
    mp_obj_t obj = mp_set_remove_first(&self->set);
    if (obj == MP_OBJ_NULL) {
411
        nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "pop from an empty set"));
John R. Lenton's avatar
John R. Lenton committed
412
413
414
    }
    return obj;
}
415
STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop);
John R. Lenton's avatar
John R. Lenton committed
416

417
STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) {
418
    check_set(self_in);
John R. Lenton's avatar
John R. Lenton committed
419
420
    mp_obj_set_t *self = self_in;
    if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) {
421
        nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
John R. Lenton's avatar
John R. Lenton committed
422
423
424
    }
    return mp_const_none;
}
425
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove);
426

427
STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) {
428
    check_set(self_in);
John R. Lenton's avatar
John R. Lenton committed
429
    mp_obj_set_t *self = self_in;
Damien George's avatar
Damien George committed
430
    mp_obj_t iter = mp_getiter(other_in);
John R. Lenton's avatar
John R. Lenton committed
431
    mp_obj_t next;
432
    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
John R. Lenton's avatar
John R. Lenton committed
433
434
435
436
        mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
    }
    return mp_const_none;
}
437
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update);
John R. Lenton's avatar
John R. Lenton committed
438

439
STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) {
440
441
442
443
444
    check_set_or_frozenset(self_in);
    mp_obj_set_t *self_out = set_copy_as_mutable(self_in);
    set_symmetric_difference_update(self_out, other_in);
    self_out->base.type = ((mp_obj_set_t*)self_in)->base.type;
    return self_out;
John R. Lenton's avatar
John R. Lenton committed
445
}
446
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference);
John R. Lenton's avatar
John R. Lenton committed
447

448
STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {
Damien George's avatar
Damien George committed
449
    mp_obj_t iter = mp_getiter(other_in);
John R. Lenton's avatar
John R. Lenton committed
450
    mp_obj_t next;
451
    while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
John R. Lenton's avatar
John R. Lenton committed
452
453
454
455
        mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
    }
}

456
STATIC mp_obj_t set_update(uint n_args, const mp_obj_t *args) {
John R. Lenton's avatar
John R. Lenton committed
457
458
459
460
461
462
463
464
    assert(n_args > 0);

    for (int i = 1; i < n_args; i++) {
        set_update_int(args[0], args[i]);
    }

    return mp_const_none;
}
465
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update);
John R. Lenton's avatar
John R. Lenton committed
466

467
STATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) {
468
    check_set_or_frozenset(self_in);
John R. Lenton's avatar
John R. Lenton committed
469
470
471
472
    mp_obj_set_t *self = set_copy(self_in);
    set_update_int(self, other_in);
    return self;
}
473
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union);
John R. Lenton's avatar
John R. Lenton committed
474

475
476
477
478
STATIC mp_obj_t set_unary_op(int op, mp_obj_t self_in) {
    mp_obj_set_t *self = self_in;
    switch (op) {
        case MP_UNARY_OP_BOOL: return MP_BOOL(self->set.used != 0);
479
        case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->set.used);
480
        default: return MP_OBJ_NULL; // op not supported
481
482
    }
}
John R. Lenton's avatar
John R. Lenton committed
483

484
STATIC mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
John R. Lenton's avatar
John R. Lenton committed
485
486
    mp_obj_t args[] = {lhs, rhs};
    switch (op) {
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
        case MP_BINARY_OP_OR:
            return set_union(lhs, rhs);
        case MP_BINARY_OP_XOR:
            return set_symmetric_difference(lhs, rhs);
        case MP_BINARY_OP_AND:
            return set_intersect(lhs, rhs);
        case MP_BINARY_OP_SUBTRACT:
            return set_diff(2, args);
        case MP_BINARY_OP_INPLACE_OR:
            return set_union(lhs, rhs);
        case MP_BINARY_OP_INPLACE_XOR:
            return set_symmetric_difference(lhs, rhs);
        case MP_BINARY_OP_INPLACE_AND:
            return set_intersect(lhs, rhs);
        case MP_BINARY_OP_INPLACE_SUBTRACT:
            return set_diff(2, args);
        case MP_BINARY_OP_LESS:
            return set_issubset_proper(lhs, rhs);
        case MP_BINARY_OP_MORE:
            return set_issuperset_proper(lhs, rhs);
        case MP_BINARY_OP_EQUAL:
            return set_equal(lhs, rhs);
        case MP_BINARY_OP_LESS_EQUAL:
            return set_issubset(lhs, rhs);
        case MP_BINARY_OP_MORE_EQUAL:
            return set_issuperset(lhs, rhs);
        case MP_BINARY_OP_IN: {
            mp_obj_set_t *o = lhs;
            mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP);
            return MP_BOOL(elem != NULL);
        }
        default:
519
            return MP_OBJ_NULL; // op not supported
John R. Lenton's avatar
John R. Lenton committed
520
521
    }
}
John R. Lenton's avatar
John R. Lenton committed
522

John R. Lenton's avatar
John R. Lenton committed
523
524
525
526
/******************************************************************************/
/* set constructors & public C API                                            */


527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
STATIC const mp_map_elem_t set_locals_dict_table[] = {
    { MP_OBJ_NEW_QSTR(MP_QSTR_add), (mp_obj_t)&set_add_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&set_clear_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&set_copy_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_discard), (mp_obj_t)&set_discard_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_difference), (mp_obj_t)&set_diff_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_difference_update), (mp_obj_t)&set_diff_update_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_intersection), (mp_obj_t)&set_intersect_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_intersection_update), (mp_obj_t)&set_intersect_update_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_isdisjoint), (mp_obj_t)&set_isdisjoint_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_issubset), (mp_obj_t)&set_issubset_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_issuperset), (mp_obj_t)&set_issuperset_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_pop), (mp_obj_t)&set_pop_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&set_remove_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference), (mp_obj_t)&set_symmetric_difference_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference_update), (mp_obj_t)&set_symmetric_difference_update_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_union), (mp_obj_t)&set_union_obj },
    { MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&set_update_obj },
545
    { MP_OBJ_NEW_QSTR(MP_QSTR___contains__), (mp_obj_t)&mp_op_contains_obj },
John R. Lenton's avatar
John R. Lenton committed
546
547
};

548
549
STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table);

550
const mp_obj_type_t mp_type_set = {
551
    { &mp_type_type },
552
    .name = MP_QSTR_set,
553
554
    .print = set_print,
    .make_new = set_make_new,
555
    .unary_op = set_unary_op,
John R. Lenton's avatar
John R. Lenton committed
556
    .binary_op = set_binary_op,
John R. Lenton's avatar
John R. Lenton committed
557
    .getiter = set_getiter,
558
    .locals_dict = (mp_obj_t)&set_locals_dict,
559
560
};

561
#if MICROPY_PY_BUILTINS_FROZENSET
562
563
564
565
566
567
568
569
570
571
572
573
const mp_obj_type_t mp_type_frozenset = {
    { &mp_type_type },
    .name = MP_QSTR_frozenset,
    .print = set_print,
    .make_new = set_make_new,
    .unary_op = set_unary_op,
    .binary_op = set_binary_op,
    .getiter = set_getiter,
    .locals_dict = (mp_obj_t)&set_locals_dict,
};
#endif

574
575
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) {
    mp_obj_set_t *o = m_new_obj(mp_obj_set_t);
576
    o->base.type = &mp_type_set;
577
578
    mp_set_init(&o->set, n_args);
    for (int i = 0; i < n_args; i++) {
John R. Lenton's avatar
John R. Lenton committed
579
        mp_set_lookup(&o->set, items[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
580
581
582
583
584
    }
    return o;
}

void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
585
    assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
586
    mp_obj_set_t *self = self_in;
John R. Lenton's avatar
John R. Lenton committed
587
    mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
588
}
589
590

#endif // MICROPY_PY_BUILTINS_SET