blob: 8343d7b279dc958fa0c25ab194aa63bb472e287d [file] [log] [blame]
Paul Sokolovskyd32bab22014-05-01 02:53:07 +03001/*
Damien George04b91472014-05-03 23:27:38 +01002 * This file is part of the Micro Python project, http://micropython.org/
Paul Sokolovskyd32bab22014-05-01 02:53:07 +03003 *
4 * The MIT License (MIT)
5 *
Damien George04b91472014-05-03 23:27:38 +01006 * Copyright (c) 2013, 2014 Damien P. George
Paul Sokolovskyd32bab22014-05-01 02:53:07 +03007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
Damien George04b91472014-05-03 23:27:38 +010026
Damien Georgea3f94e02014-04-20 00:13:22 +010027#include <stdlib.h>
28#include <assert.h>
29
Paul Sokolovskyf54bcbf2014-05-02 17:47:01 +030030#include "mpconfig.h"
Damien Georgea3f94e02014-04-20 00:13:22 +010031#include "nlr.h"
32#include "misc.h"
Damien Georgea3f94e02014-04-20 00:13:22 +010033#include "qstr.h"
34#include "obj.h"
35#include "runtime.h"
36
37void mp_arg_check_num(uint n_args, uint n_kw, uint n_args_min, uint n_args_max, bool takes_kw) {
38 // TODO maybe take the function name as an argument so we can print nicer error messages
39
40 if (n_kw && !takes_kw) {
41 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
42 }
43
44 if (n_args_min == n_args_max) {
45 if (n_args != n_args_min) {
46 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
47 "function takes %d positional arguments but %d were given",
48 n_args_min, n_args));
49 }
50 } else {
51 if (n_args < n_args_min) {
52 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
53 "function missing %d required positional arguments",
54 n_args_min - n_args));
55 } else if (n_args > n_args_max) {
56 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
57 "function expected at most %d arguments, got %d",
58 n_args_max, n_args));
59 }
60 }
61}
62
Damien Georgedbc81df2014-04-26 11:19:17 +010063void mp_arg_parse_all(uint n_pos, const mp_obj_t *pos, mp_map_t *kws, uint n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals) {
Damien Georgea3f94e02014-04-20 00:13:22 +010064 uint pos_found = 0, kws_found = 0;
65 for (uint i = 0; i < n_allowed; i++) {
66 mp_obj_t given_arg;
67 if (i < n_pos) {
Damien Georgedbc81df2014-04-26 11:19:17 +010068 if (allowed[i].flags & MP_ARG_KW_ONLY) {
Damien George64ba6ca2014-04-21 00:09:44 +010069 goto extra_positional;
Damien Georgea3f94e02014-04-20 00:13:22 +010070 }
71 pos_found++;
72 given_arg = pos[i];
73 } else {
74 mp_map_elem_t *kw = mp_map_lookup(kws, MP_OBJ_NEW_QSTR(allowed[i].qstr), MP_MAP_LOOKUP);
75 if (kw == NULL) {
Damien Georgedbc81df2014-04-26 11:19:17 +010076 if (allowed[i].flags & MP_ARG_REQUIRED) {
Damien Georgea3f94e02014-04-20 00:13:22 +010077 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' argument required", qstr_str(allowed[i].qstr)));
78 }
79 out_vals[i] = allowed[i].defval;
80 continue;
81 } else {
82 kws_found++;
83 given_arg = kw->value;
84 }
85 }
Damien Georgedbc81df2014-04-26 11:19:17 +010086 if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_BOOL) {
Damien Georgea3f94e02014-04-20 00:13:22 +010087 out_vals[i].u_bool = mp_obj_is_true(given_arg);
Damien Georgedbc81df2014-04-26 11:19:17 +010088 } else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_INT) {
Damien Georgea3f94e02014-04-20 00:13:22 +010089 out_vals[i].u_int = mp_obj_get_int(given_arg);
Damien Georgedbc81df2014-04-26 11:19:17 +010090 } else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_OBJ) {
Damien Georgea3f94e02014-04-20 00:13:22 +010091 out_vals[i].u_obj = given_arg;
92 } else {
93 assert(0);
94 }
95 }
96 if (pos_found < n_pos) {
97 // TODO better error message
Damien George64ba6ca2014-04-21 00:09:44 +010098 extra_positional:
Damien Georgea3f94e02014-04-20 00:13:22 +010099 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "extra positional arguments given"));
100 }
101 if (kws_found < kws->used) {
102 // TODO better error message
103 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "extra keyword arguments given"));
104 }
105}
Damien George491cbd62014-05-06 16:38:54 +0000106
107void mp_arg_parse_all_kw_array(uint n_pos, uint n_kw, const mp_obj_t *args, uint n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals) {
108 mp_map_t kw_args;
109 mp_map_init_fixed_table(&kw_args, n_kw, args + n_pos);
110 mp_arg_parse_all(n_pos, args, &kw_args, n_allowed, allowed, out_vals);
111}
Damien Georgec53b4082014-05-06 16:52:35 +0000112
Paul Sokolovsky47d3bd32014-05-06 19:25:25 +0300113#if MICROPY_CPYTHON_COMPAT
Damien Georgec53b4082014-05-06 16:52:35 +0000114NORETURN void mp_arg_error_unimpl_kw(void) {
Paul Sokolovsky47d3bd32014-05-06 19:25:25 +0300115 nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
116 "keyword argument(s) not yet implemented - use normal args instead"));
117}
118#endif