@@ -50,7 +50,7 @@ static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
5050 case RT_BINARY_OP_SUBSCR :
5151 {
5252 // dict load
53- mp_map_elem_t * elem = mp_map_lookup_helper (& o -> map , rhs_in , false);
53+ mp_map_elem_t * elem = mp_map_lookup_helper (& o -> map , rhs_in , false, false );
5454 if (elem == NULL ) {
5555 nlr_jump (mp_obj_new_exception_msg (MP_QSTR_KeyError , "<value>" ));
5656 } else {
@@ -140,20 +140,52 @@ 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 ) {
146+ if (deflt == NULL ) {
147+ if (pop ) {
148+ nlr_jump (mp_obj_new_exception_msg (MP_QSTR_KeyError , "<value>" ));
149+ } else {
150+ return mp_const_none ;
151+ }
152+ } else {
153+ return deflt ;
154+ }
155+ } else {
156+ mp_obj_t value = elem -> value ;
157+ if (pop ) {
158+ /* catch the leak (from mp_map_lookup_helper) */
159+ m_free (elem , 2 * sizeof (mp_obj_t ));
160+ }
161+ return value ;
162+ }
163+
164+ }
165+
143166static mp_obj_t dict_get (int n_args , const mp_obj_t * args ) {
144167 assert (2 <= n_args && n_args <= 3 );
145168 assert (MP_OBJ_IS_TYPE (args [0 ], & dict_type ));
146169
147- mp_map_elem_t * elem = mp_map_lookup_helper (& ((mp_obj_dict_t * )args [0 ])-> map ,
148- args [1 ], false);
149- if (elem == NULL ) {
150- return n_args >= 3 ? args [2 ] : mp_const_none ;
151- } else {
152- return elem -> value ;
153- }
170+ return dict_get_helper (& ((mp_obj_dict_t * )args [0 ])-> map ,
171+ args [1 ],
172+ n_args == 3 ? args [2 ] : NULL ,
173+ false);
154174}
155175static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (dict_get_obj , 2 , 3 , dict_get ) ;
156176
177+ static mp_obj_t dict_pop (int n_args , const mp_obj_t * args ) {
178+ assert (2 <= n_args && n_args <= 3 );
179+ assert (MP_OBJ_IS_TYPE (args [0 ], & dict_type ));
180+
181+ return dict_get_helper (& ((mp_obj_dict_t * )args [0 ])-> map ,
182+ args [1 ],
183+ n_args == 3 ? args [2 ] : NULL ,
184+ true);
185+ }
186+ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (dict_pop_obj , 2 , 3 , dict_pop ) ;
187+
188+
157189/******************************************************************************/
158190/* dict constructors & etc */
159191
@@ -168,6 +200,7 @@ const mp_obj_type_t dict_type = {
168200 { "clear" , & dict_clear_obj },
169201 { "copy" , & dict_copy_obj },
170202 { "get" , & dict_get_obj },
203+ { "pop" , & dict_pop_obj },
171204 { NULL , NULL }, // end-of-list sentinel
172205 },
173206};
@@ -186,6 +219,6 @@ uint mp_obj_dict_len(mp_obj_t self_in) {
186219mp_obj_t mp_obj_dict_store (mp_obj_t self_in , mp_obj_t key , mp_obj_t value ) {
187220 assert (MP_OBJ_IS_TYPE (self_in , & dict_type ));
188221 mp_obj_dict_t * self = self_in ;
189- mp_map_lookup_helper (& self -> map , key , true)-> value = value ;
222+ mp_map_lookup_helper (& self -> map , key , true, false )-> value = value ;
190223 return self_in ;
191224}
0 commit comments