blob: a9dbb76c449d59147cdd50f97e0448a227ac11da [file] [log] [blame]
xbeefe34222014-03-16 00:14:26 -07001#include <stdbool.h>
Damiend99b0522013-12-21 18:17:45 +00002#include <string.h>
3#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"
10#include "runtime0.h"
11#include "runtime.h"
Damiend99b0522013-12-21 18:17:45 +000012
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020013STATIC mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur);
14STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in);
John R. Lentona41fe312014-01-06 17:17:02 +000015
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020016STATIC void dict_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 +000017 mp_obj_dict_t *self = self_in;
18 bool first = true;
19 print(env, "{");
John R. Lentona41fe312014-01-06 17:17:02 +000020 mp_obj_t *dict_iter = mp_obj_new_dict_iterator(self, 0);
21 mp_map_elem_t *next = NULL;
22 while ((next = dict_it_iternext_elem(dict_iter)) != NULL) {
23 if (!first) {
24 print(env, ", ");
Damiend99b0522013-12-21 18:17:45 +000025 }
John R. Lentona41fe312014-01-06 17:17:02 +000026 first = false;
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020027 mp_obj_print_helper(print, env, next->key, PRINT_REPR);
John R. Lentona41fe312014-01-06 17:17:02 +000028 print(env, ": ");
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020029 mp_obj_print_helper(print, env, next->value, PRINT_REPR);
Damiend99b0522013-12-21 18:17:45 +000030 }
31 print(env, "}");
32}
33
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020034STATIC mp_obj_t dict_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
Damien George71c51812014-01-04 20:21:15 +000035 // TODO create from an iterable!
Damien Georged17926d2014-03-30 13:35:08 +010036 return mp_build_map(0);
Damien George71c51812014-01-04 20:21:15 +000037}
38
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020039STATIC mp_obj_t dict_unary_op(int op, mp_obj_t self_in) {
Damien George4e8dc8c2014-01-27 23:15:32 +000040 mp_obj_dict_t *self = self_in;
41 switch (op) {
Damien Georged17926d2014-03-30 13:35:08 +010042 case MP_UNARY_OP_BOOL: return MP_BOOL(self->map.used != 0);
43 case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->map.used);
Damien George4e8dc8c2014-01-27 23:15:32 +000044 default: return MP_OBJ_NULL; // op not supported for None
45 }
46}
47
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020048STATIC mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
Damiend99b0522013-12-21 18:17:45 +000049 mp_obj_dict_t *o = lhs_in;
50 switch (op) {
Damien Georged17926d2014-03-30 13:35:08 +010051 case MP_BINARY_OP_SUBSCR:
Damiend99b0522013-12-21 18:17:45 +000052 {
53 // dict load
Damien George38a2da62014-01-08 17:33:12 +000054 mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
Damiend99b0522013-12-21 18:17:45 +000055 if (elem == NULL) {
Damien Georgec5966122014-02-15 16:10:44 +000056 nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>"));
Damiend99b0522013-12-21 18:17:45 +000057 } else {
58 return elem->value;
59 }
60 }
Damien Georged17926d2014-03-30 13:35:08 +010061 case MP_BINARY_OP_IN:
John R. Lentonc1bef212014-01-11 12:39:33 +000062 {
63 mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
Damien George9aa2a522014-02-01 23:04:09 +000064 return MP_BOOL(elem != NULL);
John R. Lentonc1bef212014-01-11 12:39:33 +000065 }
Damiend99b0522013-12-21 18:17:45 +000066 default:
67 // op not supported
68 return NULL;
69 }
70}
71
John R. Lentona41fe312014-01-06 17:17:02 +000072
73/******************************************************************************/
74/* dict iterator */
75
76typedef struct _mp_obj_dict_it_t {
77 mp_obj_base_t base;
78 mp_obj_dict_t *dict;
79 machine_uint_t cur;
80} mp_obj_dict_it_t;
81
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +020082STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in) {
John R. Lentona41fe312014-01-06 17:17:02 +000083 mp_obj_dict_it_t *self = self_in;
84 machine_uint_t max = self->dict->map.alloc;
85 mp_map_elem_t *table = self->dict->map.table;
86
87 for (int i = self->cur; i < max; i++) {
88 if (table[i].key != NULL) {
89 self->cur = i + 1;
90 return &(table[i]);
91 }
92 }
93
94 return NULL;
95}
96
97mp_obj_t dict_it_iternext(mp_obj_t self_in) {
98 mp_map_elem_t *next = dict_it_iternext_elem(self_in);
99
100 if (next != NULL) {
101 return next->key;
102 } else {
Damien George66eaf842014-03-26 19:27:58 +0000103 return MP_OBJ_NULL;
John R. Lentona41fe312014-01-06 17:17:02 +0000104 }
105}
106
Damien George3e1a5c12014-03-29 13:43:38 +0000107STATIC const mp_obj_type_t mp_type_dict_it = {
Damien Georgec5966122014-02-15 16:10:44 +0000108 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +0000109 .name = MP_QSTR_iterator,
John R. Lentona41fe312014-01-06 17:17:02 +0000110 .iternext = dict_it_iternext,
John R. Lentona41fe312014-01-06 17:17:02 +0000111};
112
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200113STATIC mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur) {
John R. Lentona41fe312014-01-06 17:17:02 +0000114 mp_obj_dict_it_t *o = m_new_obj(mp_obj_dict_it_t);
Damien George3e1a5c12014-03-29 13:43:38 +0000115 o->base.type = &mp_type_dict_it;
John R. Lentona41fe312014-01-06 17:17:02 +0000116 o->dict = dict;
117 o->cur = cur;
118 return o;
119}
120
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200121STATIC mp_obj_t dict_getiter(mp_obj_t o_in) {
John R. Lentona41fe312014-01-06 17:17:02 +0000122 return mp_obj_new_dict_iterator(o_in, 0);
123}
124
125/******************************************************************************/
126/* dict methods */
127
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200128STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000129 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
John R. Lenton4ce6cea2014-01-06 17:38:47 +0000130 mp_obj_dict_t *self = self_in;
131
132 mp_map_clear(&self->map);
133
134 return mp_const_none;
135}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200136STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);
John R. Lenton7d21d512014-01-06 17:54:04 +0000137
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200138STATIC mp_obj_t dict_copy(mp_obj_t self_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000139 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
John R. Lentond90b19e2014-01-06 18:11:20 +0000140 mp_obj_dict_t *self = self_in;
141 mp_obj_dict_t *other = mp_obj_new_dict(self->map.alloc);
142 other->map.used = self->map.used;
143 memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t));
144 return other;
145}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200146STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy);
John R. Lenton4ce6cea2014-01-06 17:38:47 +0000147
Damien Georgeeae16442014-01-11 19:22:29 +0000148// this is a classmethod
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200149STATIC mp_obj_t dict_fromkeys(uint n_args, const mp_obj_t *args) {
Damien Georgeeae16442014-01-11 19:22:29 +0000150 assert(2 <= n_args && n_args <= 3);
Damien Georged17926d2014-03-30 13:35:08 +0100151 mp_obj_t iter = mp_getiter(args[1]);
Damien Georgeeae16442014-01-11 19:22:29 +0000152 mp_obj_t len = mp_obj_len_maybe(iter);
153 mp_obj_t value = mp_const_none;
154 mp_obj_t next = NULL;
155 mp_obj_dict_t *self = NULL;
156
157 if (n_args > 2) {
158 value = args[2];
159 }
160
161 if (len == MP_OBJ_NULL) {
162 /* object's type doesn't have a __len__ slot */
163 self = mp_obj_new_dict(0);
164 } else {
165 self = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
166 }
167
Damien Georged17926d2014-03-30 13:35:08 +0100168 while ((next = mp_iternext(iter)) != MP_OBJ_NULL) {
Damien Georgeeae16442014-01-11 19:22:29 +0000169 mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
170 }
171
172 return self;
173}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200174STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_fun_obj, 2, 3, dict_fromkeys);
175STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, (const mp_obj_t)&dict_fromkeys_fun_obj);
Damien Georgeeae16442014-01-11 19:22:29 +0000176
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200177STATIC mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp_map_lookup_kind_t lookup_kind) {
Damien George38a2da62014-01-08 17:33:12 +0000178 mp_map_elem_t *elem = mp_map_lookup(self, key, lookup_kind);
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000179 mp_obj_t value;
180 if (elem == NULL || elem->value == NULL) {
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000181 if (deflt == NULL) {
Damien George38a2da62014-01-08 17:33:12 +0000182 if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
Damien Georgec5966122014-02-15 16:10:44 +0000183 nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>"));
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000184 } else {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000185 value = mp_const_none;
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000186 }
187 } else {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000188 value = deflt;
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000189 }
190 } else {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000191 value = elem->value;
Damien George38a2da62014-01-08 17:33:12 +0000192 if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
193 // catch the leak (from mp_map_lookup)
John R. Lenton88f30432014-01-06 22:58:17 +0000194 m_free(elem, sizeof(mp_map_elem_t));
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000195 }
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000196 }
Damien George38a2da62014-01-08 17:33:12 +0000197 if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000198 elem->value = value;
199 }
200 return value;
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000201}
202
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200203STATIC mp_obj_t dict_get(uint n_args, const mp_obj_t *args) {
John R. Lentoncd088732014-01-06 18:53:16 +0000204 assert(2 <= n_args && n_args <= 3);
Damien George3e1a5c12014-03-29 13:43:38 +0000205 assert(MP_OBJ_IS_TYPE(args[0], &mp_type_dict));
John R. Lentoncd088732014-01-06 18:53:16 +0000206
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000207 return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
208 args[1],
209 n_args == 3 ? args[2] : NULL,
Damien George38a2da62014-01-08 17:33:12 +0000210 MP_MAP_LOOKUP);
John R. Lentoncd088732014-01-06 18:53:16 +0000211}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200212STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get);
John R. Lentoncd088732014-01-06 18:53:16 +0000213
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200214STATIC mp_obj_t dict_pop(uint n_args, const mp_obj_t *args) {
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000215 assert(2 <= n_args && n_args <= 3);
Damien George3e1a5c12014-03-29 13:43:38 +0000216 assert(MP_OBJ_IS_TYPE(args[0], &mp_type_dict));
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000217
218 return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
219 args[1],
220 n_args == 3 ? args[2] : NULL,
Damien George38a2da62014-01-08 17:33:12 +0000221 MP_MAP_LOOKUP_REMOVE_IF_FOUND);
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000222}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200223STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop);
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000224
225
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200226STATIC mp_obj_t dict_setdefault(uint n_args, const mp_obj_t *args) {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000227 assert(2 <= n_args && n_args <= 3);
Damien George3e1a5c12014-03-29 13:43:38 +0000228 assert(MP_OBJ_IS_TYPE(args[0], &mp_type_dict));
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000229
230 return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
231 args[1],
232 n_args == 3 ? args[2] : NULL,
Damien George38a2da62014-01-08 17:33:12 +0000233 MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000234}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200235STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setdefault);
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000236
John R. Lentonf77dce82014-01-06 20:08:52 +0000237
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200238STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000239 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
John R. Lentonf77dce82014-01-06 20:08:52 +0000240 mp_obj_dict_t *self = self_in;
241 if (self->map.used == 0) {
Damien Georgec5966122014-02-15 16:10:44 +0000242 nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "popitem(): dictionary is empty"));
John R. Lentonf77dce82014-01-06 20:08:52 +0000243 }
244 mp_obj_dict_it_t *iter = mp_obj_new_dict_iterator(self, 0);
245
246 mp_map_elem_t *next = dict_it_iternext_elem(iter);
247 self->map.used--;
248 mp_obj_t items[] = {next->key, next->value};
249 next->key = NULL;
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000250 next->value = NULL;
John R. Lentonf77dce82014-01-06 20:08:52 +0000251 mp_obj_t tuple = mp_obj_new_tuple(2, items);
252
253 return tuple;
254}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200255STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);
John R. Lentonf77dce82014-01-06 20:08:52 +0000256
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200257STATIC mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) {
Damien George3e1a5c12014-03-29 13:43:38 +0000258 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
John R. Lenton88f30432014-01-06 22:58:17 +0000259 mp_obj_dict_t *self = self_in;
260 /* TODO: check for the "keys" method */
Damien Georged17926d2014-03-30 13:35:08 +0100261 mp_obj_t iter = mp_getiter(iterable);
John R. Lenton88f30432014-01-06 22:58:17 +0000262 mp_obj_t next = NULL;
Damien Georged17926d2014-03-30 13:35:08 +0100263 while ((next = mp_iternext(iter)) != MP_OBJ_NULL) {
264 mp_obj_t inneriter = mp_getiter(next);
265 mp_obj_t key = mp_iternext(inneriter);
266 mp_obj_t value = mp_iternext(inneriter);
267 mp_obj_t stop = mp_iternext(inneriter);
Damien George66eaf842014-03-26 19:27:58 +0000268 if (key == MP_OBJ_NULL
269 || value == MP_OBJ_NULL
270 || stop != MP_OBJ_NULL) {
John R. Lenton88f30432014-01-06 22:58:17 +0000271 nlr_jump(mp_obj_new_exception_msg(
Damien Georgec5966122014-02-15 16:10:44 +0000272 &mp_type_ValueError,
John R. Lenton88f30432014-01-06 22:58:17 +0000273 "dictionary update sequence has the wrong length"));
274 } else {
Damien George38a2da62014-01-08 17:33:12 +0000275 mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
John R. Lenton88f30432014-01-06 22:58:17 +0000276 }
277 }
278
279 return mp_const_none;
280}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200281STATIC MP_DEFINE_CONST_FUN_OBJ_2(dict_update_obj, dict_update);
John R. Lenton88f30432014-01-06 22:58:17 +0000282
John R. Lentonf77dce82014-01-06 20:08:52 +0000283
John R. Lentona41fe312014-01-06 17:17:02 +0000284/******************************************************************************/
John R. Lenton9ec3a872014-01-10 01:00:20 +0000285/* dict views */
286
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200287STATIC const mp_obj_type_t dict_view_type;
288STATIC const mp_obj_type_t dict_view_it_type;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000289
290typedef enum _mp_dict_view_kind_t {
291 MP_DICT_VIEW_ITEMS,
292 MP_DICT_VIEW_KEYS,
293 MP_DICT_VIEW_VALUES,
294} mp_dict_view_kind_t;
295
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200296STATIC char *mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
John R. Lenton9ec3a872014-01-10 01:00:20 +0000297
298typedef struct _mp_obj_dict_view_it_t {
299 mp_obj_base_t base;
300 mp_dict_view_kind_t kind;
301 mp_obj_dict_it_t *iter;
302 machine_uint_t cur;
303} mp_obj_dict_view_it_t;
304
305typedef struct _mp_obj_dict_view_t {
306 mp_obj_base_t base;
307 mp_obj_dict_t *dict;
308 mp_dict_view_kind_t kind;
309} mp_obj_dict_view_t;
310
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200311STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000312 assert(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type));
313 mp_obj_dict_view_it_t *self = self_in;
314 mp_map_elem_t *next = dict_it_iternext_elem(self->iter);
315
316 if (next != NULL) {
317 switch (self->kind) {
Damien Georgeeae16442014-01-11 19:22:29 +0000318 case MP_DICT_VIEW_ITEMS:
319 {
320 mp_obj_t items[] = {next->key, next->value};
321 return mp_obj_new_tuple(2, items);
322 }
323 case MP_DICT_VIEW_KEYS:
324 return next->key;
325 case MP_DICT_VIEW_VALUES:
326 return next->value;
327 default:
328 assert(0); /* can't happen */
329 return mp_const_none;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000330 }
331 } else {
Damien George66eaf842014-03-26 19:27:58 +0000332 return MP_OBJ_NULL;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000333 }
334}
335
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200336STATIC const mp_obj_type_t dict_view_it_type = {
Damien Georgec5966122014-02-15 16:10:44 +0000337 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +0000338 .name = MP_QSTR_iterator,
John R. Lenton9ec3a872014-01-10 01:00:20 +0000339 .iternext = dict_view_it_iternext,
John R. Lenton9ec3a872014-01-10 01:00:20 +0000340};
341
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200342STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000343 assert(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
344 mp_obj_dict_view_t *view = view_in;
345 mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t);
346 o->base.type = &dict_view_it_type;
347 o->kind = view->kind;
348 o->iter = mp_obj_new_dict_iterator(view->dict, 0);
349 return o;
350}
351
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200352STATIC void dict_view_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000353 assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
354 mp_obj_dict_view_t *self = self_in;
355 bool first = true;
356 print(env, mp_dict_view_names[self->kind]);
357 print(env, "([");
358 mp_obj_t *self_iter = dict_view_getiter(self);
359 mp_obj_t *next = NULL;
Damien George66eaf842014-03-26 19:27:58 +0000360 while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_NULL) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000361 if (!first) {
362 print(env, ", ");
363 }
364 first = false;
Paul Sokolovsky76d982e2014-01-13 19:19:16 +0200365 mp_obj_print_helper(print, env, next, PRINT_REPR);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000366 }
367 print(env, "])");
368}
369
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200370STATIC mp_obj_t dict_view_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
John R. Lentonc1bef212014-01-11 12:39:33 +0000371 /* only supported for the 'keys' kind until sets and dicts are refactored */
372 mp_obj_dict_view_t *o = lhs_in;
373 if (o->kind != MP_DICT_VIEW_KEYS) return NULL;
Damien Georged17926d2014-03-30 13:35:08 +0100374 if (op != MP_BINARY_OP_IN) return NULL;
John R. Lentonc1bef212014-01-11 12:39:33 +0000375 return dict_binary_op(op, o->dict, rhs_in);
376}
377
378
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200379STATIC const mp_obj_type_t dict_view_type = {
Damien Georgec5966122014-02-15 16:10:44 +0000380 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +0000381 .name = MP_QSTR_dict_view,
John R. Lenton9ec3a872014-01-10 01:00:20 +0000382 .print = dict_view_print,
John R. Lentonc1bef212014-01-11 12:39:33 +0000383 .binary_op = dict_view_binary_op,
John R. Lenton9ec3a872014-01-10 01:00:20 +0000384 .getiter = dict_view_getiter,
385};
386
387mp_obj_t mp_obj_new_dict_view(mp_obj_dict_t *dict, mp_dict_view_kind_t kind) {
388 mp_obj_dict_view_t *o = m_new_obj(mp_obj_dict_view_t);
389 o->base.type = &dict_view_type;
390 o->dict = dict;
391 o->kind = kind;
392 return o;
393}
394
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200395STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
Damien George3e1a5c12014-03-29 13:43:38 +0000396 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
John R. Lenton9ec3a872014-01-10 01:00:20 +0000397 mp_obj_dict_t *self = self_in;
398 return mp_obj_new_dict_view(self, kind);
399}
400
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200401STATIC mp_obj_t dict_items(mp_obj_t self_in) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000402 return dict_view(self_in, MP_DICT_VIEW_ITEMS);
403}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200404STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000405
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200406STATIC mp_obj_t dict_keys(mp_obj_t self_in) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000407 return dict_view(self_in, MP_DICT_VIEW_KEYS);
408}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200409STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000410
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200411STATIC mp_obj_t dict_values(mp_obj_t self_in) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000412 return dict_view(self_in, MP_DICT_VIEW_VALUES);
413}
Paul Sokolovskyd5df6cd2014-02-12 18:15:40 +0200414STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000415
John R. Lenton4bee76e2014-01-10 11:25:03 +0000416/******************************************************************************/
Damien Georgeeae16442014-01-11 19:22:29 +0000417/* dict constructors & public C API */
John R. Lentona41fe312014-01-06 17:17:02 +0000418
Damien George9b196cd2014-03-26 21:47:19 +0000419STATIC const mp_map_elem_t dict_locals_dict_table[] = {
420 { MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&dict_clear_obj },
421 { MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&dict_copy_obj },
422 { MP_OBJ_NEW_QSTR(MP_QSTR_fromkeys), (mp_obj_t)&dict_fromkeys_obj },
423 { MP_OBJ_NEW_QSTR(MP_QSTR_get), (mp_obj_t)&dict_get_obj },
424 { MP_OBJ_NEW_QSTR(MP_QSTR_items), (mp_obj_t)&dict_items_obj },
425 { MP_OBJ_NEW_QSTR(MP_QSTR_keys), (mp_obj_t)&dict_keys_obj },
426 { MP_OBJ_NEW_QSTR(MP_QSTR_pop), (mp_obj_t)&dict_pop_obj },
427 { MP_OBJ_NEW_QSTR(MP_QSTR_popitem), (mp_obj_t)&dict_popitem_obj },
428 { MP_OBJ_NEW_QSTR(MP_QSTR_setdefault), (mp_obj_t)&dict_setdefault_obj },
429 { MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&dict_update_obj },
430 { MP_OBJ_NEW_QSTR(MP_QSTR_values), (mp_obj_t)&dict_values_obj },
John R. Lentonbaa66542014-01-07 23:18:25 +0000431};
432
Damien George9b196cd2014-03-26 21:47:19 +0000433STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);
434
Damien George3e1a5c12014-03-29 13:43:38 +0000435const mp_obj_type_t mp_type_dict = {
Damien Georgec5966122014-02-15 16:10:44 +0000436 { &mp_type_type },
Damien Georgea71c83a2014-02-15 11:34:50 +0000437 .name = MP_QSTR_dict,
Paul Sokolovsky860ffb02014-01-05 22:34:09 +0200438 .print = dict_print,
439 .make_new = dict_make_new,
Damien George4e8dc8c2014-01-27 23:15:32 +0000440 .unary_op = dict_unary_op,
Paul Sokolovsky860ffb02014-01-05 22:34:09 +0200441 .binary_op = dict_binary_op,
John R. Lentona41fe312014-01-06 17:17:02 +0000442 .getiter = dict_getiter,
Damien George9b196cd2014-03-26 21:47:19 +0000443 .locals_dict = (mp_obj_t)&dict_locals_dict,
Damiend99b0522013-12-21 18:17:45 +0000444};
445
446mp_obj_t mp_obj_new_dict(int n_args) {
447 mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);
Damien George3e1a5c12014-03-29 13:43:38 +0000448 o->base.type = &mp_type_dict;
Damien George38a2da62014-01-08 17:33:12 +0000449 mp_map_init(&o->map, n_args);
Damiend99b0522013-12-21 18:17:45 +0000450 return o;
451}
Damiendae7eb72013-12-29 22:32:51 +0000452
453uint mp_obj_dict_len(mp_obj_t self_in) {
John R. Lentoncd088732014-01-06 18:53:16 +0000454 return ((mp_obj_dict_t *)self_in)->map.used;
Damiendae7eb72013-12-29 22:32:51 +0000455}
456
457mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
Damien George3e1a5c12014-03-29 13:43:38 +0000458 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
Damiendae7eb72013-12-29 22:32:51 +0000459 mp_obj_dict_t *self = self_in;
Damien George38a2da62014-01-08 17:33:12 +0000460 mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
Damiendae7eb72013-12-29 22:32:51 +0000461 return self_in;
462}
Damien George062478e2014-01-09 20:57:50 +0000463
464mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) {
Damien George3e1a5c12014-03-29 13:43:38 +0000465 assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
Damien George062478e2014-01-09 20:57:50 +0000466 mp_obj_dict_t *self = self_in;
467 return &self->map;
468}