summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/obj.c16
-rw-r--r--py/obj.h5
-rw-r--r--py/objexcept.c38
-rw-r--r--py/vm.c2
-rw-r--r--stm/main.c6
-rw-r--r--unix/main.c10
6 files changed, 41 insertions, 36 deletions
diff --git a/py/obj.c b/py/obj.c
index c6e665376a..f90c67b0c6 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -58,6 +58,22 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
mp_obj_print_helper(printf_wrapper, NULL, o_in, kind);
}
+// helper function to print an exception with traceback
+void mp_obj_print_exception(mp_obj_t exc) {
+ if (MP_OBJ_IS_TYPE(exc, &exception_type)) {
+ machine_uint_t n, *values;
+ mp_obj_exception_get_traceback(exc, &n, &values);
+ if (n > 0) {
+ printf("Traceback (most recent call last):\n");
+ for (int i = n - 3; i >= 0; i -= 3) {
+ printf(" File \"%s\", line %d, in %s\n", qstr_str(values[i]), (int)values[i + 1], qstr_str(values[i + 2]));
+ }
+ }
+ }
+ mp_obj_print(exc, PRINT_REPR);
+ printf("\n");
+}
+
bool mp_obj_is_callable(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
return false;
diff --git a/py/obj.h b/py/obj.h
index 44d2858aee..07561b41c9 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -236,6 +236,7 @@ const char *mp_obj_get_type_str(mp_obj_t o_in);
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind);
void mp_obj_print(mp_obj_t o, mp_print_kind_t kind);
+void mp_obj_print_exception(mp_obj_t exc);
bool mp_obj_is_callable(mp_obj_t o_in);
machine_int_t mp_obj_hash(mp_obj_t o_in);
@@ -273,8 +274,8 @@ machine_int_t mp_obj_int_get_checked(mp_obj_t self_in);
// exception
extern const mp_obj_type_t exception_type;
qstr mp_obj_exception_get_type(mp_obj_t self_in);
-void mp_obj_exception_set_source_info(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block);
-void mp_obj_exception_get_source_info(mp_obj_t self_in, qstr *file, machine_uint_t *line, qstr *block);
+void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block);
+void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values);
// str
extern const mp_obj_type_t str_type;
diff --git a/py/objexcept.c b/py/objexcept.c
index 326d320d52..2e145ee358 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -17,9 +17,7 @@
// have args tuple (or otherwise have it as NULL).
typedef struct mp_obj_exception_t {
mp_obj_base_t base;
- qstr source_file;
- machine_uint_t source_line;
- qstr source_block;
+ mp_obj_t traceback; // a list object, holding (file,line,block) as numbers (not Python objects); a hack for now
qstr id;
qstr msg;
mp_obj_tuple_t args;
@@ -90,8 +88,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) {
// make exception object
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0);
o->base.type = &exception_type;
- o->source_file = 0;
- o->source_line = 0;
+ o->traceback = MP_OBJ_NULL;
o->id = id;
o->args.len = 0;
if (fmt == NULL) {
@@ -115,26 +112,27 @@ qstr mp_obj_exception_get_type(mp_obj_t self_in) {
return self->id;
}
-void mp_obj_exception_set_source_info(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block) {
+void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block) {
assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
mp_obj_exception_t *self = self_in;
- // TODO make a list of file/line pairs for the traceback
- // for now, just keep the first one
- if (file != 0 && self->source_file == 0) {
- self->source_file = file;
- }
- if (line != 0 && self->source_line == 0) {
- self->source_line = line;
- }
- if (block != 0 && self->source_block == 0) {
- self->source_block = block;
+ // for traceback, we are just using the list object for convenience, it's not really a list of Python objects
+ if (self->traceback == MP_OBJ_NULL) {
+ self->traceback = mp_obj_new_list(0, NULL);
}
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)file);
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)line);
+ mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)block);
}
-void mp_obj_exception_get_source_info(mp_obj_t self_in, qstr *file, machine_uint_t *line, qstr *block) {
+void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values) {
assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
mp_obj_exception_t *self = self_in;
- *file = self->source_file;
- *line = self->source_line;
- *block = self->source_block;
+ if (self->traceback == MP_OBJ_NULL) {
+ *n = 0;
+ *values = NULL;
+ } else {
+ uint n2;
+ mp_obj_list_get(self->traceback, &n2, (mp_obj_t**)values);
+ *n = n2;
+ }
}
diff --git a/py/vm.c b/py/vm.c
index 44cbd9f359..75c21d1b3c 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -544,7 +544,7 @@ bool mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_ob
break;
}
}
- mp_obj_exception_set_source_info(nlr.ret_val, source_file, source_line, block_name);
+ mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
}
while (currently_in_except_block) {
diff --git a/stm/main.c b/stm/main.c
index c49fa42ff9..4e1222e8fc 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -445,8 +445,7 @@ void do_repl(void) {
}
} else {
// uncaught exception
- mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
- printf("\n");
+ mp_obj_print_exception((mp_obj_t)nlr.ret_val);
}
}
}
@@ -490,8 +489,7 @@ bool do_file(const char *filename) {
return true;
} else {
// uncaught exception
- mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
- printf("\n");
+ mp_obj_print_exception((mp_obj_t)nlr.ret_val);
return false;
}
}
diff --git a/unix/main.c b/unix/main.c
index 35fca2059a..b39ed4f2c7 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -73,15 +73,7 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
nlr_pop();
} else {
// uncaught exception
- mp_obj_t exc = (mp_obj_t)nlr.ret_val;
- if (MP_OBJ_IS_TYPE(exc, &exception_type)) {
- qstr file, block;
- machine_uint_t line;
- mp_obj_exception_get_source_info(exc, &file, &line, &block);
- printf("File \"%s\", line %d, in %s\n", qstr_str(file), (int)line, qstr_str(block));
- }
- mp_obj_print(exc, PRINT_REPR);
- printf("\n");
+ mp_obj_print_exception((mp_obj_t)nlr.ret_val);
}
}