diff options
-rw-r--r-- | py/builtin.c | 2 | ||||
-rw-r--r-- | py/obj.h | 2 | ||||
-rw-r--r-- | py/objfun.c | 43 | ||||
-rw-r--r-- | py/objlist.c | 2 |
4 files changed, 32 insertions, 17 deletions
diff --git a/py/builtin.c b/py/builtin.c index 2d61cd603f..53ae93ad95 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -314,4 +314,4 @@ static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) { return self; } -MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, mp_builtin_sorted); +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted); @@ -59,7 +59,7 @@ typedef struct _mp_obj_base_t mp_obj_base_t; #define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, 3, 3, (mp_fun_3_t)fun_name) #define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, (~((machine_uint_t)0)), (mp_fun_var_t)fun_name) #define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, n_args_max, (mp_fun_var_t)fun_name) -#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, 0, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_name) +#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, n_args_min, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_name) // These macros are used to declare and define constant staticmethond and classmethod objects // You can put "static" in front of the definitions to make them local diff --git a/py/objfun.c b/py/objfun.c index afac3889fd..eb24ea8763 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -17,21 +17,44 @@ // mp_obj_fun_native_t defined in obj.h +void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) { + if (n_kw && !self->is_kw) { + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, + "function does not take keyword arguments")); + } + + if (self->n_args_min == self->n_args_max) { + if (n_args != self->n_args_min) { + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, + "function takes %d positional arguments but %d were given", + (const char*)(machine_int_t)self->n_args_min, + (const char*)(machine_int_t)n_args)); + } + } else { + if (n_args < self->n_args_min) { + nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, + "<fun name>() missing %d required positional arguments: <list of names of params>", + (const char*)(machine_int_t)(self->n_args_min - n_args))); + } else if (n_args > self->n_args_max) { + nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, + "<fun name> expected at most %d arguments, got %d", + (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args)); + } + } +} + mp_obj_t fun_native_call_n_kw(mp_obj_t self_in, int n_args, int n_kw, const mp_obj_t *args); // args are in reverse order in the array mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { mp_obj_fun_native_t *self = self_in; + // check number of arguments + check_nargs(self, n_args, 0); if (self->is_kw) { return fun_native_call_n_kw(self_in, n_args, 0, args); } if (self->n_args_min == self->n_args_max) { // function requires a fixed number of arguments - // check number of arguments - if (n_args != self->n_args_min) { - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args_min, (const char*)(machine_int_t)n_args)); - } - // dispatch function call switch (self->n_args_min) { case 0: @@ -54,12 +77,6 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { } else { // function takes a variable number of arguments - if (n_args < self->n_args_min) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(self->n_args_min - n_args))); - } else if (n_args > self->n_args_max) { - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "<fun name> expected at most %d arguments, got %d", (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args)); - } - // TODO really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args mp_obj_t *args_ordered = m_new(mp_obj_t, n_args); for (int i = 0; i < n_args; i++) { @@ -76,9 +93,7 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { mp_obj_t fun_native_call_n_kw(mp_obj_t self_in, int n_args, int n_kw, const mp_obj_t *args) { mp_obj_fun_native_t *self = self_in; - if (!self->is_kw) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments")); - } + check_nargs(self, n_args, n_kw); mp_obj_t *vargs = mp_obj_new_tuple_reverse(n_args, args + 2*n_kw); mp_map_t *kw_args = mp_map_new(n_kw); diff --git a/py/objlist.c b/py/objlist.c index d5ea7f47b2..f806dfae8f 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -381,7 +381,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert); static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop); static MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, list_remove); static MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse); -static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, list_sort); +static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 0, list_sort); static const mp_method_t list_type_methods[] = { { "append", &list_append_obj }, |