@@ -246,17 +246,150 @@ static mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) {
246246static MP_DEFINE_CONST_FUN_OBJ_2 (dict_update_obj , dict_update ) ;
247247
248248
249+ /******************************************************************************/
250+ /* dict views */
251+
252+ static const mp_obj_type_t dict_view_type ;
253+ static const mp_obj_type_t dict_view_it_type ;
254+
255+ typedef enum _mp_dict_view_kind_t {
256+ MP_DICT_VIEW_ITEMS ,
257+ MP_DICT_VIEW_KEYS ,
258+ MP_DICT_VIEW_VALUES ,
259+ } mp_dict_view_kind_t ;
260+
261+ static char * mp_dict_view_names [] = {"dict_items" , "dict_keys" , "dict_values" };
262+
263+ typedef struct _mp_obj_dict_view_it_t {
264+ mp_obj_base_t base ;
265+ mp_dict_view_kind_t kind ;
266+ mp_obj_dict_it_t * iter ;
267+ machine_uint_t cur ;
268+ } mp_obj_dict_view_it_t ;
269+
270+ typedef struct _mp_obj_dict_view_t {
271+ mp_obj_base_t base ;
272+ mp_obj_dict_t * dict ;
273+ mp_dict_view_kind_t kind ;
274+ } mp_obj_dict_view_t ;
275+
276+ static mp_obj_t dict_view_it_iternext (mp_obj_t self_in ) {
277+ assert (MP_OBJ_IS_TYPE (self_in , & dict_view_it_type ));
278+ mp_obj_dict_view_it_t * self = self_in ;
279+ mp_map_elem_t * next = dict_it_iternext_elem (self -> iter );
280+
281+ if (next != NULL ) {
282+ switch (self -> kind ) {
283+ case MP_DICT_VIEW_ITEMS :
284+ {
285+ mp_obj_t items [] = {next -> key , next -> value };
286+ return mp_obj_new_tuple (2 , items );
287+ }
288+ case MP_DICT_VIEW_KEYS :
289+ {
290+ return next -> key ;
291+ }
292+ case MP_DICT_VIEW_VALUES :
293+ {
294+ return next -> value ;
295+ }
296+ default :
297+ {
298+ assert (0 ); /* can't happen */
299+ }
300+ }
301+ } else {
302+ return mp_const_stop_iteration ;
303+ }
304+ }
305+
306+ static const mp_obj_type_t dict_view_it_type = {
307+ { & mp_const_type },
308+ "dict_view_iterator" ,
309+ .iternext = dict_view_it_iternext ,
310+ .methods = NULL , /* set operations still to come */
311+ };
312+
313+ static mp_obj_t dict_view_getiter (mp_obj_t view_in ) {
314+ assert (MP_OBJ_IS_TYPE (view_in , & dict_view_type ));
315+ mp_obj_dict_view_t * view = view_in ;
316+ mp_obj_dict_view_it_t * o = m_new_obj (mp_obj_dict_view_it_t );
317+ o -> base .type = & dict_view_it_type ;
318+ o -> kind = view -> kind ;
319+ o -> iter = mp_obj_new_dict_iterator (view -> dict , 0 );
320+ return o ;
321+ }
322+
323+
324+ static void dict_view_print (void (* print )(void * env , const char * fmt , ...), void * env , mp_obj_t self_in ) {
325+ assert (MP_OBJ_IS_TYPE (self_in , & dict_view_type ));
326+ mp_obj_dict_view_t * self = self_in ;
327+ bool first = true;
328+ print (env , mp_dict_view_names [self -> kind ]);
329+ print (env , "([" );
330+ mp_obj_t * self_iter = dict_view_getiter (self );
331+ mp_obj_t * next = NULL ;
332+ while ((next = dict_view_it_iternext (self_iter )) != mp_const_stop_iteration ) {
333+ if (!first ) {
334+ print (env , ", " );
335+ }
336+ first = false;
337+ mp_obj_print_helper (print , env , next );
338+ }
339+ print (env , "])" );
340+ }
341+
342+ static const mp_obj_type_t dict_view_type = {
343+ { & mp_const_type },
344+ "dict_view" ,
345+ .print = dict_view_print ,
346+ .getiter = dict_view_getiter ,
347+ };
348+
349+ mp_obj_t mp_obj_new_dict_view (mp_obj_dict_t * dict , mp_dict_view_kind_t kind ) {
350+ mp_obj_dict_view_t * o = m_new_obj (mp_obj_dict_view_t );
351+ o -> base .type = & dict_view_type ;
352+ o -> dict = dict ;
353+ o -> kind = kind ;
354+ return o ;
355+ }
356+
357+
358+ static mp_obj_t dict_view (mp_obj_t self_in , mp_dict_view_kind_t kind ) {
359+ assert (MP_OBJ_IS_TYPE (self_in , & dict_type ));
360+ mp_obj_dict_t * self = self_in ;
361+ return mp_obj_new_dict_view (self , kind );
362+ }
363+
364+ static mp_obj_t dict_items (mp_obj_t self_in ) {
365+ return dict_view (self_in , MP_DICT_VIEW_ITEMS );
366+ }
367+ static MP_DEFINE_CONST_FUN_OBJ_1 (dict_items_obj , dict_items ) ;
368+
369+ static mp_obj_t dict_keys (mp_obj_t self_in ) {
370+ return dict_view (self_in , MP_DICT_VIEW_KEYS );
371+ }
372+ static MP_DEFINE_CONST_FUN_OBJ_1 (dict_keys_obj , dict_keys ) ;
373+
374+ static mp_obj_t dict_values (mp_obj_t self_in ) {
375+ return dict_view (self_in , MP_DICT_VIEW_VALUES );
376+ }
377+ static MP_DEFINE_CONST_FUN_OBJ_1 (dict_values_obj , dict_values ) ;
378+
249379/******************************************************************************/
250380/* dict constructors & etc */
251381
252382static const mp_method_t dict_type_methods [] = {
253383 { "clear" , & dict_clear_obj },
254384 { "copy" , & dict_copy_obj },
255385 { "get" , & dict_get_obj },
386+ { "items" , & dict_items_obj },
387+ { "keys" , & dict_keys_obj },
256388 { "pop" , & dict_pop_obj },
257389 { "popitem" , & dict_popitem_obj },
258390 { "setdefault" , & dict_setdefault_obj },
259391 { "update" , & dict_update_obj },
392+ { "values" , & dict_values_obj },
260393 { NULL , NULL }, // end-of-list sentinel
261394};
262395
0 commit comments