blob: 7f87478a8986df5cfc6984de0672414eb97914b3 [file] [log] [blame]
Damiend99b0522013-12-21 18:17:45 +00001#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
Damien George6c73ca12014-01-08 18:11:23 +00004#include <stdarg.h>
Damiend99b0522013-12-21 18:17:45 +00005#include <assert.h>
6
7#include "nlr.h"
8#include "misc.h"
9#include "mpconfig.h"
Damien George20006db2014-01-18 14:10:48 +000010#include "mpqstr.h"
Damiend99b0522013-12-21 18:17:45 +000011#include "obj.h"
Paul Sokolovskyddf21782014-01-12 23:30:20 +020012#include "objtuple.h"
Damiend99b0522013-12-21 18:17:45 +000013
Paul Sokolovskyddf21782014-01-12 23:30:20 +020014// This is unified class for C-level and Python-level exceptions
15// Python-level exception have empty ->msg and all arguments are in
16// args tuple. C-level excepttion likely have ->msg, and may as well
17// have args tuple (or otherwise have it as NULL).
Damiend99b0522013-12-21 18:17:45 +000018typedef struct mp_obj_exception_t {
19 mp_obj_base_t base;
Damien George08335002014-01-18 23:24:36 +000020 qstr source_file;
21 machine_uint_t source_line;
Damiend99b0522013-12-21 18:17:45 +000022 qstr id;
Paul Sokolovskyddf21782014-01-12 23:30:20 +020023 qstr msg;
24 mp_obj_tuple_t args;
Damiend99b0522013-12-21 18:17:45 +000025} mp_obj_exception_t;
26
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020027void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
Damiend99b0522013-12-21 18:17:45 +000028 mp_obj_exception_t *o = o_in;
Paul Sokolovskyddf21782014-01-12 23:30:20 +020029 if (o->msg != 0) {
30 print(env, "%s: %s", qstr_str(o->id), qstr_str(o->msg));
31 } else {
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020032 // Yes, that's how CPython has it
33 if (kind == PRINT_REPR) {
34 print(env, "%s", qstr_str(o->id));
35 }
36 if (kind == PRINT_STR) {
37 if (o->args.len == 0) {
38 print(env, "");
39 return;
40 } else if (o->args.len == 1) {
41 mp_obj_print_helper(print, env, o->args.items[0], PRINT_STR);
42 return;
43 }
44 }
45 tuple_print(print, env, &o->args, kind);
Damiend99b0522013-12-21 18:17:45 +000046 }
47}
48
Damien George20006db2014-01-18 14:10:48 +000049static mp_obj_t exception_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
Paul Sokolovskyddf21782014-01-12 23:30:20 +020050 mp_obj_exception_t *base = self_in;
Damien George20006db2014-01-18 14:10:48 +000051
52 if (n_kw != 0) {
53 nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "%s does not take keyword arguments", qstr_str(base->id)));
54 }
55
56 mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, n_args);
Paul Sokolovskyddf21782014-01-12 23:30:20 +020057 o->base.type = &exception_type;
58 o->id = base->id;
59 o->msg = 0;
60 o->args.len = n_args;
Damien George20006db2014-01-18 14:10:48 +000061 memcpy(o->args.items, args, n_args * sizeof(mp_obj_t));
Paul Sokolovskyddf21782014-01-12 23:30:20 +020062 return o;
63}
64
Damiend99b0522013-12-21 18:17:45 +000065const mp_obj_type_t exception_type = {
66 { &mp_const_type },
67 "exception",
Damien George97209d32014-01-07 15:58:30 +000068 .print = exception_print,
Damien George20006db2014-01-18 14:10:48 +000069 .call = exception_call,
Damiend99b0522013-12-21 18:17:45 +000070};
71
72mp_obj_t mp_obj_new_exception(qstr id) {
Paul Sokolovskyddf21782014-01-12 23:30:20 +020073 return mp_obj_new_exception_msg_varg(id, NULL);
Damiend99b0522013-12-21 18:17:45 +000074}
75
76mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg) {
Paul Sokolovskyddf21782014-01-12 23:30:20 +020077 return mp_obj_new_exception_msg_varg(id, msg);
Damiend99b0522013-12-21 18:17:45 +000078}
79
80mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1) {
Paul Sokolovskyddf21782014-01-12 23:30:20 +020081 return mp_obj_new_exception_msg_varg(id, fmt, a1);
Damiend99b0522013-12-21 18:17:45 +000082}
83
84mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2) {
Paul Sokolovskyddf21782014-01-12 23:30:20 +020085 return mp_obj_new_exception_msg_varg(id, fmt, a1, a2);
Damiend99b0522013-12-21 18:17:45 +000086}
Damienb86e3f92013-12-29 17:17:43 +000087
Damien George6c73ca12014-01-08 18:11:23 +000088mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) {
Damien George6c73ca12014-01-08 18:11:23 +000089 // make exception object
Paul Sokolovskyddf21782014-01-12 23:30:20 +020090 mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0);
Damien George6c73ca12014-01-08 18:11:23 +000091 o->base.type = &exception_type;
Damien George08335002014-01-18 23:24:36 +000092 o->source_file = 0;
93 o->source_line = 0;
Damien George6c73ca12014-01-08 18:11:23 +000094 o->id = id;
Paul Sokolovskyddf21782014-01-12 23:30:20 +020095 o->args.len = 0;
96 if (fmt == NULL) {
97 o->msg = 0;
98 } else {
99 // render exception message
100 vstr_t *vstr = vstr_new();
101 va_list ap;
102 va_start(ap, fmt);
103 vstr_vprintf(vstr, fmt, ap);
104 va_end(ap);
105 o->msg = qstr_from_str_take(vstr->buf, vstr->alloc);
Damien George6c73ca12014-01-08 18:11:23 +0000106 }
Damien George6c73ca12014-01-08 18:11:23 +0000107
108 return o;
109}
110
Damienb86e3f92013-12-29 17:17:43 +0000111qstr mp_obj_exception_get_type(mp_obj_t self_in) {
112 assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
113 mp_obj_exception_t *self = self_in;
114 return self->id;
115}
Damien George08335002014-01-18 23:24:36 +0000116
117void mp_obj_exception_set_source_info(mp_obj_t self_in, qstr file, machine_uint_t line) {
118 assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
119 mp_obj_exception_t *self = self_in;
120 // TODO make a list of file/line pairs for the traceback
121 // for now, just keep the first one
122 if (file != 0 && self->source_file == 0) {
123 self->source_file = file;
124 }
125 if (line != 0 && self->source_line == 0) {
126 self->source_line = line;
127 }
128}
129
130void mp_obj_exception_get_source_info(mp_obj_t self_in, qstr *file, machine_uint_t *line) {
131 assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
132 mp_obj_exception_t *self = self_in;
133 *file = self->source_file;
134 *line = self->source_line;
135}