|
| 1 | +#include <stdlib.h> |
| 2 | +#include <assert.h> |
| 3 | + |
| 4 | +#include "nlr.h" |
| 5 | +#include "misc.h" |
| 6 | +#include "mpconfig.h" |
| 7 | +#include "qstr.h" |
| 8 | +#include "obj.h" |
| 9 | +#include "runtime.h" |
| 10 | + |
| 11 | +void mp_arg_check_num(uint n_args, uint n_kw, uint n_args_min, uint n_args_max, bool takes_kw) { |
| 12 | + // TODO maybe take the function name as an argument so we can print nicer error messages |
| 13 | + |
| 14 | + if (n_kw && !takes_kw) { |
| 15 | + nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); |
| 16 | + } |
| 17 | + |
| 18 | + if (n_args_min == n_args_max) { |
| 19 | + if (n_args != n_args_min) { |
| 20 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, |
| 21 | + "function takes %d positional arguments but %d were given", |
| 22 | + n_args_min, n_args)); |
| 23 | + } |
| 24 | + } else { |
| 25 | + if (n_args < n_args_min) { |
| 26 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, |
| 27 | + "function missing %d required positional arguments", |
| 28 | + n_args_min - n_args)); |
| 29 | + } else if (n_args > n_args_max) { |
| 30 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, |
| 31 | + "function expected at most %d arguments, got %d", |
| 32 | + n_args_max, n_args)); |
| 33 | + } |
| 34 | + } |
| 35 | +} |
| 36 | + |
| 37 | +void mp_arg_parse_all(uint n_pos, const mp_obj_t *pos, mp_map_t *kws, uint n_allowed, const mp_arg_parse_t *allowed, mp_arg_parse_val_t *out_vals) { |
| 38 | + uint pos_found = 0, kws_found = 0; |
| 39 | + for (uint i = 0; i < n_allowed; i++) { |
| 40 | + mp_obj_t given_arg; |
| 41 | + if (i < n_pos) { |
| 42 | + if (allowed[i].flags & MP_ARG_PARSE_KW_ONLY) { |
| 43 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' argument must be given by a keyword", qstr_str(allowed[i].qstr))); |
| 44 | + } |
| 45 | + pos_found++; |
| 46 | + given_arg = pos[i]; |
| 47 | + } else { |
| 48 | + mp_map_elem_t *kw = mp_map_lookup(kws, MP_OBJ_NEW_QSTR(allowed[i].qstr), MP_MAP_LOOKUP); |
| 49 | + if (kw == NULL) { |
| 50 | + if (allowed[i].flags & MP_ARG_PARSE_REQUIRED) { |
| 51 | + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' argument required", qstr_str(allowed[i].qstr))); |
| 52 | + } |
| 53 | + out_vals[i] = allowed[i].defval; |
| 54 | + continue; |
| 55 | + } else { |
| 56 | + kws_found++; |
| 57 | + given_arg = kw->value; |
| 58 | + } |
| 59 | + } |
| 60 | + if (allowed[i].flags == MP_ARG_PARSE_BOOL) { |
| 61 | + out_vals[i].u_bool = mp_obj_is_true(given_arg); |
| 62 | + } else if (allowed[i].flags == MP_ARG_PARSE_INT) { |
| 63 | + out_vals[i].u_int = mp_obj_get_int(given_arg); |
| 64 | + } else if (allowed[i].flags == MP_ARG_PARSE_OBJ) { |
| 65 | + out_vals[i].u_obj = given_arg; |
| 66 | + } else { |
| 67 | + assert(0); |
| 68 | + } |
| 69 | + } |
| 70 | + if (pos_found < n_pos) { |
| 71 | + // TODO better error message |
| 72 | + nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "extra positional arguments given")); |
| 73 | + } |
| 74 | + if (kws_found < kws->used) { |
| 75 | + // TODO better error message |
| 76 | + nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "extra keyword arguments given")); |
| 77 | + } |
| 78 | +} |
0 commit comments