diff options
Diffstat (limited to 'py/objfun.c')
-rw-r--r-- | py/objfun.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/py/objfun.c b/py/objfun.c index 51b4329c63..395824b046 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,10 +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", .call_n = fun_native_call_n, + .call_n_kw = fun_native_call_n_kw, }; mp_obj_t rt_make_function_0(mp_fun_0_t fun) { |