Skip to content
Snippets Groups Projects
Commit 58f00d7c authored by Damien George's avatar Damien George
Browse files

py/modbuiltins: Use standard arg-parsing helper func for builtin print.

This allows the function to raise an exception when unknown keyword args
are passed in.  This patch also reduces code size by (in bytes):

   bare-arm:   -24
minimal x86:   -76
   unix x64:   -56
unix nanbox:   -84
      stm32:   -40
    esp8266:   -68
     cc3200:   -48

Furthermore, this patch adds space (" ") to the set of ROM qstrs which
means it doesn't need to be put in RAM if it's ever used.
parent e104e24e
No related branches found
No related tags found
No related merge requests found
...@@ -383,46 +383,52 @@ STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) { ...@@ -383,46 +383,52 @@ STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) {
} }
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow);
STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_map_elem_t *sep_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_MAP_LOOKUP); enum { ARG_sep, ARG_end, ARG_file };
mp_map_elem_t *end_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_MAP_LOOKUP); static const mp_arg_t allowed_args[] = {
const char *sep_data = " "; { MP_QSTR_sep, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__space_)} },
size_t sep_len = 1; { MP_QSTR_end, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__0x0a_)} },
const char *end_data = "\n";
size_t end_len = 1;
if (sep_elem != NULL && sep_elem->value != mp_const_none) {
sep_data = mp_obj_str_get_data(sep_elem->value, &sep_len);
}
if (end_elem != NULL && end_elem->value != mp_const_none) {
end_data = mp_obj_str_get_data(end_elem->value, &end_len);
}
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
void *stream_obj = &mp_sys_stdout_obj; { MP_QSTR_file, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_sys_stdout_obj)} },
mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP); #endif
if (file_elem != NULL && file_elem->value != mp_const_none) { };
stream_obj = MP_OBJ_TO_PTR(file_elem->value); // XXX may not be a concrete object
}
mp_print_t print = {stream_obj, mp_stream_write_adaptor}; // parse args (a union is used to reduce the amount of C stack that is needed)
union {
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
size_t len[2];
} u;
mp_arg_parse_all(0, NULL, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, u.args);
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
// TODO file may not be a concrete object (eg it could be a small-int)
mp_print_t print = {MP_OBJ_TO_PTR(u.args[ARG_file].u_obj), mp_stream_write_adaptor};
#endif #endif
// extract the objects first because we are going to use the other part of the union
mp_obj_t sep = u.args[ARG_sep].u_obj;
mp_obj_t end = u.args[ARG_end].u_obj;
const char *sep_data = mp_obj_str_get_data(sep, &u.len[0]);
const char *end_data = mp_obj_str_get_data(end, &u.len[1]);
for (size_t i = 0; i < n_args; i++) { for (size_t i = 0; i < n_args; i++) {
if (i > 0) { if (i > 0) {
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
mp_stream_write_adaptor(stream_obj, sep_data, sep_len); mp_stream_write_adaptor(print.data, sep_data, u.len[0]);
#else #else
mp_print_strn(&mp_plat_print, sep_data, sep_len, 0, 0, 0); mp_print_strn(&mp_plat_print, sep_data, u.len[0], 0, 0, 0);
#endif #endif
} }
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
mp_obj_print_helper(&print, args[i], PRINT_STR); mp_obj_print_helper(&print, pos_args[i], PRINT_STR);
#else #else
mp_obj_print_helper(&mp_plat_print, args[i], PRINT_STR); mp_obj_print_helper(&mp_plat_print, pos_args[i], PRINT_STR);
#endif #endif
} }
#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
mp_stream_write_adaptor(stream_obj, end_data, end_len); mp_stream_write_adaptor(print.data, end_data, u.len[1]);
#else #else
mp_print_strn(&mp_plat_print, end_data, end_len, 0, 0, 0); mp_print_strn(&mp_plat_print, end_data, u.len[1], 0, 0, 0);
#endif #endif
return mp_const_none; return mp_const_none;
} }
......
...@@ -40,6 +40,7 @@ Q(/) ...@@ -40,6 +40,7 @@ Q(/)
Q(%#o) Q(%#o)
Q(%#x) Q(%#x)
Q({:#b}) Q({:#b})
Q( )
Q(\n) Q(\n)
Q(maximum recursion depth exceeded) Q(maximum recursion depth exceeded)
Q(<module>) Q(<module>)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment