4040#include "objstr.h"
4141#include "objlist.h"
4242
43- STATIC mp_obj_t str_modulo_format (mp_obj_t pattern , uint n_args , const mp_obj_t * args );
43+ STATIC mp_obj_t str_modulo_format (mp_obj_t pattern , uint n_args , const mp_obj_t * args , mp_obj_t dict );
4444const mp_obj_t mp_const_empty_bytes ;
4545
4646// use this macro to extract the string hash
@@ -307,14 +307,19 @@ STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
307307 case MP_BINARY_OP_MODULO : {
308308 mp_obj_t * args ;
309309 uint n_args ;
310+ mp_obj_t dict = MP_OBJ_NULL ;
310311 if (MP_OBJ_IS_TYPE (rhs_in , & mp_type_tuple )) {
311312 // TODO: Support tuple subclasses?
312313 mp_obj_tuple_get (rhs_in , & n_args , & args );
314+ } else if (MP_OBJ_IS_TYPE (rhs_in , & mp_type_dict )) {
315+ args = NULL ;
316+ n_args = 0 ;
317+ dict = rhs_in ;
313318 } else {
314319 args = & rhs_in ;
315320 n_args = 1 ;
316321 }
317- return str_modulo_format (lhs_in , n_args , args );
322+ return str_modulo_format (lhs_in , n_args , args , dict );
318323 }
319324
320325 //case MP_BINARY_OP_NOT_EQUAL: // This is never passed here
@@ -1125,7 +1130,7 @@ mp_obj_t mp_obj_str_format(uint n_args, const mp_obj_t *args) {
11251130 return s ;
11261131}
11271132
1128- STATIC mp_obj_t str_modulo_format (mp_obj_t pattern , uint n_args , const mp_obj_t * args ) {
1133+ STATIC mp_obj_t str_modulo_format (mp_obj_t pattern , uint n_args , const mp_obj_t * args , mp_obj_t dict ) {
11291134 assert (MP_OBJ_IS_STR (pattern ));
11301135
11311136 GET_STR_DATA_LEN (pattern , str , len );
@@ -1137,6 +1142,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
11371142 pfenv_vstr .print_strn = pfenv_vstr_add_strn ;
11381143
11391144 for (const byte * top = str + len ; str < top ; str ++ ) {
1145+ mp_obj_t arg = MP_OBJ_NULL ;
11401146 if (* str != '%' ) {
11411147 vstr_add_char (vstr , * str );
11421148 continue ;
@@ -1148,9 +1154,21 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
11481154 vstr_add_char (vstr , '%' );
11491155 continue ;
11501156 }
1151- if (arg_i >= n_args ) {
1152- nlr_raise (mp_obj_new_exception_msg (& mp_type_TypeError , "not enough arguments for format string" ));
1157+
1158+ // Dictionary value lookup
1159+ if (* str == '(' ) {
1160+ const byte * key = ++ str ;
1161+ while (* str != ')' ) {
1162+ if (str >= top ) {
1163+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , "incomplete format key" ));
1164+ }
1165+ ++ str ;
1166+ }
1167+ mp_obj_t k_obj = mp_obj_new_str ((const char * )key , str - key , true);
1168+ arg = mp_obj_dict_get (dict , k_obj );
1169+ str ++ ;
11531170 }
1171+
11541172 int flags = 0 ;
11551173 char fill = ' ' ;
11561174 bool alt = false;
@@ -1169,6 +1187,9 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
11691187 int width = 0 ;
11701188 if (str < top ) {
11711189 if (* str == '*' ) {
1190+ if (arg_i >= n_args ) {
1191+ goto not_enough_args ;
1192+ }
11721193 width = mp_obj_get_int (args [arg_i ++ ]);
11731194 str ++ ;
11741195 } else {
@@ -1181,6 +1202,9 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
11811202 if (str < top && * str == '.' ) {
11821203 if (++ str < top ) {
11831204 if (* str == '*' ) {
1205+ if (arg_i >= n_args ) {
1206+ goto not_enough_args ;
1207+ }
11841208 prec = mp_obj_get_int (args [arg_i ++ ]);
11851209 str ++ ;
11861210 } else {
@@ -1195,7 +1219,15 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
11951219 if (str >= top ) {
11961220 nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , "incomplete format" ));
11971221 }
1198- mp_obj_t arg = args [arg_i ];
1222+
1223+ // Tuple value lookup
1224+ if (arg == MP_OBJ_NULL ) {
1225+ if (arg_i >= n_args ) {
1226+ not_enough_args :
1227+ nlr_raise (mp_obj_new_exception_msg (& mp_type_TypeError , "not enough arguments for format string" ));
1228+ }
1229+ arg = args [arg_i ++ ];
1230+ }
11991231 switch (* str ) {
12001232 case 'c' :
12011233 if (MP_OBJ_IS_STR (arg )) {
@@ -1284,7 +1316,6 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
12841316 "unsupported format character '%c' (0x%x) at index %d" ,
12851317 * str , * str , str - start_str ));
12861318 }
1287- arg_i ++ ;
12881319 }
12891320
12901321 if (arg_i != n_args ) {
0 commit comments