diff options
author | John R. Lenton <jlenton@gmail.com> | 2014-01-07 17:29:16 +0000 |
---|---|---|
committer | John R. Lenton <jlenton@gmail.com> | 2014-01-07 17:29:16 +0000 |
commit | c06763a0207dde7f2060f7b1670a0b99298a01f8 (patch) | |
tree | 2f28c6e8824849f167a9b133c2d23c3c55c727d9 /py/objfun.c | |
parent | 880ce2d7fabc127b4bca7b6f2ea8b82d0977045f (diff) | |
download | micropython-c06763a0207dde7f2060f7b1670a0b99298a01f8.tar.gz micropython-c06763a0207dde7f2060f7b1670a0b99298a01f8.zip |
This implements a better (more python-conformant) list.sort.
It's not really about that, though; it's about me figuring out a sane
way forward for keyword-argument functions (and function
metadata). But it's useful as is, and shouldn't break any existing
code, so here you have it; I'm going to park it in my mind for a bit
while sorting out the rest of the dict branch.
Diffstat (limited to 'py/objfun.c')
-rw-r--r-- | py/objfun.c | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/py/objfun.c b/py/objfun.c index 0db6459a39..3697c64303 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -17,9 +17,13 @@ // mp_obj_fun_native_t defined in obj.h +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; + 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 @@ -69,16 +73,29 @@ 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")); + } + + mp_obj_t *vargs = mp_obj_new_tuple_reverse(n_args, args + 2*n_kw); + mp_map_t *kw_args = mp_map_new(MP_MAP_QSTR, n_kw); + for (int i = 0; i < 2*n_kw; i+=2) { + qstr name = mp_obj_str_get(args[i+1]); + mp_qstr_map_lookup(kw_args, name, true)->value = args[i]; + } + mp_obj_t res = ((mp_fun_kw_t)self->fun)(vargs, kw_args); + /* TODO clean up vargs and kw_args */ + return res; +} + const mp_obj_type_t fun_native_type = { - { &mp_const_type }, - "function", - NULL, // print - NULL, // make_new - fun_native_call_n, // call_n - NULL, // unary_op - NULL, // binary_op - NULL, // getiter - NULL, // iternext + .base = { &mp_const_type }, + .name = "function", + .call_n = fun_native_call_n, + .call_n_kw = fun_native_call_n_kw, .methods = { {NULL, NULL}, // end-of-list sentinel }, @@ -172,15 +189,9 @@ mp_obj_t fun_bc_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { } const mp_obj_type_t fun_bc_type = { - { &mp_const_type }, - "function", - NULL, // print - NULL, // make_new - fun_bc_call_n, // call_n - NULL, // unary_op - NULL, // binary_op - NULL, // getiter - NULL, // iternext + .base = { &mp_const_type }, + .name = "function", + .call_n = fun_bc_call_n, .methods = { {NULL, NULL}, // end-of-list sentinel }, @@ -286,15 +297,9 @@ mp_obj_t fun_asm_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { } static const mp_obj_type_t fun_asm_type = { - { &mp_const_type }, - "function", - NULL, // print - NULL, // make_new - fun_asm_call_n, // call_n - NULL, // unary_op - NULL, // binary_op - NULL, // getiter - NULL, // iternext + .base = { &mp_const_type }, + .name = "function", + .call_n = fun_asm_call_n, .methods = { {NULL, NULL}, // end-of-list sentinel }, |