@@ -140,27 +140,30 @@ static mp_obj_t dict_copy(mp_obj_t self_in) {
140140}
141141static MP_DEFINE_CONST_FUN_OBJ_1 (dict_copy_obj , dict_copy ) ;
142142
143- static mp_obj_t dict_get_helper (mp_map_t * self , mp_obj_t key , mp_obj_t deflt , bool pop ) {
144- mp_map_elem_t * elem = mp_map_lookup_helper (self , key , false, pop );
145- if (elem == NULL ) {
143+ static mp_obj_t dict_get_helper (mp_map_t * self , mp_obj_t key , mp_obj_t deflt , bool pop , bool set ) {
144+ mp_map_elem_t * elem = mp_map_lookup_helper (self , key , set , pop );
145+ mp_obj_t value ;
146+ if (elem == NULL || elem -> value == NULL ) {
146147 if (deflt == NULL ) {
147148 if (pop ) {
148149 nlr_jump (mp_obj_new_exception_msg (MP_QSTR_KeyError , "<value>" ));
149150 } else {
150- return mp_const_none ;
151+ value = mp_const_none ;
151152 }
152153 } else {
153- return deflt ;
154+ value = deflt ;
154155 }
155156 } else {
156- mp_obj_t value = elem -> value ;
157+ value = elem -> value ;
157158 if (pop ) {
158159 /* catch the leak (from mp_map_lookup_helper) */
159160 m_free (elem , 2 * sizeof (mp_obj_t ));
160161 }
161- return value ;
162162 }
163-
163+ if (set ) {
164+ elem -> value = value ;
165+ }
166+ return value ;
164167}
165168
166169static mp_obj_t dict_get (int n_args , const mp_obj_t * args ) {
@@ -170,7 +173,7 @@ static mp_obj_t dict_get(int n_args, const mp_obj_t *args) {
170173 return dict_get_helper (& ((mp_obj_dict_t * )args [0 ])-> map ,
171174 args [1 ],
172175 n_args == 3 ? args [2 ] : NULL ,
173- false);
176+ false, false );
174177}
175178static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (dict_get_obj , 2 , 3 , dict_get ) ;
176179
@@ -181,11 +184,22 @@ static mp_obj_t dict_pop(int n_args, const mp_obj_t *args) {
181184 return dict_get_helper (& ((mp_obj_dict_t * )args [0 ])-> map ,
182185 args [1 ],
183186 n_args == 3 ? args [2 ] : NULL ,
184- true);
187+ true, false );
185188}
186189static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (dict_pop_obj , 2 , 3 , dict_pop ) ;
187190
188191
192+ static mp_obj_t dict_setdefault (int n_args , const mp_obj_t * args ) {
193+ assert (2 <= n_args && n_args <= 3 );
194+ assert (MP_OBJ_IS_TYPE (args [0 ], & dict_type ));
195+
196+ return dict_get_helper (& ((mp_obj_dict_t * )args [0 ])-> map ,
197+ args [1 ],
198+ n_args == 3 ? args [2 ] : NULL ,
199+ false, true);
200+ }
201+ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (dict_setdefault_obj , 2 , 3 , dict_setdefault ) ;
202+
189203
190204static mp_obj_t dict_popitem (mp_obj_t self_in ) {
191205 assert (MP_OBJ_IS_TYPE (self_in , & dict_type ));
@@ -199,6 +213,7 @@ static mp_obj_t dict_popitem(mp_obj_t self_in) {
199213 self -> map .used -- ;
200214 mp_obj_t items [] = {next -> key , next -> value };
201215 next -> key = NULL ;
216+ next -> value = NULL ;
202217 mp_obj_t tuple = mp_obj_new_tuple (2 , items );
203218
204219 return tuple ;
@@ -222,6 +237,7 @@ const mp_obj_type_t dict_type = {
222237 { "get" , & dict_get_obj },
223238 { "pop" , & dict_pop_obj },
224239 { "popitem" , & dict_popitem_obj },
240+ { "setdefault" , & dict_setdefault_obj },
225241 { NULL , NULL }, // end-of-list sentinel
226242 },
227243};
0 commit comments