summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-03-31 01:10:10 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-03-31 02:23:56 +0300
commita96d3d0840357e6015119c427e7052fd73d9be3a (patch)
treebe6d651de8e64dbd5da5e2b16f0870b06fc248df
parente0f2979aed58499e791b01a77190d7f266cc88ea (diff)
downloadmicropython-a96d3d0840357e6015119c427e7052fd73d9be3a.tar.gz
micropython-a96d3d0840357e6015119c427e7052fd73d9be3a.zip
objexcept: No more magic messages in exceptions, only exception arguments.
One of the reason for separate "message" (besides still unfulfilled desire to optimize memory usage) was apparent special handling of exception with messages by CPython. Well, the message is still just an exception argument, it just printed specially. Implement that with PRINT_EXC printing format.
-rw-r--r--py/obj.c2
-rw-r--r--py/obj.h4
-rw-r--r--py/objexcept.c54
3 files changed, 28 insertions, 32 deletions
diff --git a/py/obj.c b/py/obj.c
index f80d1a9772..95052d16d2 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -62,7 +62,7 @@ void mp_obj_print_exception(mp_obj_t exc) {
}
}
}
- mp_obj_print(exc, PRINT_REPR);
+ mp_obj_print(exc, PRINT_EXC);
printf("\n");
}
diff --git a/py/obj.h b/py/obj.h
index a34d5407af..952187e464 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -141,7 +141,9 @@ typedef mp_obj_t (*mp_fun_var_t)(uint n, const mp_obj_t *);
typedef mp_obj_t (*mp_fun_kw_t)(uint n, const mp_obj_t *, mp_map_t *);
typedef enum {
- PRINT_STR, PRINT_REPR
+ PRINT_STR,
+ PRINT_REPR,
+ PRINT_EXC, // Special format for printing exception in unhandled exception message
} mp_print_kind_t;
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);
diff --git a/py/objexcept.c b/py/objexcept.c
index 7dd5c7ac39..0efc21d360 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -11,42 +11,34 @@
#include "runtime.h"
#include "runtime0.h"
-// This is unified class for C-level and Python-level exceptions
-// Python-level exceptions have empty ->msg and all arguments are in
-// args tuple. C-level exceptions likely have ->msg set, and args is empty.
typedef struct _mp_obj_exception_t {
mp_obj_base_t base;
mp_obj_t traceback; // a list object, holding (file,line,block) as numbers (not Python objects); a hack for now
- vstr_t *msg;
mp_obj_tuple_t args;
} mp_obj_exception_t;
// Instance of GeneratorExit exception - needed by generator.close()
// This would belong to objgenerator.c, but to keep mp_obj_exception_t
// definition module-private so far, have it here.
-const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, MP_OBJ_NULL, NULL, {{&mp_type_tuple}, 0}};
+const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, MP_OBJ_NULL, {{&mp_type_tuple}, 0}};
STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_exception_t *o = o_in;
- if (o->msg != NULL) {
- print(env, "%s: %s", qstr_str(o->base.type->name), vstr_str(o->msg));
- } else {
- // Yes, that's how CPython has it
- // TODO now that exceptions are classes and instances, I think this needs to be changed to match CPython
- if (kind == PRINT_REPR) {
- print(env, "%s", qstr_str(o->base.type->name));
- }
- if (kind == PRINT_STR) {
- if (o->args.len == 0) {
- print(env, "");
- return;
- } else if (o->args.len == 1) {
- mp_obj_print_helper(print, env, o->args.items[0], PRINT_STR);
- return;
- }
+ if (kind == PRINT_REPR) {
+ print(env, "%s", qstr_str(o->base.type->name));
+ } else if (kind == PRINT_EXC) {
+ print(env, "%s: ", qstr_str(o->base.type->name));
+ }
+ if (kind == PRINT_STR || kind == PRINT_EXC) {
+ if (o->args.len == 0) {
+ print(env, "");
+ return;
+ } else if (o->args.len == 1) {
+ mp_obj_print_helper(print, env, o->args.items[0], PRINT_STR);
+ return;
}
- tuple_print(print, env, &o->args, kind);
}
+ tuple_print(print, env, &o->args, kind);
}
STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
@@ -59,7 +51,6 @@ STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, n_args);
o->base.type = type;
o->traceback = MP_OBJ_NULL;
- o->msg = NULL;
o->args.base.type = &mp_type_tuple;
o->args.len = n_args;
memcpy(o->args.items, args, n_args * sizeof(mp_obj_t));
@@ -185,7 +176,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
*/
mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) {
- return mp_obj_new_exception_msg_varg(exc_type, NULL);
+ return mp_obj_new_exception_args(exc_type, 0, NULL);
}
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, uint n_args, const mp_obj_t *args) {
@@ -202,22 +193,25 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
assert(exc_type->make_new == mp_obj_exception_make_new);
// make exception object
- mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, 0);
+ mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, 1);
o->base.type = exc_type;
o->traceback = MP_OBJ_NULL;
o->args.base.type = &mp_type_tuple;
- o->args.len = 0;
+ o->args.len = 1;
if (fmt == NULL) {
// no message
- o->msg = NULL;
+ assert(0);
} else {
- // render exception message
- o->msg = vstr_new();
+ // render exception message and store as .args[0]
+ // TODO: optimize bufferbloat
+ vstr_t *vstr = vstr_new();
va_list ap;
va_start(ap, fmt);
- vstr_vprintf(o->msg, fmt, ap);
+ vstr_vprintf(vstr, fmt, ap);
va_end(ap);
+ o->args.items[0] = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
+ vstr_free(vstr);
}
return o;