From 5c7683955994b965270598559e979c581ddc1950 Mon Sep 17 00:00:00 2001 From: "John R. Lenton" Date: Mon, 13 Jan 2014 05:12:50 +0000 Subject: sorted --- py/builtin.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'py/builtin.c') diff --git a/py/builtin.c b/py/builtin.c index 078f4b49c..f73d41b0d 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -296,3 +296,29 @@ mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { } return value; } + +extern mp_obj_t list_sort(mp_obj_t args, mp_map_t *kwargs); +static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) { + mp_obj_t *args_items = NULL; + uint args_len = 0; + + assert(MP_OBJ_IS_TYPE(args, &tuple_type)); + mp_obj_tuple_get(args, &args_len, &args_items); + assert(args_len >= 1); + if (args_len > 1) { + nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, + "must use keyword argument for key function")); + } + mp_obj_t iterable = rt_getiter(args_items[0]); + mp_obj_t self = rt_build_list(0, NULL); + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { + rt_list_append(self, item); + } + + mp_obj_t new_args = rt_build_tuple(1, &self); + list_sort(new_args, kwargs); + + return self; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, mp_builtin_sorted); -- cgit v1.2.3 From 2ded68db77d92f4f277ae688c22ac0be32dc4f31 Mon Sep 17 00:00:00 2001 From: "John R. Lenton" Date: Mon, 13 Jan 2014 19:52:28 +0000 Subject: Cleaned up sorted() as per Damien's suggestions. --- py/builtin.c | 9 +-------- py/obj.h | 1 + 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'py/builtin.c') diff --git a/py/builtin.c b/py/builtin.c index f73d41b0d..2d61cd603 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -297,7 +297,6 @@ mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { return value; } -extern mp_obj_t list_sort(mp_obj_t args, mp_map_t *kwargs); static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) { mp_obj_t *args_items = NULL; uint args_len = 0; @@ -309,13 +308,7 @@ static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) { nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "must use keyword argument for key function")); } - mp_obj_t iterable = rt_getiter(args_items[0]); - mp_obj_t self = rt_build_list(0, NULL); - mp_obj_t item; - while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { - rt_list_append(self, item); - } - + mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, args_items); mp_obj_t new_args = rt_build_tuple(1, &self); list_sort(new_args, kwargs); diff --git a/py/obj.h b/py/obj.h index 8a2cba62b..d1db0dde0 100644 --- a/py/obj.h +++ b/py/obj.h @@ -292,6 +292,7 @@ extern const mp_obj_type_t list_type; mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items); void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); +mp_obj_t list_sort(mp_obj_t args, struct _mp_map_t *kwargs); // dict extern const mp_obj_type_t dict_type; -- cgit v1.2.3 From 88cb1e60e0b780d71e9c2d7b0acafa71ba3ea318 Mon Sep 17 00:00:00 2001 From: "John R. Lenton" Date: Mon, 13 Jan 2014 19:55:18 +0000 Subject: Made sorted() raise an exception instead of aborting when given no arguments; moved around some things in objfun.c as a consequence --- py/builtin.c | 2 +- py/obj.h | 2 +- py/objfun.c | 43 +++++++++++++++++++++++++++++-------------- py/objlist.c | 2 +- 4 files changed, 32 insertions(+), 17 deletions(-) (limited to 'py/builtin.c') diff --git a/py/builtin.c b/py/builtin.c index 2d61cd603..53ae93ad9 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); diff --git a/py/obj.h b/py/obj.h index d1db0dde0..dbf9efe20 100644 --- a/py/obj.h +++ b/py/obj.h @@ -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 afac3889f..eb24ea876 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, + "() missing %d required positional arguments: ", + (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, + " 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, "() missing %d required positional arguments: ", (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, " 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 d5ea7f47b..f806dfae8 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 }, -- cgit v1.2.3