blob: cf64fa9555a28676f1eb6cd1cb819b48d8c8669b [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
Alexander Steffen55f33242017-06-30 09:22:17 +02002 * This file is part of the MicroPython project, http://micropython.org/
Damien George04b91472014-05-03 23:27:38 +01003 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
Paul Sokolovsky016d9a42019-05-14 15:51:57 +03007 * Copyright (c) 2014-2017 Paul Sokolovsky
Damien George04b91472014-05-03 23:27:38 +01008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 */
27
Damiend99b0522013-12-21 18:17:45 +000028#include <string.h>
29#include <assert.h>
30
Damien George51dfcb42015-01-01 20:27:54 +000031#include "py/runtime.h"
32#include "py/builtin.h"
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +020033#include "py/objtype.h"
Eric Poulsen01054f22019-07-16 14:29:22 -070034#include "py/objstr.h"
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +020035
Jim Mussaredb41aaaa2022-09-17 22:22:32 +100036bool mp_obj_is_dict_or_ordereddict(mp_obj_t o) {
37 return mp_obj_is_obj(o) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(o))->type, make_new) == mp_obj_dict_make_new;
38}
39
Jim Mussared880875b2020-10-09 17:10:29 +110040const mp_obj_dict_t mp_const_empty_dict_obj = {
41 .base = { .type = &mp_type_dict },
42 .map = {
43 .all_keys_are_qstrs = 0,
44 .is_fixed = 1,
45 .is_ordered = 1,
46 .used = 0,
47 .alloc = 0,
48 .table = NULL,
49 }
50};
51
Angus Grattondecf8e62024-02-27 15:32:29 +110052static mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
John R. Lentona41fe312014-01-06 17:17:02 +000053
Damien George8a9b9992014-09-17 15:53:03 +010054// This is a helper function to iterate through a dictionary. The state of
55// the iteration is held in *cur and should be initialised with zero for the
56// first call. Will return NULL when no more elements are available.
Angus Grattondecf8e62024-02-27 15:32:29 +110057static mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) {
Damien George1ea2f7a2017-02-16 16:15:04 +110058 size_t max = dict->map.alloc;
Damien George8a9b9992014-09-17 15:53:03 +010059 mp_map_t *map = &dict->map;
60
Jim Mussared57fce3b2020-04-23 01:10:30 +100061 size_t i = *cur;
62 for (; i < max; i++) {
Damien George054dd332019-01-30 21:57:29 +110063 if (mp_map_slot_is_filled(map, i)) {
Damien George8a9b9992014-09-17 15:53:03 +010064 *cur = i + 1;
65 return &(map->table[i]);
66 }
67 }
68
Jim Mussared57fce3b2020-04-23 01:10:30 +100069 assert(map->used == 0 || i == max);
Damien George8a9b9992014-09-17 15:53:03 +010070 return NULL;
71}
72
Angus Grattondecf8e62024-02-27 15:32:29 +110073static void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
Damien George999cedb2015-11-27 17:01:44 +000074 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Damiend99b0522013-12-21 18:17:45 +000075 bool first = true;
Peter Zügerffc854f2021-02-03 09:24:25 +010076 const char *item_separator = ", ";
77 const char *key_separator = ": ";
Jim Mussaredf5f9edf2022-08-18 15:01:26 +100078 if (!(MICROPY_PY_JSON && kind == PRINT_JSON)) {
Damien George612045f2014-09-17 22:56:34 +010079 kind = PRINT_REPR;
Peter Zügerffc854f2021-02-03 09:24:25 +010080 } else {
Jim Mussaredf5f9edf2022-08-18 15:01:26 +100081 #if MICROPY_PY_JSON_SEPARATORS
Peter Zügerffc854f2021-02-03 09:24:25 +010082 item_separator = MP_PRINT_GET_EXT(print)->item_separator;
83 key_separator = MP_PRINT_GET_EXT(print)->key_separator;
84 #endif
Damien George612045f2014-09-17 22:56:34 +010085 }
Andrew Leech1e87f112019-11-11 15:44:04 +110086 if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) {
Damien George044c4732015-04-11 13:03:37 +010087 mp_printf(print, "%q(", self->base.type->name);
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +020088 }
Damien George7f9d1d62015-04-09 23:56:15 +010089 mp_print_str(print, "{");
Damien George1ea2f7a2017-02-16 16:15:04 +110090 size_t cur = 0;
John R. Lentona41fe312014-01-06 17:17:02 +000091 mp_map_elem_t *next = NULL;
Damien George8a9b9992014-09-17 15:53:03 +010092 while ((next = dict_iter_next(self, &cur)) != NULL) {
John R. Lentona41fe312014-01-06 17:17:02 +000093 if (!first) {
Peter Zügerffc854f2021-02-03 09:24:25 +010094 mp_print_str(print, item_separator);
Damiend99b0522013-12-21 18:17:45 +000095 }
John R. Lentona41fe312014-01-06 17:17:02 +000096 first = false;
Jim Mussaredf5f9edf2022-08-18 15:01:26 +100097 bool add_quote = MICROPY_PY_JSON && kind == PRINT_JSON && !mp_obj_is_str_or_bytes(next->key);
Eric Poulsen01054f22019-07-16 14:29:22 -070098 if (add_quote) {
99 mp_print_str(print, "\"");
100 }
Damien George7f9d1d62015-04-09 23:56:15 +0100101 mp_obj_print_helper(print, next->key, kind);
Eric Poulsen01054f22019-07-16 14:29:22 -0700102 if (add_quote) {
103 mp_print_str(print, "\"");
104 }
Peter Zügerffc854f2021-02-03 09:24:25 +0100105 mp_print_str(print, key_separator);
Damien George7f9d1d62015-04-09 23:56:15 +0100106 mp_obj_print_helper(print, next->value, kind);
Damiend99b0522013-12-21 18:17:45 +0000107 }
Damien George7f9d1d62015-04-09 23:56:15 +0100108 mp_print_str(print, "}");
Andrew Leech1e87f112019-11-11 15:44:04 +1100109 if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) {
Damien George7f9d1d62015-04-09 23:56:15 +0100110 mp_print_str(print, ")");
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200111 }
Damiend99b0522013-12-21 18:17:45 +0000112}
113
Damien George456a3ab2020-06-21 17:10:20 +1000114mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200115 mp_obj_t dict_out = mp_obj_new_dict(0);
Damien George999cedb2015-11-27 17:01:44 +0000116 mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out);
Damien George5b3f0b72016-01-03 15:55:55 +0000117 dict->base.type = type;
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200118 #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
Damien George5b3f0b72016-01-03 15:55:55 +0000119 if (type == &mp_type_ordereddict) {
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200120 dict->map.is_ordered = 1;
121 }
122 #endif
Damien Georgebcb6ca42014-06-03 12:53:44 +0100123 if (n_args > 0 || n_kw > 0) {
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200124 mp_obj_t args2[2] = {dict_out, args[0]}; // args[0] is always valid, even if it's not a positional arg
Damien Georgebcb6ca42014-06-03 12:53:44 +0100125 mp_map_t kwargs;
126 mp_map_init_fixed_table(&kwargs, n_kw, args + n_args);
127 dict_update(n_args + 1, args2, &kwargs); // dict_update will check that n_args + 1 == 1 or 2
Damien Georged7aadcf2014-04-04 15:08:00 +0100128 }
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200129 return dict_out;
Damien George71c51812014-01-04 20:21:15 +0000130}
131
Angus Grattondecf8e62024-02-27 15:32:29 +1100132static mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
Damien George999cedb2015-11-27 17:01:44 +0000133 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Damien George4e8dc8c2014-01-27 23:15:32 +0000134 switch (op) {
Damien George69661f32020-02-27 15:36:53 +1100135 case MP_UNARY_OP_BOOL:
136 return mp_obj_new_bool(self->map.used != 0);
137 case MP_UNARY_OP_LEN:
138 return MP_OBJ_NEW_SMALL_INT(self->map.used);
Paul Sokolovskybfc20922017-08-11 09:42:39 +0300139 #if MICROPY_PY_SYS_GETSIZEOF
140 case MP_UNARY_OP_SIZEOF: {
141 size_t sz = sizeof(*self) + sizeof(*self->map.table) * self->map.alloc;
142 return MP_OBJ_NEW_SMALL_INT(sz);
143 }
144 #endif
Damien George69661f32020-02-27 15:36:53 +1100145 default:
146 return MP_OBJ_NULL; // op not supported
Damien George4e8dc8c2014-01-27 23:15:32 +0000147 }
148}
149
Angus Grattondecf8e62024-02-27 15:32:29 +1100150static mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
Damien George999cedb2015-11-27 17:01:44 +0000151 mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in);
Damiend99b0522013-12-21 18:17:45 +0000152 switch (op) {
Damien George5e34a112017-11-24 13:04:24 +1100153 case MP_BINARY_OP_CONTAINS: {
John R. Lentonc1bef212014-01-11 12:39:33 +0000154 mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
Paul Sokolovsky1b586f32015-10-11 12:09:43 +0300155 return mp_obj_new_bool(elem != NULL);
John R. Lentonc1bef212014-01-11 12:39:33 +0000156 }
Paul Sokolovsky7cf057a2014-04-06 21:20:52 +0300157 case MP_BINARY_OP_EQUAL: {
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200158 #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
Damien Georgeeee1e882019-01-30 18:49:52 +1100159 if (MP_UNLIKELY(mp_obj_is_type(lhs_in, &mp_type_ordereddict) && mp_obj_is_type(rhs_in, &mp_type_ordereddict))) {
Mark Anthony Palomer31310532016-06-05 18:48:25 -0700160 // Iterate through both dictionaries simultaneously and compare keys and values.
161 mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in);
Damien George1ea2f7a2017-02-16 16:15:04 +1100162 size_t c1 = 0, c2 = 0;
Mark Anthony Palomer31310532016-06-05 18:48:25 -0700163 mp_map_elem_t *e1 = dict_iter_next(o, &c1), *e2 = dict_iter_next(rhs, &c2);
164 for (; e1 != NULL && e2 != NULL; e1 = dict_iter_next(o, &c1), e2 = dict_iter_next(rhs, &c2)) {
165 if (!mp_obj_equal(e1->key, e2->key) || !mp_obj_equal(e1->value, e2->value)) {
166 return mp_const_false;
167 }
168 }
169 return e1 == NULL && e2 == NULL ? mp_const_true : mp_const_false;
Damien Georgea1b18b32020-02-20 00:17:13 +1100170 }
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200171 #endif
Damien Georgea1b18b32020-02-20 00:17:13 +1100172
Damien Georgeeee1e882019-01-30 18:49:52 +1100173 if (mp_obj_is_type(rhs_in, &mp_type_dict)) {
Damien George999cedb2015-11-27 17:01:44 +0000174 mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in);
Paul Sokolovsky7cf057a2014-04-06 21:20:52 +0300175 if (o->map.used != rhs->map.used) {
176 return mp_const_false;
177 }
178
Damien George1ea2f7a2017-02-16 16:15:04 +1100179 size_t cur = 0;
Damien George8a9b9992014-09-17 15:53:03 +0100180 mp_map_elem_t *next = NULL;
181 while ((next = dict_iter_next(o, &cur)) != NULL) {
182 mp_map_elem_t *elem = mp_map_lookup(&rhs->map, next->key, MP_MAP_LOOKUP);
183 if (elem == NULL || !mp_obj_equal(next->value, elem->value)) {
184 return mp_const_false;
Paul Sokolovsky7cf057a2014-04-06 21:20:52 +0300185 }
186 }
187 return mp_const_true;
Damien Georgee22d76e2014-04-11 10:52:06 +0000188 } else {
189 // dict is not equal to instance of any other type
190 return mp_const_false;
Paul Sokolovsky7cf057a2014-04-06 21:20:52 +0300191 }
192 }
Rayane Chatrieuxf3e4c502022-04-11 17:35:56 -0400193 #if MICROPY_CPYTHON_COMPAT
194 case MP_BINARY_OP_INPLACE_OR:
195 case MP_BINARY_OP_OR: {
196 if (op == MP_BINARY_OP_OR) {
197 lhs_in = mp_obj_dict_copy(lhs_in);
198 }
199 mp_obj_t dicts[2] = {lhs_in, rhs_in};
200 dict_update(2, dicts, (mp_map_t *)&mp_const_empty_map);
201 return lhs_in;
202 }
203 #endif
Damiend99b0522013-12-21 18:17:45 +0000204 default:
205 // op not supported
Damien George6ac5dce2014-05-21 19:42:43 +0100206 return MP_OBJ_NULL;
Damiend99b0522013-12-21 18:17:45 +0000207 }
208}
209
Damien George814f17a2018-09-27 15:14:12 +1000210// Note: Make sure this is inlined in load part of dict_subscr() below.
Paul Sokolovsky75ce9252014-06-05 20:02:15 +0300211mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) {
Damien George999cedb2015-11-27 17:01:44 +0000212 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Paul Sokolovsky75ce9252014-06-05 20:02:15 +0300213 mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);
214 if (elem == NULL) {
Damien George38a204e2021-07-14 22:56:52 +1000215 mp_raise_type_arg(&mp_type_KeyError, index);
Paul Sokolovsky75ce9252014-06-05 20:02:15 +0300216 } else {
217 return elem->value;
218 }
219}
220
Angus Grattondecf8e62024-02-27 15:32:29 +1100221static mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
Damien Georgef4c9b332014-04-08 21:32:29 +0100222 if (value == MP_OBJ_NULL) {
Damien George729f7b42014-04-17 22:10:53 +0100223 // delete
Damien Georgef4c9b332014-04-08 21:32:29 +0100224 mp_obj_dict_delete(self_in, index);
Damien George729f7b42014-04-17 22:10:53 +0100225 return mp_const_none;
226 } else if (value == MP_OBJ_SENTINEL) {
227 // load
Damien George999cedb2015-11-27 17:01:44 +0000228 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Damien George729f7b42014-04-17 22:10:53 +0100229 mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);
230 if (elem == NULL) {
Damien George38a204e2021-07-14 22:56:52 +1000231 mp_raise_type_arg(&mp_type_KeyError, index);
Damien George729f7b42014-04-17 22:10:53 +0100232 } else {
233 return elem->value;
234 }
Damien Georgef4c9b332014-04-08 21:32:29 +0100235 } else {
Damien George729f7b42014-04-17 22:10:53 +0100236 // store
Damien Georgef4c9b332014-04-08 21:32:29 +0100237 mp_obj_dict_store(self_in, index, value);
Damien George729f7b42014-04-17 22:10:53 +0100238 return mp_const_none;
Damien Georgef4c9b332014-04-08 21:32:29 +0100239 }
Damien Georgef4c9b332014-04-08 21:32:29 +0100240}
John R. Lentona41fe312014-01-06 17:17:02 +0000241
242/******************************************************************************/
John R. Lentona41fe312014-01-06 17:17:02 +0000243/* dict methods */
244
Angus Grattondecf8e62024-02-27 15:32:29 +1100245static void mp_ensure_not_fixed(const mp_obj_dict_t *dict) {
Mike Wadstena3e01d32018-02-18 21:51:04 -0600246 if (dict->map.is_fixed) {
247 mp_raise_TypeError(NULL);
248 }
249}
250
Angus Grattondecf8e62024-02-27 15:32:29 +1100251static mp_obj_t dict_clear(mp_obj_t self_in) {
Damien George456a3ab2020-06-21 17:10:20 +1000252 mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
Damien George999cedb2015-11-27 17:01:44 +0000253 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Mike Wadstena3e01d32018-02-18 21:51:04 -0600254 mp_ensure_not_fixed(self);
John R. Lenton4ce6cea2014-01-06 17:38:47 +0000255
256 mp_map_clear(&self->map);
257
258 return mp_const_none;
259}
Angus Grattondecf8e62024-02-27 15:32:29 +1100260static MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);
John R. Lenton7d21d512014-01-06 17:54:04 +0000261
Andrew Leech28370c02020-06-10 10:45:24 +1000262mp_obj_t mp_obj_dict_copy(mp_obj_t self_in) {
Damien George456a3ab2020-06-21 17:10:20 +1000263 mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
Damien George999cedb2015-11-27 17:01:44 +0000264 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200265 mp_obj_t other_out = mp_obj_new_dict(self->map.alloc);
Damien George999cedb2015-11-27 17:01:44 +0000266 mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out);
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200267 other->base.type = self->base.type;
John R. Lentond90b19e2014-01-06 18:11:20 +0000268 other->map.used = self->map.used;
Paul Sokolovsky5fedd0c2014-04-06 21:00:58 +0300269 other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs;
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200270 other->map.is_fixed = 0;
271 other->map.is_ordered = self->map.is_ordered;
John R. Lentond90b19e2014-01-06 18:11:20 +0000272 memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t));
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200273 return other_out;
John R. Lentond90b19e2014-01-06 18:11:20 +0000274}
Angus Grattondecf8e62024-02-27 15:32:29 +1100275static MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, mp_obj_dict_copy);
John R. Lenton4ce6cea2014-01-06 17:38:47 +0000276
Paul Sokolovskyfbb83352018-08-06 01:25:41 +0300277#if MICROPY_PY_BUILTINS_DICT_FROMKEYS
Damien Georgeeae16442014-01-11 19:22:29 +0000278// this is a classmethod
Angus Grattondecf8e62024-02-27 15:32:29 +1100279static mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) {
Damien Georgee6003f42017-02-13 15:44:31 +1100280 mp_obj_t iter = mp_getiter(args[1], NULL);
Damien Georgeeae16442014-01-11 19:22:29 +0000281 mp_obj_t value = mp_const_none;
Damien George83229d32015-11-20 14:09:20 +0000282 mp_obj_t next = MP_OBJ_NULL;
Damien Georgeeae16442014-01-11 19:22:29 +0000283
284 if (n_args > 2) {
285 value = args[2];
286 }
287
Damien Georgea3edeb92016-10-17 11:58:57 +1100288 // optimisation to allocate result based on len of argument
289 mp_obj_t self_out;
290 mp_obj_t len = mp_obj_len_maybe(args[1]);
Damien Georgeeae16442014-01-11 19:22:29 +0000291 if (len == MP_OBJ_NULL) {
292 /* object's type doesn't have a __len__ slot */
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200293 self_out = mp_obj_new_dict(0);
Damien Georgeeae16442014-01-11 19:22:29 +0000294 } else {
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200295 self_out = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
Damien Georgeeae16442014-01-11 19:22:29 +0000296 }
297
Damien George999cedb2015-11-27 17:01:44 +0000298 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_out);
Damien Georgeea8d06c2014-04-17 23:19:36 +0100299 while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
Damien Georgeeae16442014-01-11 19:22:29 +0000300 mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
301 }
302
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200303 return self_out;
Damien Georgeeae16442014-01-11 19:22:29 +0000304}
Angus Grattondecf8e62024-02-27 15:32:29 +1100305static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_fun_obj, 2, 3, dict_fromkeys);
306static MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromkeys_fun_obj));
Paul Sokolovskyfbb83352018-08-06 01:25:41 +0300307#endif
Damien Georgeeae16442014-01-11 19:22:29 +0000308
Angus Grattondecf8e62024-02-27 15:32:29 +1100309static mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) {
Damien George456a3ab2020-06-21 17:10:20 +1000310 mp_check_self(mp_obj_is_dict_or_ordereddict(args[0]));
Damien George8b84b8a2017-07-04 23:24:59 +1000311 mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
Mike Wadstena3e01d32018-02-18 21:51:04 -0600312 if (lookup_kind != MP_MAP_LOOKUP) {
313 mp_ensure_not_fixed(self);
314 }
Damien George8b84b8a2017-07-04 23:24:59 +1000315 mp_map_elem_t *elem = mp_map_lookup(&self->map, args[1], lookup_kind);
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000316 mp_obj_t value;
Damien George8a9b9992014-09-17 15:53:03 +0100317 if (elem == NULL || elem->value == MP_OBJ_NULL) {
Damien George8b84b8a2017-07-04 23:24:59 +1000318 if (n_args == 2) {
Damien George38a2da62014-01-08 17:33:12 +0000319 if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
Damien George38a204e2021-07-14 22:56:52 +1000320 mp_raise_type_arg(&mp_type_KeyError, args[1]);
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000321 } else {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000322 value = mp_const_none;
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000323 }
324 } else {
Damien George8b84b8a2017-07-04 23:24:59 +1000325 value = args[2];
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000326 }
Damien George8a9b9992014-09-17 15:53:03 +0100327 if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
328 elem->value = value;
329 }
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000330 } else {
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000331 value = elem->value;
Damien George8a9b9992014-09-17 15:53:03 +0100332 if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
333 elem->value = MP_OBJ_NULL; // so that GC can collect the deleted value
334 }
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000335 }
336 return value;
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000337}
338
Angus Grattondecf8e62024-02-27 15:32:29 +1100339static mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) {
Damien George8b84b8a2017-07-04 23:24:59 +1000340 return dict_get_helper(n_args, args, MP_MAP_LOOKUP);
John R. Lentoncd088732014-01-06 18:53:16 +0000341}
Angus Grattondecf8e62024-02-27 15:32:29 +1100342static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get);
John R. Lentoncd088732014-01-06 18:53:16 +0000343
Angus Grattondecf8e62024-02-27 15:32:29 +1100344static mp_obj_t dict_pop(size_t n_args, const mp_obj_t *args) {
Damien George8b84b8a2017-07-04 23:24:59 +1000345 return dict_get_helper(n_args, args, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000346}
Angus Grattondecf8e62024-02-27 15:32:29 +1100347static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop);
John R. Lenton0fcbaa42014-01-06 19:48:34 +0000348
Angus Grattondecf8e62024-02-27 15:32:29 +1100349static mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) {
Damien George8b84b8a2017-07-04 23:24:59 +1000350 return dict_get_helper(n_args, args, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000351}
Angus Grattondecf8e62024-02-27 15:32:29 +1100352static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setdefault);
John R. Lentonbe8fe5b2014-01-06 20:25:51 +0000353
Angus Grattondecf8e62024-02-27 15:32:29 +1100354static mp_obj_t dict_popitem(mp_obj_t self_in) {
Damien George456a3ab2020-06-21 17:10:20 +1000355 mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
Damien George999cedb2015-11-27 17:01:44 +0000356 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Mike Wadstena3e01d32018-02-18 21:51:04 -0600357 mp_ensure_not_fixed(self);
Jim Mussared57fce3b2020-04-23 01:10:30 +1000358 if (self->map.used == 0) {
Jim Mussareddef76fe2020-03-02 22:35:22 +1100359 mp_raise_msg(&mp_type_KeyError, MP_ERROR_TEXT("popitem(): dictionary is empty"));
John R. Lentonf77dce82014-01-06 20:08:52 +0000360 }
Jim Mussared57fce3b2020-04-23 01:10:30 +1000361 size_t cur = 0;
362 #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
363 if (self->map.is_ordered) {
364 cur = self->map.used - 1;
365 }
366 #endif
367 mp_map_elem_t *next = dict_iter_next(self, &cur);
368 assert(next);
John R. Lentonf77dce82014-01-06 20:08:52 +0000369 self->map.used--;
370 mp_obj_t items[] = {next->key, next->value};
Damien George8a9b9992014-09-17 15:53:03 +0100371 next->key = MP_OBJ_SENTINEL; // must mark key as sentinel to indicate that it was deleted
372 next->value = MP_OBJ_NULL;
John R. Lentonf77dce82014-01-06 20:08:52 +0000373 mp_obj_t tuple = mp_obj_new_tuple(2, items);
374
375 return tuple;
376}
Angus Grattondecf8e62024-02-27 15:32:29 +1100377static MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);
John R. Lentonf77dce82014-01-06 20:08:52 +0000378
Angus Grattondecf8e62024-02-27 15:32:29 +1100379static mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
Damien George456a3ab2020-06-21 17:10:20 +1000380 mp_check_self(mp_obj_is_dict_or_ordereddict(args[0]));
Damien George999cedb2015-11-27 17:01:44 +0000381 mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
Mike Wadstena3e01d32018-02-18 21:51:04 -0600382 mp_ensure_not_fixed(self);
Damien Georgebcb6ca42014-06-03 12:53:44 +0100383
384 mp_arg_check_num(n_args, kwargs->used, 1, 2, true);
385
386 if (n_args == 2) {
387 // given a positional argument
388
Damien George456a3ab2020-06-21 17:10:20 +1000389 if (mp_obj_is_dict_or_ordereddict(args[1])) {
Damien Georgebcb6ca42014-06-03 12:53:44 +0100390 // update from other dictionary (make sure other is not self)
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200391 if (args[1] != args[0]) {
Damien George1ea2f7a2017-02-16 16:15:04 +1100392 size_t cur = 0;
Damien Georgebcb6ca42014-06-03 12:53:44 +0100393 mp_map_elem_t *elem = NULL;
Damien George69661f32020-02-27 15:36:53 +1100394 while ((elem = dict_iter_next((mp_obj_dict_t *)MP_OBJ_TO_PTR(args[1]), &cur)) != NULL) {
Damien Georgebcb6ca42014-06-03 12:53:44 +0100395 mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value;
396 }
397 }
John R. Lenton88f30432014-01-06 22:58:17 +0000398 } else {
Damien Georgebcb6ca42014-06-03 12:53:44 +0100399 // update from a generic iterable of pairs
Damien Georgee6003f42017-02-13 15:44:31 +1100400 mp_obj_t iter = mp_getiter(args[1], NULL);
Damien George83229d32015-11-20 14:09:20 +0000401 mp_obj_t next = MP_OBJ_NULL;
Damien Georgebcb6ca42014-06-03 12:53:44 +0100402 while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
Damien Georgee6003f42017-02-13 15:44:31 +1100403 mp_obj_t inneriter = mp_getiter(next, NULL);
Damien Georgebcb6ca42014-06-03 12:53:44 +0100404 mp_obj_t key = mp_iternext(inneriter);
405 mp_obj_t value = mp_iternext(inneriter);
406 mp_obj_t stop = mp_iternext(inneriter);
407 if (key == MP_OBJ_STOP_ITERATION
408 || value == MP_OBJ_STOP_ITERATION
409 || stop != MP_OBJ_STOP_ITERATION) {
Jim Mussareddef76fe2020-03-02 22:35:22 +1100410 mp_raise_ValueError(MP_ERROR_TEXT("dict update sequence has wrong length"));
Damien Georgebcb6ca42014-06-03 12:53:44 +0100411 } else {
412 mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
413 }
414 }
415 }
416 }
417
418 // update the dict with any keyword args
Damien George1ea2f7a2017-02-16 16:15:04 +1100419 for (size_t i = 0; i < kwargs->alloc; i++) {
Damien George054dd332019-01-30 21:57:29 +1100420 if (mp_map_slot_is_filled(kwargs, i)) {
Damien Georgebcb6ca42014-06-03 12:53:44 +0100421 mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value;
John R. Lenton88f30432014-01-06 22:58:17 +0000422 }
423 }
424
425 return mp_const_none;
426}
Angus Grattondecf8e62024-02-27 15:32:29 +1100427static MP_DEFINE_CONST_FUN_OBJ_KW(dict_update_obj, 1, dict_update);
John R. Lenton88f30432014-01-06 22:58:17 +0000428
John R. Lentonf77dce82014-01-06 20:08:52 +0000429
John R. Lentona41fe312014-01-06 17:17:02 +0000430/******************************************************************************/
John R. Lenton9ec3a872014-01-10 01:00:20 +0000431/* dict views */
432
Angus Grattondecf8e62024-02-27 15:32:29 +1100433static const mp_obj_type_t mp_type_dict_view;
434static const mp_obj_type_t mp_type_dict_view_it;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000435
436typedef enum _mp_dict_view_kind_t {
437 MP_DICT_VIEW_ITEMS,
438 MP_DICT_VIEW_KEYS,
439 MP_DICT_VIEW_VALUES,
440} mp_dict_view_kind_t;
441
Angus Grattondecf8e62024-02-27 15:32:29 +1100442static const char *const mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
John R. Lenton9ec3a872014-01-10 01:00:20 +0000443
444typedef struct _mp_obj_dict_view_it_t {
445 mp_obj_base_t base;
446 mp_dict_view_kind_t kind;
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200447 mp_obj_t dict;
Damien George1ea2f7a2017-02-16 16:15:04 +1100448 size_t cur;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000449} mp_obj_dict_view_it_t;
450
451typedef struct _mp_obj_dict_view_t {
452 mp_obj_base_t base;
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200453 mp_obj_t dict;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000454 mp_dict_view_kind_t kind;
455} mp_obj_dict_view_t;
456
Angus Grattondecf8e62024-02-27 15:32:29 +1100457static mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
Damien George9fef1c02021-03-26 13:48:34 +1100458 mp_check_self(mp_obj_is_type(self_in, &mp_type_dict_view_it));
Damien George999cedb2015-11-27 17:01:44 +0000459 mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in);
460 mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000461
Damien George8a9b9992014-09-17 15:53:03 +0100462 if (next == NULL) {
463 return MP_OBJ_STOP_ITERATION;
464 } else {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000465 switch (self->kind) {
Damien Georgeeae16442014-01-11 19:22:29 +0000466 case MP_DICT_VIEW_ITEMS:
Damien Georged2d64f02015-01-14 21:32:42 +0000467 default: {
Damien Georgeeae16442014-01-11 19:22:29 +0000468 mp_obj_t items[] = {next->key, next->value};
469 return mp_obj_new_tuple(2, items);
470 }
471 case MP_DICT_VIEW_KEYS:
472 return next->key;
473 case MP_DICT_VIEW_VALUES:
474 return next->value;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000475 }
John R. Lenton9ec3a872014-01-10 01:00:20 +0000476 }
477}
478
Angus Grattondecf8e62024-02-27 15:32:29 +1100479static MP_DEFINE_CONST_OBJ_TYPE(
Jim Mussared662b9762021-07-14 14:38:38 +1000480 mp_type_dict_view_it,
481 MP_QSTR_iterator,
Jim Mussared6da41b52022-09-16 23:57:38 +1000482 MP_TYPE_FLAG_ITER_IS_ITERNEXT,
Jim Mussared6da41b52022-09-16 23:57:38 +1000483 iter, dict_view_it_iternext
Jim Mussared662b9762021-07-14 14:38:38 +1000484 );
John R. Lenton9ec3a872014-01-10 01:00:20 +0000485
Angus Grattondecf8e62024-02-27 15:32:29 +1100486static mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) {
Damien Georgeae8d8672016-01-09 23:14:54 +0000487 assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t));
Damien George9fef1c02021-03-26 13:48:34 +1100488 mp_check_self(mp_obj_is_type(view_in, &mp_type_dict_view));
Damien George999cedb2015-11-27 17:01:44 +0000489 mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in);
Damien George69661f32020-02-27 15:36:53 +1100490 mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t *)iter_buf;
Damien George9fef1c02021-03-26 13:48:34 +1100491 o->base.type = &mp_type_dict_view_it;
John R. Lenton9ec3a872014-01-10 01:00:20 +0000492 o->kind = view->kind;
Damien George8a9b9992014-09-17 15:53:03 +0100493 o->dict = view->dict;
494 o->cur = 0;
Damien George999cedb2015-11-27 17:01:44 +0000495 return MP_OBJ_FROM_PTR(o);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000496}
497
Angus Grattondecf8e62024-02-27 15:32:29 +1100498static void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
Damien Georgeff8dd3f2015-01-20 12:47:20 +0000499 (void)kind;
Damien George9fef1c02021-03-26 13:48:34 +1100500 mp_check_self(mp_obj_is_type(self_in, &mp_type_dict_view));
Damien George999cedb2015-11-27 17:01:44 +0000501 mp_obj_dict_view_t *self = MP_OBJ_TO_PTR(self_in);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000502 bool first = true;
Damien George7f9d1d62015-04-09 23:56:15 +0100503 mp_print_str(print, mp_dict_view_names[self->kind]);
504 mp_print_str(print, "([");
Damien Georgeae8d8672016-01-09 23:14:54 +0000505 mp_obj_iter_buf_t iter_buf;
506 mp_obj_t self_iter = dict_view_getiter(self_in, &iter_buf);
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200507 mp_obj_t next = MP_OBJ_NULL;
Damien Georgeea8d06c2014-04-17 23:19:36 +0100508 while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000509 if (!first) {
Damien George7f9d1d62015-04-09 23:56:15 +0100510 mp_print_str(print, ", ");
John R. Lenton9ec3a872014-01-10 01:00:20 +0000511 }
512 first = false;
Damien George7f9d1d62015-04-09 23:56:15 +0100513 mp_obj_print_helper(print, next, PRINT_REPR);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000514 }
Damien George7f9d1d62015-04-09 23:56:15 +0100515 mp_print_str(print, "])");
John R. Lenton9ec3a872014-01-10 01:00:20 +0000516}
517
Angus Grattondecf8e62024-02-27 15:32:29 +1100518static mp_obj_t dict_view_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
David Lechner2fe6d4e2023-01-18 13:59:54 -0600519 mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(o_in);
520 // only dict.values() supports __hash__.
521 if (op == MP_UNARY_OP_HASH && o->kind == MP_DICT_VIEW_VALUES) {
522 return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in);
523 }
524 return MP_OBJ_NULL;
525}
526
Angus Grattondecf8e62024-02-27 15:32:29 +1100527static mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
Damien George6ac5dce2014-05-21 19:42:43 +0100528 // only supported for the 'keys' kind until sets and dicts are refactored
Damien George999cedb2015-11-27 17:01:44 +0000529 mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(lhs_in);
Damien Georged0a5bf32014-05-10 13:55:11 +0100530 if (o->kind != MP_DICT_VIEW_KEYS) {
Damien George6ac5dce2014-05-21 19:42:43 +0100531 return MP_OBJ_NULL; // op not supported
Damien Georged0a5bf32014-05-10 13:55:11 +0100532 }
Damien George5e34a112017-11-24 13:04:24 +1100533 if (op != MP_BINARY_OP_CONTAINS) {
Damien George6ac5dce2014-05-21 19:42:43 +0100534 return MP_OBJ_NULL; // op not supported
Damien Georged0a5bf32014-05-10 13:55:11 +0100535 }
John R. Lentonc1bef212014-01-11 12:39:33 +0000536 return dict_binary_op(op, o->dict, rhs_in);
537}
538
Angus Grattondecf8e62024-02-27 15:32:29 +1100539static MP_DEFINE_CONST_OBJ_TYPE(
Jim Mussared662b9762021-07-14 14:38:38 +1000540 mp_type_dict_view,
541 MP_QSTR_dict_view,
Jim Mussared6da41b52022-09-16 23:57:38 +1000542 MP_TYPE_FLAG_ITER_IS_GETITER,
Jim Mussared662b9762021-07-14 14:38:38 +1000543 print, dict_view_print,
David Lechner2fe6d4e2023-01-18 13:59:54 -0600544 unary_op, dict_view_unary_op,
Jim Mussared662b9762021-07-14 14:38:38 +1000545 binary_op, dict_view_binary_op,
Jim Mussared6da41b52022-09-16 23:57:38 +1000546 iter, dict_view_getiter
Jim Mussared662b9762021-07-14 14:38:38 +1000547 );
John R. Lenton9ec3a872014-01-10 01:00:20 +0000548
Angus Grattondecf8e62024-02-27 15:32:29 +1100549static mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) {
Jim Mussared0e7bfc82022-04-22 17:09:15 +1000550 mp_obj_dict_view_t *o = mp_obj_malloc(mp_obj_dict_view_t, &mp_type_dict_view);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000551 o->dict = dict;
552 o->kind = kind;
Damien George999cedb2015-11-27 17:01:44 +0000553 return MP_OBJ_FROM_PTR(o);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000554}
555
Angus Grattondecf8e62024-02-27 15:32:29 +1100556static mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
Damien George456a3ab2020-06-21 17:10:20 +1000557 mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200558 return mp_obj_new_dict_view(self_in, kind);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000559}
560
Angus Grattondecf8e62024-02-27 15:32:29 +1100561static mp_obj_t dict_items(mp_obj_t self_in) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000562 return dict_view(self_in, MP_DICT_VIEW_ITEMS);
563}
Angus Grattondecf8e62024-02-27 15:32:29 +1100564static MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000565
Angus Grattondecf8e62024-02-27 15:32:29 +1100566static mp_obj_t dict_keys(mp_obj_t self_in) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000567 return dict_view(self_in, MP_DICT_VIEW_KEYS);
568}
Angus Grattondecf8e62024-02-27 15:32:29 +1100569static MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000570
Angus Grattondecf8e62024-02-27 15:32:29 +1100571static mp_obj_t dict_values(mp_obj_t self_in) {
John R. Lenton9ec3a872014-01-10 01:00:20 +0000572 return dict_view(self_in, MP_DICT_VIEW_VALUES);
573}
Angus Grattondecf8e62024-02-27 15:32:29 +1100574static MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
John R. Lenton9ec3a872014-01-10 01:00:20 +0000575
John R. Lenton4bee76e2014-01-10 11:25:03 +0000576/******************************************************************************/
Damien George2161d6b2017-11-27 23:40:31 +1100577/* dict iterator */
578
Angus Grattondecf8e62024-02-27 15:32:29 +1100579static mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
Damien George2161d6b2017-11-27 23:40:31 +1100580 assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t));
Damien George456a3ab2020-06-21 17:10:20 +1000581 mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
Damien George69661f32020-02-27 15:36:53 +1100582 mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t *)iter_buf;
Damien George9fef1c02021-03-26 13:48:34 +1100583 o->base.type = &mp_type_dict_view_it;
Damien George2161d6b2017-11-27 23:40:31 +1100584 o->kind = MP_DICT_VIEW_KEYS;
585 o->dict = self_in;
586 o->cur = 0;
587 return MP_OBJ_FROM_PTR(o);
588}
589
590/******************************************************************************/
Damien Georgeeae16442014-01-11 19:22:29 +0000591/* dict constructors & public C API */
John R. Lentona41fe312014-01-06 17:17:02 +0000592
Angus Grattondecf8e62024-02-27 15:32:29 +1100593static const mp_rom_map_elem_t dict_locals_dict_table[] = {
Damien Georgecbf76742015-11-27 13:38:15 +0000594 { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&dict_clear_obj) },
595 { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&dict_copy_obj) },
Paul Sokolovskyfbb83352018-08-06 01:25:41 +0300596 #if MICROPY_PY_BUILTINS_DICT_FROMKEYS
Damien Georgecbf76742015-11-27 13:38:15 +0000597 { MP_ROM_QSTR(MP_QSTR_fromkeys), MP_ROM_PTR(&dict_fromkeys_obj) },
Paul Sokolovskyfbb83352018-08-06 01:25:41 +0300598 #endif
Damien Georgecbf76742015-11-27 13:38:15 +0000599 { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&dict_get_obj) },
600 { MP_ROM_QSTR(MP_QSTR_items), MP_ROM_PTR(&dict_items_obj) },
601 { MP_ROM_QSTR(MP_QSTR_keys), MP_ROM_PTR(&dict_keys_obj) },
602 { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&dict_pop_obj) },
603 { MP_ROM_QSTR(MP_QSTR_popitem), MP_ROM_PTR(&dict_popitem_obj) },
604 { MP_ROM_QSTR(MP_QSTR_setdefault), MP_ROM_PTR(&dict_setdefault_obj) },
605 { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&dict_update_obj) },
606 { MP_ROM_QSTR(MP_QSTR_values), MP_ROM_PTR(&dict_values_obj) },
607 { MP_ROM_QSTR(MP_QSTR___getitem__), MP_ROM_PTR(&mp_op_getitem_obj) },
608 { MP_ROM_QSTR(MP_QSTR___setitem__), MP_ROM_PTR(&mp_op_setitem_obj) },
609 { MP_ROM_QSTR(MP_QSTR___delitem__), MP_ROM_PTR(&mp_op_delitem_obj) },
John R. Lentonbaa66542014-01-07 23:18:25 +0000610};
611
Angus Grattondecf8e62024-02-27 15:32:29 +1100612static MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);
Damien George9b196cd2014-03-26 21:47:19 +0000613
Jim Mussared662b9762021-07-14 14:38:38 +1000614MP_DEFINE_CONST_OBJ_TYPE(
615 mp_type_dict,
616 MP_QSTR_dict,
Jim Mussared6da41b52022-09-16 23:57:38 +1000617 MP_TYPE_FLAG_ITER_IS_GETITER,
Jim Mussared94beeab2022-09-17 00:31:23 +1000618 make_new, mp_obj_dict_make_new,
Jim Mussared662b9762021-07-14 14:38:38 +1000619 print, dict_print,
620 unary_op, dict_unary_op,
621 binary_op, dict_binary_op,
622 subscr, dict_subscr,
Jim Mussared6da41b52022-09-16 23:57:38 +1000623 iter, dict_getiter,
Jim Mussared9dce8272022-06-24 16:27:46 +1000624 locals_dict, &dict_locals_dict
Jim Mussared662b9762021-07-14 14:38:38 +1000625 );
Damiend99b0522013-12-21 18:17:45 +0000626
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200627#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
Jim Mussared662b9762021-07-14 14:38:38 +1000628MP_DEFINE_CONST_OBJ_TYPE(
629 mp_type_ordereddict,
630 MP_QSTR_OrderedDict,
Jim Mussared6da41b52022-09-16 23:57:38 +1000631 MP_TYPE_FLAG_ITER_IS_GETITER,
Jim Mussared94beeab2022-09-17 00:31:23 +1000632 make_new, mp_obj_dict_make_new,
Jim Mussared662b9762021-07-14 14:38:38 +1000633 print, dict_print,
634 unary_op, dict_unary_op,
635 binary_op, dict_binary_op,
636 subscr, dict_subscr,
Jim Mussared6da41b52022-09-16 23:57:38 +1000637 iter, dict_getiter,
Jim Mussared662b9762021-07-14 14:38:38 +1000638 parent, &mp_type_dict,
Jim Mussared9dce8272022-06-24 16:27:46 +1000639 locals_dict, &dict_locals_dict
Jim Mussared662b9762021-07-14 14:38:38 +1000640 );
Paul Sokolovsky0ef01d02015-03-18 01:25:04 +0200641#endif
642
Damien George1ea2f7a2017-02-16 16:15:04 +1100643void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args) {
Damien George8b0535e2014-04-05 21:53:54 +0100644 dict->base.type = &mp_type_dict;
645 mp_map_init(&dict->map, n_args);
646}
647
Damien George1ea2f7a2017-02-16 16:15:04 +1100648mp_obj_t mp_obj_new_dict(size_t n_args) {
Damien George999cedb2015-11-27 17:01:44 +0000649 mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);
Damien George8b0535e2014-04-05 21:53:54 +0100650 mp_obj_dict_init(o, n_args);
Damien George999cedb2015-11-27 17:01:44 +0000651 return MP_OBJ_FROM_PTR(o);
Damiend99b0522013-12-21 18:17:45 +0000652}
Damiendae7eb72013-12-29 22:32:51 +0000653
Damien George1ea2f7a2017-02-16 16:15:04 +1100654size_t mp_obj_dict_len(mp_obj_t self_in) {
Damien George999cedb2015-11-27 17:01:44 +0000655 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Paul Sokolovsky0090c712015-03-26 12:28:31 +0200656 return self->map.used;
Damiendae7eb72013-12-29 22:32:51 +0000657}
658
659mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
Damien George456a3ab2020-06-21 17:10:20 +1000660 mp_check_self(mp_obj_is_dict_or_ordereddict(self_in));
Damien George999cedb2015-11-27 17:01:44 +0000661 mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
Mike Wadstena3e01d32018-02-18 21:51:04 -0600662 mp_ensure_not_fixed(self);
Damien George38a2da62014-01-08 17:33:12 +0000663 mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
Damiendae7eb72013-12-29 22:32:51 +0000664 return self_in;
665}
Damien George062478e2014-01-09 20:57:50 +0000666
Damien George66edc5d2014-04-05 13:25:13 +0100667mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) {
Damien George8b84b8a2017-07-04 23:24:59 +1000668 mp_obj_t args[2] = {self_in, key};
669 dict_get_helper(2, args, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
Damien George66edc5d2014-04-05 13:25:13 +0100670 return self_in;
671}