40
40
41
41
STATIC mp_obj_t mp_obj_new_dict_iterator (mp_obj_dict_t * dict , int cur );
42
42
STATIC mp_map_elem_t * dict_it_iternext_elem (mp_obj_t self_in );
43
- STATIC mp_obj_t dict_copy ( mp_obj_t self_in );
43
+ STATIC mp_obj_t dict_update ( uint n_args , const mp_obj_t * args , mp_map_t * kwargs );
44
44
45
45
STATIC void dict_print (void (* print )(void * env , const char * fmt , ...), void * env , mp_obj_t self_in , mp_print_kind_t kind ) {
46
46
mp_obj_dict_t * self = self_in ;
@@ -61,40 +61,13 @@ STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env
61
61
}
62
62
63
63
STATIC mp_obj_t dict_make_new (mp_obj_t type_in , uint n_args , uint n_kw , const mp_obj_t * args ) {
64
- mp_obj_t dict ;
65
- switch (n_args ) {
66
- case 0 :
67
- dict = mp_obj_new_dict (0 );
68
- break ;
69
-
70
- case 1 : {
71
- if (MP_OBJ_IS_TYPE (args [0 ], & mp_type_dict )) {
72
- return dict_copy (args [0 ]);
73
- }
74
- // TODO create dict from an arbitrary mapping!
75
-
76
- // Make dict from iterable of pairs
77
- mp_obj_t iterable = mp_getiter (args [0 ]);
78
- mp_obj_t dict = mp_obj_new_dict (0 );
79
- // TODO: support arbitrary seq as a pair
80
- mp_obj_t item ;
81
- while ((item = mp_iternext (iterable )) != MP_OBJ_STOP_ITERATION ) {
82
- mp_obj_t * sub_items ;
83
- mp_obj_get_array_fixed_n (item , 2 , & sub_items );
84
- mp_obj_dict_store (dict , sub_items [0 ], sub_items [1 ]);
85
- }
86
- return dict ;
87
- }
88
-
89
- default :
90
- nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_TypeError , "dict takes at most 1 argument" ));
91
- }
92
-
93
- // add to the new dict any keyword args
94
- for (const mp_obj_t * a = args + n_args ; n_kw > 0 ; n_kw -- , a += 2 ) {
95
- mp_obj_dict_store (dict , a [0 ], a [1 ]);
64
+ mp_obj_t dict = mp_obj_new_dict (0 );
65
+ if (n_args > 0 || n_kw > 0 ) {
66
+ mp_obj_t args2 [2 ] = {dict , args [0 ]}; // args[0] is always valid, even if it's not a positional arg
67
+ mp_map_t kwargs ;
68
+ mp_map_init_fixed_table (& kwargs , n_kw , args + n_args );
69
+ dict_update (n_args + 1 , args2 , & kwargs ); // dict_update will check that n_args + 1 == 1 or 2
96
70
}
97
-
98
71
return dict ;
99
72
}
100
73
@@ -348,31 +321,57 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
348
321
}
349
322
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (dict_popitem_obj , dict_popitem );
350
323
351
- STATIC mp_obj_t dict_update (mp_obj_t self_in , mp_obj_t iterable ) {
352
- assert (MP_OBJ_IS_TYPE (self_in , & mp_type_dict ));
353
- mp_obj_dict_t * self = self_in ;
354
- /* TODO: check for the "keys" method */
355
- mp_obj_t iter = mp_getiter (iterable );
356
- mp_obj_t next = NULL ;
357
- while ((next = mp_iternext (iter )) != MP_OBJ_STOP_ITERATION ) {
358
- mp_obj_t inneriter = mp_getiter (next );
359
- mp_obj_t key = mp_iternext (inneriter );
360
- mp_obj_t value = mp_iternext (inneriter );
361
- mp_obj_t stop = mp_iternext (inneriter );
362
- if (key == MP_OBJ_STOP_ITERATION
363
- || value == MP_OBJ_STOP_ITERATION
364
- || stop != MP_OBJ_STOP_ITERATION ) {
365
- nlr_raise (mp_obj_new_exception_msg (
366
- & mp_type_ValueError ,
367
- "dictionary update sequence has the wrong length" ));
324
+ STATIC mp_obj_t dict_update (uint n_args , const mp_obj_t * args , mp_map_t * kwargs ) {
325
+ assert (MP_OBJ_IS_TYPE (args [0 ], & mp_type_dict ));
326
+ mp_obj_dict_t * self = args [0 ];
327
+
328
+ mp_arg_check_num (n_args , kwargs -> used , 1 , 2 , true);
329
+
330
+ if (n_args == 2 ) {
331
+ // given a positional argument
332
+
333
+ if (MP_OBJ_IS_TYPE (args [1 ], & mp_type_dict )) {
334
+ // update from other dictionary (make sure other is not self)
335
+ if (args [1 ] != self ) {
336
+ // TODO don't allocate heap object for this iterator
337
+ mp_obj_t * dict_iter = mp_obj_new_dict_iterator (args [1 ], 0 );
338
+ mp_map_elem_t * elem = NULL ;
339
+ while ((elem = dict_it_iternext_elem (dict_iter )) != MP_OBJ_STOP_ITERATION ) {
340
+ mp_map_lookup (& self -> map , elem -> key , MP_MAP_LOOKUP_ADD_IF_NOT_FOUND )-> value = elem -> value ;
341
+ }
342
+ }
368
343
} else {
369
- mp_map_lookup (& self -> map , key , MP_MAP_LOOKUP_ADD_IF_NOT_FOUND )-> value = value ;
344
+ // update from a generic iterable of pairs
345
+ mp_obj_t iter = mp_getiter (args [1 ]);
346
+ mp_obj_t next = NULL ;
347
+ while ((next = mp_iternext (iter )) != MP_OBJ_STOP_ITERATION ) {
348
+ mp_obj_t inneriter = mp_getiter (next );
349
+ mp_obj_t key = mp_iternext (inneriter );
350
+ mp_obj_t value = mp_iternext (inneriter );
351
+ mp_obj_t stop = mp_iternext (inneriter );
352
+ if (key == MP_OBJ_STOP_ITERATION
353
+ || value == MP_OBJ_STOP_ITERATION
354
+ || stop != MP_OBJ_STOP_ITERATION ) {
355
+ nlr_raise (mp_obj_new_exception_msg (
356
+ & mp_type_ValueError ,
357
+ "dictionary update sequence has the wrong length" ));
358
+ } else {
359
+ mp_map_lookup (& self -> map , key , MP_MAP_LOOKUP_ADD_IF_NOT_FOUND )-> value = value ;
360
+ }
361
+ }
362
+ }
363
+ }
364
+
365
+ // update the dict with any keyword args
366
+ for (machine_uint_t i = 0 ; i < kwargs -> alloc ; i ++ ) {
367
+ if (MP_MAP_SLOT_IS_FILLED (kwargs , i )) {
368
+ mp_map_lookup (& self -> map , kwargs -> table [i ].key , MP_MAP_LOOKUP_ADD_IF_NOT_FOUND )-> value = kwargs -> table [i ].value ;
370
369
}
371
370
}
372
371
373
372
return mp_const_none ;
374
373
}
375
- STATIC MP_DEFINE_CONST_FUN_OBJ_2 (dict_update_obj , dict_update );
374
+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (dict_update_obj , 1 , dict_update );
376
375
377
376
378
377
/******************************************************************************/
0 commit comments