blob: 934eb506504593463659a5ab432fe05c4edb7993 [file] [log] [blame]
Damiend99b0522013-12-21 18:17:45 +00001#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
4#include <assert.h>
5
6#include "nlr.h"
7#include "misc.h"
8#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +00009#include "qstr.h"
Damiend99b0522013-12-21 18:17:45 +000010#include "obj.h"
11#include "runtime0.h"
12#include "runtime.h"
13#include "map.h"
14
15typedef struct _mp_obj_dict_t {
16 mp_obj_base_t base;
17 mp_map_t map;
18} mp_obj_dict_t;
19
John R. Lentona41fe312014-01-06 17:17:02 +000020static mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur);
21static mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in);
22
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020023static 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 +000024 mp_obj_dict_t *self = self_in;
25 bool first = true;
26 print(env, "{");
John R. Lentona41fe312014-01-06 17:17:02 +000027 mp_obj_t *dict_iter = mp_obj_new_dict_iterator(self, 0);
28 mp_map_elem_t *next = NULL;
29 while ((next = dict_it_iternext_elem(dict_iter)) != NULL) {
30 if (!first) {
31 print(env, ", ");
Damiend99b0522013-12-21 18:17:45 +000032 }
John R. Lentona41fe312014-01-06 17:17:02 +000033 first = false;
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020034 mp_obj_print_helper(print, env, next->key, PRINT_REPR);
John R. Lentona41fe312014-01-06 17:17:02 +000035 print(env, ": ");
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020036 mp_obj_print_helper(print, env, next->value, PRINT_REPR);
Damiend99b0522013-12-21 18:17:45 +000037 }
38 print(env, "}");
39}
40
Damien George20006db2014-01-18 14:10:48 +000041static 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 +000042 // TODO create from an iterable!
43 return rt_build_map(0);
44}
45
Damien George4e8dc8c2014-01-27 23:15:32 +000046static mp_obj_t dict_unary_op(int op, mp_obj_t self_in) {
47 mp_obj_dict_t *self = self_in;
48 switch (op) {
Paul Sokolovskyc1d9bbc2014-01-30 04:37:19 +020049 case RT_UNARY_OP_BOOL: return MP_BOOL(self->map.used != 0);
Damien George09a0c642014-01-30 10:05:33 +000050 case RT_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->map.used);
Damien George4e8dc8c2014-01-27 23:15:32 +000051 default: return MP_OBJ_NULL; // op not supported for None
52 }
53}
54
Damien George71c51812014-01-04 20:21:15 +000055static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
Damiend99b0522013-12-21 18:17:45 +000056 mp_obj_dict_t *o = lhs_in;
57 switch (op) {
58 case RT_BINARY_OP_SUBSCR:
59 {
60 // dict load
Damien George38a2da62014-01-08 17:33:12 +000061 mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
Damiend99b0522013-12-21 18:17:45 +000062 if (elem == NULL) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +000063 nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "<value>"));
Damiend99b0522013-12-21 18:17:45 +000064 } else {
65 return elem->value;
66 }
67 }
John R. Lentonc1bef212014-01-11 12:39:33 +000068 case RT_COMPARE_OP_IN:
69 case RT_COMPARE_OP_NOT_IN:
70 {
71 mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
72 return MP_BOOL((op == RT_COMPARE_OP_IN) ^ (elem == NULL));
73 }
Damiend99b0522013-12-21 18:17:45 +000074 default:
75 // op not supported
76 return NULL;
77 }
78}
79
John R. Lentona41fe312014-01-06 17:17:02 +000080
81/******************************************************************************/
82/* dict iterator */
83
84typedef struct _mp_obj_dict_it_t {
85 mp_obj_base_t base;
86 mp_obj_dict_t *dict;
87 machine_uint_t cur;
88} mp_obj_dict_it_t;
89
90static mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in) {
91 mp_obj_dict_it_t *self = self_in;
92 machine_uint_t max = self->dict->map.alloc;
93 mp_map_elem_t *table = self->dict->map.table;
94
95 for (int i = self->cur; i < max; i++) {
96 if (table[i].key != NULL) {
97 self->cur = i + 1;
98 return &(table[i]);
99 }
100 }
101
102 return NULL;
103}
104
105mp_obj_t dict_it_iternext(mp_obj_t self_in) {
106 mp_map_elem_t *next = dict_it_iternext_elem(self_in);
107
108 if (next != NULL) {
109 return next->key;
110 } else {
111 return mp_const_stop_iteration;
112 }
113}
114
115static const mp_obj_type_t dict_it_type = {
116 { &mp_const_type },
117 "dict_iterator",
118 .iternext = dict_it_iternext,
John R. Lentona41fe312014-01-06 17:17:02 +0000119};
120
121static mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur) {
122 mp_obj_dict_it_t *o = m_new_obj(mp_obj_dict_it_t);
123 o->base.type = &dict_it_type;
124 o->dict = dict;
125 o->cur = cur;
126 return o;
127}
128
129static mp_obj_t dict_getiter(mp_obj_t o_in) {
130 return mp_obj_new_dict_iterator(o_in, 0);
131}
132
133/******************************************************************************/
134/* dict methods */
135
John R. Lenton4ce6cea2014-01-06 17:38:47 +0000136static mp_obj_t dict_clear(mp_obj_t self_in) {
137 assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
138 mp_obj_dict_t *self = self_in;
139
140 mp_map_clear(&self->map);
141
142 return mp_const_none;
143}
John R. Lenton7d21d512014-01-06 17:54:04 +0000144static MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);
145
John R. Lentond90b19e2014-01-06 18:11:20 +0000146static mp_obj_t dict_copy(mp_obj_t self_in) {
147 assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
148 mp_obj_dict_t *self = self_in;
149 mp_obj_dict_t *other = mp_obj_new_dict(self->map.alloc);
150 other->map.used = self->map.used;
151 memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t));
152 return other;
153}
154static MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy);
John R. Lenton4ce6cea2014-01-06 17:38:47 +0000155
Damien Georgeeae16442014-01-11 19:22:29 +0000156// this is a classmethod
Damien Georgea11ceca2014-01-19 16:02:09 +0000157static mp_obj_t dict_fromkeys(uint n_args, const mp_obj_t *args) {
Damien Georgeeae16442014-01-11 19:22:29 +0000158 assert(2 <= n_args && n_args <= 3);
159 mp_obj_t iter = rt_getiter(args[1]);
160 mp_obj_t len = mp_obj_len_maybe(iter);
161 mp_obj_t value = mp_const_none;
162 mp_obj_t next = NULL;
163 mp_obj_dict_t *self = NULL;
164
165 if (n_args > 2) {
166 value = args[2];
167 }
168
169 if (len == MP_OBJ_NULL) {
170 /* object's type doesn't have a __len__ slot */
171 self = mp_obj_new_dict(0);
172 } else {
173 self = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
174 }
175
176 while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
177 mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
178 }
179
180 return self;
181}
182static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_fun_obj, 2, 3, dict_fromkeys);
183static MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, (const mp_obj_t)&dict_fromkeys_fun_obj);
184
Damien George38a2da62014-01-08 17:33:12 +0000185static 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) {
186 mp_map_elem_t *elem = mp_map_lookup(self, key, lookup_kind);
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000187 mp_obj_t value;
188 if (elem == NULL || elem->value == NULL) {
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000189 if (deflt == NULL) {
Damien George38a2da62014-01-08 17:33:12 +0000190 if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000191 nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "<value>"));
192 } else {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000193 value = mp_const_none;
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000194 }
195 } else {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000196 value = deflt;
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000197 }
198 } else {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000199 value = elem->value;
Damien George38a2da62014-01-08 17:33:12 +0000200 if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
201 // catch the leak (from mp_map_lookup)
John R. Lenton88f30432014-01-06 22:58:17 +0000202 m_free(elem, sizeof(mp_map_elem_t));
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000203 }
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000204 }
Damien George38a2da62014-01-08 17:33:12 +0000205 if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000206 elem->value = value;
207 }
208 return value;
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000209}
210
Damien Georgea11ceca2014-01-19 16:02:09 +0000211static mp_obj_t dict_get(uint n_args, const mp_obj_t *args) {
John R. Lentoncd088732014-01-06 18:53:16 +0000212 assert(2 <= n_args && n_args <= 3);
213 assert(MP_OBJ_IS_TYPE(args[0], &dict_type));
214
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000215 return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
216 args[1],
217 n_args == 3 ? args[2] : NULL,
Damien George38a2da62014-01-08 17:33:12 +0000218 MP_MAP_LOOKUP);
John R. Lentoncd088732014-01-06 18:53:16 +0000219}
220static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get);
221
Damien Georgea11ceca2014-01-19 16:02:09 +0000222static mp_obj_t dict_pop(uint n_args, const mp_obj_t *args) {
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000223 assert(2 <= n_args && n_args <= 3);
224 assert(MP_OBJ_IS_TYPE(args[0], &dict_type));
225
226 return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
227 args[1],
228 n_args == 3 ? args[2] : NULL,
Damien George38a2da62014-01-08 17:33:12 +0000229 MP_MAP_LOOKUP_REMOVE_IF_FOUND);
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000230}
231static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop);
232
233
Damien Georgea11ceca2014-01-19 16:02:09 +0000234static mp_obj_t dict_setdefault(uint n_args, const mp_obj_t *args) {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000235 assert(2 <= n_args && n_args <= 3);
236 assert(MP_OBJ_IS_TYPE(args[0], &dict_type));
237
238 return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
239 args[1],
240 n_args == 3 ? args[2] : NULL,
Damien George38a2da62014-01-08 17:33:12 +0000241 MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000242}
243static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setdefault);
244
John R. Lentonf77dce82014-01-06 20:08:52 +0000245
246static mp_obj_t dict_popitem(mp_obj_t self_in) {
247 assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
248 mp_obj_dict_t *self = self_in;
249 if (self->map.used == 0) {
250 nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "popitem(): dictionary is empty"));
251 }
252 mp_obj_dict_it_t *iter = mp_obj_new_dict_iterator(self, 0);
253
254 mp_map_elem_t *next = dict_it_iternext_elem(iter);
255 self->map.used--;
256 mp_obj_t items[] = {next->key, next->value};
257 next->key = NULL;
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000258 next->value = NULL;
John R. Lentonf77dce82014-01-06 20:08:52 +0000259 mp_obj_t tuple = mp_obj_new_tuple(2, items);
260
261 return tuple;
262}
263static MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);
264
John R. Lenton88f30432014-01-06 22:58:17 +0000265static mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) {
266 assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
267 mp_obj_dict_t *self = self_in;
268 /* TODO: check for the "keys" method */
269 mp_obj_t iter = rt_getiter(iterable);
270 mp_obj_t next = NULL;
271 while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
272 mp_obj_t inneriter = rt_getiter(next);
273 mp_obj_t key = rt_iternext(inneriter);
274 mp_obj_t value = rt_iternext(inneriter);
275 mp_obj_t stop = rt_iternext(inneriter);
276 if (key == mp_const_stop_iteration
277 || value == mp_const_stop_iteration
278 || stop != mp_const_stop_iteration) {
279 nlr_jump(mp_obj_new_exception_msg(
280 MP_QSTR_ValueError,
281 "dictionary update sequence has the wrong length"));
282 } else {
Damien George38a2da62014-01-08 17:33:12 +0000283 mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
John R. Lenton88f30432014-01-06 22:58:17 +0000284 }
285 }
286
287 return mp_const_none;
288}
289static MP_DEFINE_CONST_FUN_OBJ_2(dict_update_obj, dict_update);
290
John R. Lentonf77dce82014-01-06 20:08:52 +0000291
John R. Lentona41fe312014-01-06 17:17:02 +0000292/******************************************************************************/
John R. Lenton9ec3a872014-01-10 01:00:20 +0000293/* dict views */
294
295static const mp_obj_type_t dict_view_type;
296static const mp_obj_type_t dict_view_it_type;
297
298typedef enum _mp_dict_view_kind_t {
299 MP_DICT_VIEW_ITEMS,
300 MP_DICT_VIEW_KEYS,
301 MP_DICT_VIEW_VALUES,
302} mp_dict_view_kind_t;
303
304static char *mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
305
306typedef struct _mp_obj_dict_view_it_t {
307 mp_obj_base_t base;
308 mp_dict_view_kind_t kind;
309 mp_obj_dict_it_t *iter;
310 machine_uint_t cur;
311} mp_obj_dict_view_it_t;
312
313typedef struct _mp_obj_dict_view_t {
314 mp_obj_base_t base;
315 mp_obj_dict_t *dict;
316 mp_dict_view_kind_t kind;
317} mp_obj_dict_view_t;
318
319static mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
320 assert(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type));
321 mp_obj_dict_view_it_t *self = self_in;
322 mp_map_elem_t *next = dict_it_iternext_elem(self->iter);
323
324 if (next != NULL) {
325 switch (self->kind) {
Damien Georgeeae16442014-01-11 19:22:29 +0000326 case MP_DICT_VIEW_ITEMS:
327 {
328 mp_obj_t items[] = {next->key, next->value};
329 return mp_obj_new_tuple(2, items);
330 }
331 case MP_DICT_VIEW_KEYS:
332 return next->key;
333 case MP_DICT_VIEW_VALUES:
334 return next->value;
335 default:
336 assert(0); /* can't happen */
337 return mp_const_none;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000338 }
339 } else {
340 return mp_const_stop_iteration;
341 }
342}
343
344static const mp_obj_type_t dict_view_it_type = {
345 { &mp_const_type },
346 "dict_view_iterator",
347 .iternext = dict_view_it_iternext,
348 .methods = NULL, /* set operations still to come */
349};
350
351static mp_obj_t dict_view_getiter(mp_obj_t view_in) {
352 assert(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
353 mp_obj_dict_view_t *view = view_in;
354 mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t);
355 o->base.type = &dict_view_it_type;
356 o->kind = view->kind;
357 o->iter = mp_obj_new_dict_iterator(view->dict, 0);
358 return o;
359}
360
Paul Sokolovsky76d982e2014-01-13 19:19:16 +0200361static 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 +0000362 assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
363 mp_obj_dict_view_t *self = self_in;
364 bool first = true;
365 print(env, mp_dict_view_names[self->kind]);
366 print(env, "([");
367 mp_obj_t *self_iter = dict_view_getiter(self);
368 mp_obj_t *next = NULL;
369 while ((next = dict_view_it_iternext(self_iter)) != mp_const_stop_iteration) {
370 if (!first) {
371 print(env, ", ");
372 }
373 first = false;
Paul Sokolovsky76d982e2014-01-13 19:19:16 +0200374 mp_obj_print_helper(print, env, next, PRINT_REPR);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000375 }
376 print(env, "])");
377}
378
John R. Lentonc1bef212014-01-11 12:39:33 +0000379static mp_obj_t dict_view_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
380 /* only supported for the 'keys' kind until sets and dicts are refactored */
381 mp_obj_dict_view_t *o = lhs_in;
382 if (o->kind != MP_DICT_VIEW_KEYS) return NULL;
383 if (op != RT_COMPARE_OP_IN && op != RT_COMPARE_OP_NOT_IN) return NULL;
384 return dict_binary_op(op, o->dict, rhs_in);
385}
386
387
John R. Lenton9ec3a872014-01-10 01:00:20 +0000388static const mp_obj_type_t dict_view_type = {
389 { &mp_const_type },
390 "dict_view",
391 .print = dict_view_print,
John R. Lentonc1bef212014-01-11 12:39:33 +0000392 .binary_op = dict_view_binary_op,
John R. Lenton9ec3a872014-01-10 01:00:20 +0000393 .getiter = dict_view_getiter,
394};
395
396mp_obj_t mp_obj_new_dict_view(mp_obj_dict_t *dict, mp_dict_view_kind_t kind) {
397 mp_obj_dict_view_t *o = m_new_obj(mp_obj_dict_view_t);
398 o->base.type = &dict_view_type;
399 o->dict = dict;
400 o->kind = kind;
401 return o;
402}
403
John R. Lenton9ec3a872014-01-10 01:00:20 +0000404static mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
405 assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
406 mp_obj_dict_t *self = self_in;
407 return mp_obj_new_dict_view(self, kind);
408}
409
410static mp_obj_t dict_items(mp_obj_t self_in) {
411 return dict_view(self_in, MP_DICT_VIEW_ITEMS);
412}
413static MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items);
414
415static mp_obj_t dict_keys(mp_obj_t self_in) {
416 return dict_view(self_in, MP_DICT_VIEW_KEYS);
417}
418static MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys);
419
420static mp_obj_t dict_values(mp_obj_t self_in) {
421 return dict_view(self_in, MP_DICT_VIEW_VALUES);
422}
423static MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
424
John R. Lenton4bee76e2014-01-10 11:25:03 +0000425/******************************************************************************/
Damien Georgeeae16442014-01-11 19:22:29 +0000426/* dict constructors & public C API */
John R. Lentona41fe312014-01-06 17:17:02 +0000427
John R. Lentonbaa66542014-01-07 23:18:25 +0000428static const mp_method_t dict_type_methods[] = {
429 { "clear", &dict_clear_obj },
430 { "copy", &dict_copy_obj },
Damien Georgeeae16442014-01-11 19:22:29 +0000431 { "fromkeys", &dict_fromkeys_obj },
John R. Lentonbaa66542014-01-07 23:18:25 +0000432 { "get", &dict_get_obj },
John R. Lenton9ec3a872014-01-10 01:00:20 +0000433 { "items", &dict_items_obj },
434 { "keys", &dict_keys_obj },
John R. Lentonbaa66542014-01-07 23:18:25 +0000435 { "pop", &dict_pop_obj },
436 { "popitem", &dict_popitem_obj },
437 { "setdefault", &dict_setdefault_obj },
438 { "update", &dict_update_obj },
John R. Lenton9ec3a872014-01-10 01:00:20 +0000439 { "values", &dict_values_obj },
John R. Lentonbaa66542014-01-07 23:18:25 +0000440 { NULL, NULL }, // end-of-list sentinel
441};
442
Damiend99b0522013-12-21 18:17:45 +0000443const mp_obj_type_t dict_type = {
Damien Georgeeae16442014-01-11 19:22:29 +0000444 { &mp_const_type },
Damiend99b0522013-12-21 18:17:45 +0000445 "dict",
Paul Sokolovsky860ffb02014-01-05 22:34:09 +0200446 .print = dict_print,
447 .make_new = dict_make_new,
Damien George4e8dc8c2014-01-27 23:15:32 +0000448 .unary_op = dict_unary_op,
Paul Sokolovsky860ffb02014-01-05 22:34:09 +0200449 .binary_op = dict_binary_op,
John R. Lentona41fe312014-01-06 17:17:02 +0000450 .getiter = dict_getiter,
John R. Lentonbaa66542014-01-07 23:18:25 +0000451 .methods = dict_type_methods,
Damiend99b0522013-12-21 18:17:45 +0000452};
453
454mp_obj_t mp_obj_new_dict(int n_args) {
455 mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);
456 o->base.type = &dict_type;
Damien George38a2da62014-01-08 17:33:12 +0000457 mp_map_init(&o->map, n_args);
Damiend99b0522013-12-21 18:17:45 +0000458 return o;
459}
Damiendae7eb72013-12-29 22:32:51 +0000460
461uint mp_obj_dict_len(mp_obj_t self_in) {
John R. Lentoncd088732014-01-06 18:53:16 +0000462 return ((mp_obj_dict_t *)self_in)->map.used;
Damiendae7eb72013-12-29 22:32:51 +0000463}
464
465mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
466 assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
467 mp_obj_dict_t *self = self_in;
Damien George38a2da62014-01-08 17:33:12 +0000468 mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
Damiendae7eb72013-12-29 22:32:51 +0000469 return self_in;
470}
Damien George062478e2014-01-09 20:57:50 +0000471
472mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) {
473 assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
474 mp_obj_dict_t *self = self_in;
475 return &self->map;
476}