diff options
author | Damien George <damien.p.george@gmail.com> | 2014-01-08 18:11:23 +0000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-01-08 18:11:23 +0000 |
commit | 6c73ca1e754aa5fb822999a0b46f01e216619ec6 (patch) | |
tree | 6fdd7b4205d2a4ef7056753ff067f78fb1197f41 /py | |
parent | 199b9e04eb186320f5d94bdc3b852f2443e466e0 (diff) | |
download | micropython-6c73ca1e754aa5fb822999a0b46f01e216619ec6.tar.gz micropython-6c73ca1e754aa5fb822999a0b46f01e216619ec6.zip |
py: add variable argument exception constructor function.
Addresses issue #104.
Diffstat (limited to 'py')
-rw-r--r-- | py/builtin.c | 12 | ||||
-rw-r--r-- | py/obj.c | 14 | ||||
-rw-r--r-- | py/obj.h | 1 | ||||
-rw-r--r-- | py/objbool.c | 2 | ||||
-rw-r--r-- | py/objexcept.c | 32 | ||||
-rw-r--r-- | py/runtime.c | 26 | ||||
-rw-r--r-- | py/stream.c | 4 |
7 files changed, 62 insertions, 29 deletions
diff --git a/py/builtin.c b/py/builtin.c index 0d18508aff..a5193bf760 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -154,7 +154,7 @@ mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2); return rt_build_tuple(2, revs_args); } else { - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in))); } } @@ -188,7 +188,7 @@ mp_obj_t mp_builtin_len(mp_obj_t o_in) { } else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) { len = mp_obj_dict_len(o_in); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); } return MP_OBJ_NEW_SMALL_INT(len); } @@ -263,7 +263,7 @@ mp_obj_t mp_builtin_ord(mp_obj_t o_in) { if (strlen(str) == 1) { return mp_obj_new_int(str[0]); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "ord() expected a character, but string of length %d found", strlen(str))); } } @@ -271,7 +271,7 @@ mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args) { switch (n_args) { case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]); case 3: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise... - default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "pow expected at most 3 arguments, got %d", n_args)); } } @@ -297,7 +297,7 @@ mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) { case 1: return mp_obj_new_range(0, mp_obj_get_int(args[0]), 1); case 2: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), 1); case 3: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2])); - default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "range expected at most 3 arguments, got %d", n_args)); } } @@ -306,7 +306,7 @@ mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { switch (n_args) { case 1: value = mp_obj_new_int(0); break; case 2: value = args[1]; break; - default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "sum expected at most 2 arguments, got %d", n_args)); } mp_obj_t iterable = rt_getiter(args[0]); mp_obj_t item; @@ -145,7 +145,7 @@ machine_int_t mp_obj_get_int(mp_obj_t arg) { return (machine_int_t)mp_obj_float_get(arg); #endif } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg))); } } @@ -160,7 +160,7 @@ machine_float_t mp_obj_get_float(mp_obj_t arg) { } else if (MP_OBJ_IS_TYPE(arg, &float_type)) { return mp_obj_float_get(arg); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); } } @@ -180,7 +180,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { } else if (MP_OBJ_IS_TYPE(arg, &complex_type)) { mp_obj_complex_get(arg, real, imag); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); } } #endif @@ -204,11 +204,11 @@ mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) { mp_obj_list_get(o_in, &seq_len, &seq_items); } if (seq_len != n) { - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_IndexError, "requested length %d but object has length %d", n, seq_len)); } return seq_items; } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in))); } } @@ -220,10 +220,10 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index) i += len; } if (i < 0 || i >= len) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_IndexError, "%s index out of range", type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_IndexError, "%s index out of range", type->name)); } return i; } else { - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index))); } } @@ -191,6 +191,7 @@ mp_obj_t mp_obj_new_exception(qstr id); mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg); mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1); mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2); +mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!) mp_obj_t mp_obj_new_range(int start, int stop, int step); mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step); mp_obj_t mp_obj_new_fun_bc(int n_args, uint n_state, const byte *code); diff --git a/py/objbool.c b/py/objbool.c index cfab7db068..da9a678063 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -27,7 +27,7 @@ static mp_obj_t bool_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args switch (n_args) { case 0: return mp_const_false; case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; } - default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "bool takes at most 1 argument, %d given", (void*)(machine_int_t)n_args)); + default: nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "bool takes at most 1 argument, %d given", n_args)); } } diff --git a/py/objexcept.c b/py/objexcept.c index 829b147853..4708a27bfc 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <stdarg.h> #include <assert.h> #include "nlr.h" @@ -79,6 +80,37 @@ mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a return o; } +mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) { + // count number of arguments by number of % signs, excluding %% + int n_args = 1; // count fmt + for (const char *s = fmt; *s; s++) { + if (*s == '%') { + if (s[1] == '%') { + s += 1; + } else { + n_args += 1; + } + } + } + + // make exception object + mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, n_args); + o->base.type = &exception_type; + o->id = id; + o->n_args = n_args; + o->args[0] = fmt; + + // extract args and store them + va_list ap; + va_start(ap, fmt); + for (int i = 1; i < n_args; i++) { + o->args[i] = va_arg(ap, void*); + } + va_end(ap); + + return o; +} + qstr mp_obj_exception_get_type(mp_obj_t self_in) { assert(MP_OBJ_IS_TYPE(self_in, &exception_type)); mp_obj_exception_t *self = self_in; diff --git a/py/runtime.c b/py/runtime.c index 84a902f2f4..387e10abbe 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -373,7 +373,7 @@ mp_obj_t rt_load_name(qstr qstr) { if (elem == NULL) { elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP); if (elem == NULL) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr))); } } } @@ -387,7 +387,7 @@ mp_obj_t rt_load_global(qstr qstr) { if (elem == NULL) { elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP); if (elem == NULL) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr))); } } return elem->value; @@ -447,7 +447,7 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) { } } // TODO specify in error message what the operator is - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "bad operand type for unary operator: '%s'", o->type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "bad operand type for unary operator: '%s'", o->type->name)); } } @@ -532,7 +532,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } // TODO specify in error message what the operator is - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs))); } mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs) { @@ -687,7 +687,7 @@ mp_obj_t rt_call_function_n(mp_obj_t fun_in, int n_args, const mp_obj_t *args) { if (fun->type->call_n != NULL) { return fun->type->call_n(fun_in, n_args, args); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not callable", fun->type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not callable", fun->type->name)); } } } @@ -705,7 +705,7 @@ mp_obj_t rt_call_function_n_kw(mp_obj_t fun_in, uint n_args, uint n_kw, const mp if (fun->type->call_n_kw != NULL) { return fun->type->call_n_kw(fun_in, n_args, n_kw, args); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not callable", fun->type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not callable", fun->type->name)); } } } @@ -754,14 +754,14 @@ void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) { mp_obj_list_get(seq_in, &seq_len, &seq_items); } if (seq_len < num) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len)); } else if (seq_len > num) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num)); } memcpy(items, seq_items, num * sizeof(mp_obj_t)); } else { // TODO call rt_getiter and extract via rt_iternext - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in))); } } @@ -807,7 +807,7 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) { } no_attr: - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { @@ -852,7 +852,7 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { mp_map_t *globals = mp_obj_module_get_globals(base); mp_map_lookup(globals, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } else { - nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } } @@ -877,7 +877,7 @@ mp_obj_t rt_getiter(mp_obj_t o_in) { if (o->type->getiter != NULL) { return o->type->getiter(o_in); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not iterable", o->type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not iterable", o->type->name)); } } } @@ -890,7 +890,7 @@ mp_obj_t rt_iternext(mp_obj_t o_in) { if (o->type->iternext != NULL) { return o->type->iternext(o_in); } else { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not an iterator", o->type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not an iterator", o->type->name)); } } } diff --git a/py/stream.c b/py/stream.c index 82a5aac10b..f883efcd25 100644 --- a/py/stream.c +++ b/py/stream.c @@ -23,7 +23,7 @@ static mp_obj_t stream_read(mp_obj_t self_in, mp_obj_t arg) { int error; machine_int_t out_sz = o->type->stream_p.read(self_in, buf, sz, &error); if (out_sz == -1) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_OSError, "[Errno %d]", (const char *)error)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error)); } else { buf[out_sz] = 0; return mp_obj_new_str(qstr_from_str_take(buf, /*out_sz,*/ sz + 1)); @@ -42,7 +42,7 @@ static mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) { int error; machine_int_t out_sz = o->type->stream_p.write(self_in, buf, sz, &error); if (out_sz == -1) { - nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_OSError, "[Errno %d]", (const char *)error)); + nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error)); } else { // http://docs.python.org/3/library/io.html#io.RawIOBase.write // "None is returned if the raw stream is set not to block and no single byte could be readily written to it." |