diff --git a/py/builtin.c b/py/builtin.c index 91e54faed..ef9e70c94 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -36,7 +36,7 @@ STATIC mp_obj_t mp_builtin___build_class__(uint n_args, const mp_obj_t *args) { mp_obj_t meta; if (n_args == 2) { // no explicit bases, so use 'type' - meta = (mp_obj_t)&mp_const_type; + meta = (mp_obj_t)&mp_type_type; } else { // use type of first base object meta = mp_obj_get_type(args[2]); @@ -142,7 +142,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { byte str[1] = {ord}; return mp_obj_new_str(str, 1, true); } else { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "chr() arg not in range(0x110000)")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)")); } } @@ -187,7 +187,7 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2); return rt_build_tuple(2, args); } else { - 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))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in))); } } @@ -209,7 +209,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter); STATIC mp_obj_t mp_builtin_len(mp_obj_t o_in) { mp_obj_t len = mp_obj_len_maybe(o_in); if (len == NULL) { - 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))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); } else { return len; } @@ -229,7 +229,7 @@ STATIC mp_obj_t mp_builtin_max(uint n_args, const mp_obj_t *args) { } } if (max_obj == NULL) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "max() arg is an empty sequence")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "max() arg is an empty sequence")); } return max_obj; } else { @@ -258,7 +258,7 @@ STATIC mp_obj_t mp_builtin_min(uint n_args, const mp_obj_t *args) { } } if (min_obj == NULL) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "min() arg is an empty sequence")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "min() arg is an empty sequence")); } return min_obj; } else { @@ -278,7 +278,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_min_obj, 1, mp_builtin_min); STATIC mp_obj_t mp_builtin_next(mp_obj_t o) { mp_obj_t ret = rt_iternext(o); if (ret == mp_const_stop_iteration) { - nlr_jump(mp_obj_new_exception(MP_QSTR_StopIteration)); + nlr_jump(mp_obj_new_exception(&mp_type_StopIteration)); } else { return ret; } @@ -294,7 +294,7 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { // TODO unicode return mp_obj_new_int(((const byte*)str)[0]); } else { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "ord() expected a character, but string of length %d found", len)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", len)); } } @@ -364,7 +364,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum); STATIC mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) { assert(n_args >= 1); if (n_args > 1) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "must use keyword argument for key function")); } mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, 0, args); diff --git a/py/builtinevex.c b/py/builtinevex.c index 3e3c9a610..6e920e85f 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -13,6 +13,7 @@ #include "lexerunix.h" #include "parse.h" #include "obj.h" +#include "parsehelper.h" #include "compile.h" #include "runtime0.h" #include "runtime.h" @@ -28,14 +29,13 @@ STATIC mp_obj_t parse_compile_execute(mp_obj_t o_in, mp_parse_input_kind_t parse qstr source_name = mp_lexer_source_name(lex); // parse the string - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, parse_input_kind, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, parse_input_kind, &parse_error_kind); mp_lexer_free(lex); if (pn == MP_PARSE_NODE_NULL) { // parse error; raise exception - nlr_jump(mp_obj_new_exception_msg(parse_exc_id, parse_exc_msg)); + nlr_jump(mp_parse_make_exception(parse_error_kind)); } // compile the string @@ -74,6 +74,7 @@ STATIC mp_obj_t mp_builtin_exec(uint n_args, const mp_obj_t *args) { rt_locals_set(mp_obj_dict_get_map(locals)); } mp_obj_t res = parse_compile_execute(args[0], MP_PARSE_FILE_INPUT); + // TODO if the above call throws an exception, then we never get to reset the globals/locals rt_globals_set(old_globals); rt_locals_set(old_locals); return res; diff --git a/py/builtinimport.c b/py/builtinimport.c index 0e44676c3..c90625e9e 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -13,6 +13,7 @@ #include "lexerunix.h" #include "parse.h" #include "obj.h" +#include "parsehelper.h" #include "compile.h" #include "runtime0.h" #include "runtime.h" @@ -77,7 +78,7 @@ void do_load(mp_obj_t module_obj, vstr_t *file) { if (lex == NULL) { // we verified the file exists using stat, but lexer could still fail - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ImportError, "ImportError: No module named '%s'", vstr_str(file))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "ImportError: No module named '%s'", vstr_str(file))); } qstr source_name = mp_lexer_source_name(lex); @@ -91,16 +92,15 @@ void do_load(mp_obj_t module_obj, vstr_t *file) { rt_globals_set(mp_obj_module_get_globals(module_obj)); // parse the imported script - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); mp_lexer_free(lex); if (pn == MP_PARSE_NODE_NULL) { // parse error; clean up and raise exception rt_locals_set(old_locals); rt_globals_set(old_globals); - nlr_jump(mp_obj_new_exception_msg(parse_exc_id, parse_exc_msg)); + nlr_jump(mp_parse_make_exception(parse_error_kind)); } // compile the imported script @@ -172,7 +172,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { // fail if we couldn't find the file if (stat == MP_IMPORT_STAT_NO_EXIST) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ImportError, "ImportError: No module named '%s'", qstr_str(mod_name))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "ImportError: No module named '%s'", qstr_str(mod_name))); } module_obj = mp_obj_module_get(mod_name); diff --git a/py/lexer.c b/py/lexer.c index c3c992aee..be0b1883c 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -51,6 +51,7 @@ bool str_strn_equal(const char *str, const char *strn, int len) { return i == len && *str == 0; } +#ifdef MICROPY_DEBUG_PRINTERS void mp_token_show(const mp_token_t *tok) { printf("(%d:%d) kind:%d str:%p len:%d", tok->src_line, tok->src_column, tok->kind, tok->str, tok->len); if (tok->str != NULL && tok->len > 0) { @@ -69,6 +70,7 @@ void mp_token_show(const mp_token_t *tok) { } printf("\n"); } +#endif #define CUR_CHAR(lex) ((lex)->chr0) @@ -711,35 +713,3 @@ const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex) { bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind) { return lex->tok_cur.kind == kind; } - -/* -bool mp_lexer_is_str(mp_lexer_t *lex, const char *str) { - return mp_token_is_str(&lex->tok_cur, str); -} - -bool mp_lexer_opt_kind(mp_lexer_t *lex, mp_token_kind_t kind) { - if (mp_lexer_is_kind(lex, kind)) { - mp_lexer_to_next(lex); - return true; - } - return false; -} - -bool mp_lexer_opt_str(mp_lexer_t *lex, const char *str) { - if (mp_lexer_is_str(lex, str)) { - mp_lexer_to_next(lex); - return true; - } - return false; -} -*/ - -bool mp_lexer_show_error_pythonic_prefix(mp_lexer_t *lex) { - printf(" File \"%s\", line %d column %d\n", qstr_str(lex->source_name), lex->tok_cur.src_line, lex->tok_cur.src_column); - return false; -} - -bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg) { - printf(" File \"%s\", line %d column %d\n%s\n", qstr_str(lex->source_name), lex->tok_cur.src_line, lex->tok_cur.src_column, msg); - return false; -} diff --git a/py/mpconfig.h b/py/mpconfig.h index 6ff069291..00e2439e4 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -40,6 +40,7 @@ #endif // Whether to build functions that print debugging info: +// mp_token_show // mp_byte_code_print // mp_parse_node_print #ifndef MICROPY_DEBUG_PRINTERS diff --git a/py/obj.c b/py/obj.c index 86c0edc15..0068af4c4 100644 --- a/py/obj.c +++ b/py/obj.c @@ -51,7 +51,7 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t 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)) { + if (mp_obj_is_exception_instance(exc)) { machine_uint_t n, *values; mp_obj_exception_get_traceback(exc, &n, &values); if (n > 0) { @@ -133,7 +133,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { } } - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_NotImplementedError, + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_NotImplementedError, "Equality for '%s' and '%s' types not yet implemented", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2))); return false; } @@ -160,7 +160,7 @@ machine_int_t mp_obj_get_int(mp_obj_t arg) { } else if (MP_OBJ_IS_TYPE(arg, &int_type)) { return mp_obj_int_get_checked(arg); } else { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg))); } } @@ -175,7 +175,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_varg(MP_QSTR_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); } } @@ -195,7 +195,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_varg(MP_QSTR_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); } } #endif @@ -210,11 +210,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_varg(MP_QSTR_IndexError, "requested length %d but object has length %d", n, seq_len)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "requested length %d but object has length %d", n, seq_len)); } return seq_items; } else { - 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))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in))); } } @@ -226,11 +226,11 @@ 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_varg(MP_QSTR_IndexError, "%s index out of range", qstr_str(type->name))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "%s index out of range", qstr_str(type->name))); } return i; } else { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "%s indices must be integers, not %s", qstr_str(type->name), mp_obj_get_type_str(index))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%s indices must be integers, not %s", qstr_str(type->name), mp_obj_get_type_str(index))); } } diff --git a/py/obj.h b/py/obj.h index bed119c0a..dd6d217e4 100644 --- a/py/obj.h +++ b/py/obj.h @@ -188,9 +188,27 @@ struct _mp_obj_type_t { typedef struct _mp_obj_type_t mp_obj_type_t; +// Constant types, globally accessible + +extern const mp_obj_type_t mp_type_type; +extern const mp_obj_type_t mp_type_BaseException; +extern const mp_obj_type_t mp_type_AssertionError; +extern const mp_obj_type_t mp_type_AttributeError; +extern const mp_obj_type_t mp_type_ImportError; +extern const mp_obj_type_t mp_type_IndentationError; +extern const mp_obj_type_t mp_type_IndexError; +extern const mp_obj_type_t mp_type_KeyError; +extern const mp_obj_type_t mp_type_NameError; +extern const mp_obj_type_t mp_type_SyntaxError; +extern const mp_obj_type_t mp_type_TypeError; +extern const mp_obj_type_t mp_type_ValueError; +extern const mp_obj_type_t mp_type_OverflowError; +extern const mp_obj_type_t mp_type_OSError; +extern const mp_obj_type_t mp_type_NotImplementedError; +extern const mp_obj_type_t mp_type_StopIteration; + // Constant objects, globally accessible -extern const mp_obj_type_t mp_const_type; extern const mp_obj_t mp_const_none; extern const mp_obj_t mp_const_false; extern const mp_obj_t mp_const_true; @@ -213,9 +231,9 @@ mp_obj_t mp_obj_new_bytes(const byte* data, uint len); mp_obj_t mp_obj_new_float(mp_float_t val); mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag); #endif -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_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_exception(const mp_obj_type_t *exc_type); +mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg); +mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, 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, mp_obj_t def_args, uint n_state, const byte *code); @@ -235,6 +253,7 @@ mp_obj_t mp_obj_new_module(qstr module_name); mp_obj_type_t *mp_obj_get_type(mp_obj_t o_in); const char *mp_obj_get_type_str(mp_obj_t o_in); +bool mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo); 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); @@ -274,8 +293,9 @@ machine_int_t mp_obj_int_get(mp_obj_t self_in); 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); +bool mp_obj_is_exception_type(mp_obj_t self_in); +bool mp_obj_is_exception_instance(mp_obj_t self_in); +void mp_obj_exception_clear_traceback(mp_obj_t self_in); 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); diff --git a/py/objarray.c b/py/objarray.c index 4a70f9f7f..9e36196e5 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -82,7 +82,7 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { STATIC mp_obj_t array_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { if (n_args < 1 || n_args > 2) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "unexpected # of arguments, %d given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unexpected # of arguments, %d given", n_args)); } // TODO check args uint l; @@ -160,7 +160,7 @@ STATIC const mp_method_t array_type_methods[] = { }; const mp_obj_type_t array_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_array, .print = array_print, .make_new = array_make_new, @@ -222,7 +222,7 @@ mp_obj_t array_it_iternext(mp_obj_t self_in) { } STATIC const mp_obj_type_t array_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = array_it_iternext, }; diff --git a/py/objbool.c b/py/objbool.c index 2dd019b72..1dc5e5760 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -29,7 +29,7 @@ STATIC mp_obj_t bool_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp 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_varg(MP_QSTR_TypeError, "bool takes at most 1 argument, %d given", n_args)); + default: nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bool takes at most 1 argument, %d given", n_args)); } } @@ -46,7 +46,7 @@ STATIC mp_obj_t bool_unary_op(int op, mp_obj_t o_in) { } const mp_obj_type_t bool_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_bool, .print = bool_print, .make_new = bool_make_new, diff --git a/py/objboundmeth.c b/py/objboundmeth.c index 72fbc233f..0b5fc10a0 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -40,7 +40,7 @@ mp_obj_t bound_meth_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_ } const mp_obj_type_t bound_meth_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_bound_method, .call = bound_meth_call, }; diff --git a/py/objcell.c b/py/objcell.c index ce8f36014..366661747 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -25,7 +25,7 @@ void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) { } const mp_obj_type_t cell_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_, // should never need to print cell type }; diff --git a/py/objclosure.c b/py/objclosure.c index 39e38c9d2..e2de0e045 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -41,7 +41,7 @@ mp_obj_t closure_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t * } const mp_obj_type_t closure_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_closure, .call = closure_call, }; diff --git a/py/objcomplex.c b/py/objcomplex.c index 3b5de03ed..188c33413 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -66,7 +66,7 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const } default: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "complex takes at most 2 arguments, %d given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "complex takes at most 2 arguments, %d given", n_args)); } } @@ -86,7 +86,7 @@ STATIC mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { } const mp_obj_type_t complex_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_complex, .print = complex_print, .make_new = complex_make_new, diff --git a/py/objdict.c b/py/objdict.c index 15e738dff..31a80bd6c 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -60,7 +60,7 @@ STATIC mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // dict load mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP); if (elem == NULL) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "")); } else { return elem->value; } @@ -112,7 +112,7 @@ mp_obj_t dict_it_iternext(mp_obj_t self_in) { } STATIC const mp_obj_type_t dict_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = dict_it_iternext, }; @@ -187,7 +187,7 @@ STATIC mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp if (elem == NULL || elem->value == NULL) { if (deflt == NULL) { if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "")); } else { value = mp_const_none; } @@ -246,7 +246,7 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { assert(MP_OBJ_IS_TYPE(self_in, &dict_type)); mp_obj_dict_t *self = self_in; if (self->map.used == 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "popitem(): dictionary is empty")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "popitem(): dictionary is empty")); } mp_obj_dict_it_t *iter = mp_obj_new_dict_iterator(self, 0); @@ -276,7 +276,7 @@ STATIC mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) { || value == mp_const_stop_iteration || stop != mp_const_stop_iteration) { nlr_jump(mp_obj_new_exception_msg( - MP_QSTR_ValueError, + &mp_type_ValueError, "dictionary update sequence has the wrong length")); } else { mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; @@ -341,7 +341,7 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { } STATIC const mp_obj_type_t dict_view_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = dict_view_it_iternext, .methods = NULL, /* set operations still to come */ @@ -385,7 +385,7 @@ STATIC mp_obj_t dict_view_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { STATIC const mp_obj_type_t dict_view_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_dict_view, .print = dict_view_print, .binary_op = dict_view_binary_op, @@ -440,7 +440,7 @@ STATIC const mp_method_t dict_type_methods[] = { }; const mp_obj_type_t dict_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_dict, .print = dict_print, .make_new = dict_make_new, diff --git a/py/objenumerate.c b/py/objenumerate.c index 2ca4dcd77..1c858ff56 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -27,7 +27,7 @@ STATIC mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, con } const mp_obj_type_t enumerate_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_enumerate, .make_new = enumerate_make_new, .iternext = enumerate_iternext, diff --git a/py/objexcept.c b/py/objexcept.c index e2c154de9..d5c056a8d 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -17,19 +17,18 @@ 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 - qstr id; vstr_t *msg; mp_obj_tuple_t args; } mp_obj_exception_t; -STATIC void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { +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->id), vstr_str(o->msg)); + print(env, "%s: %s", qstr_str(o->base.type->name), vstr_str(o->msg)); } else { // Yes, that's how CPython has it if (kind == PRINT_REPR) { - print(env, "%s", qstr_str(o->id)); + print(env, "%s", qstr_str(o->base.type->name)); } if (kind == PRINT_STR) { if (o->args.len == 0) { @@ -44,46 +43,74 @@ STATIC void exception_print(void (*print)(void *env, const char *fmt, ...), void } } -STATIC mp_obj_t exception_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { - mp_obj_exception_t *base = self_in; +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) { + mp_obj_type_t *type = type_in; if (n_kw != 0) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "%s does not take keyword arguments", qstr_str(base->id))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%s does not take keyword arguments", type->name)); } mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, n_args); - o->base.type = &exception_type; + o->base.type = type; o->traceback = MP_OBJ_NULL; - o->id = base->id; o->msg = NULL; o->args.len = n_args; memcpy(o->args.items, args, n_args * sizeof(mp_obj_t)); return o; } -const mp_obj_type_t exception_type = { - { &mp_const_type }, - .name = MP_QSTR_, // TODO proper exception names - .print = exception_print, - .call = exception_call, +const mp_obj_type_t mp_type_BaseException = { + { &mp_type_type }, + .name = MP_QSTR_BaseException, + .print = mp_obj_exception_print, + .make_new = mp_obj_exception_make_new, }; -mp_obj_t mp_obj_new_exception(qstr id) { - return mp_obj_new_exception_msg_varg(id, NULL); +#define MP_DEFINE_EXCEPTION(exc_name) \ +STATIC const mp_obj_tuple_t mp_type_ ## exc_name ## _bases_tuple = {{&tuple_type}, 1, {(mp_obj_t)&mp_type_BaseException}};\ +const mp_obj_type_t mp_type_ ## exc_name = { \ + { &mp_type_type }, \ + .name = MP_QSTR_ ## exc_name, \ + .print = mp_obj_exception_print, \ + .make_new = mp_obj_exception_make_new, \ + .bases_tuple = (mp_obj_t)&mp_type_ ## exc_name ## _bases_tuple, \ +}; + +MP_DEFINE_EXCEPTION(AssertionError) +MP_DEFINE_EXCEPTION(AttributeError) +MP_DEFINE_EXCEPTION(ImportError) +MP_DEFINE_EXCEPTION(IndentationError) +MP_DEFINE_EXCEPTION(IndexError) +MP_DEFINE_EXCEPTION(KeyError) +MP_DEFINE_EXCEPTION(NameError) +MP_DEFINE_EXCEPTION(SyntaxError) +MP_DEFINE_EXCEPTION(TypeError) +MP_DEFINE_EXCEPTION(ValueError) +MP_DEFINE_EXCEPTION(OverflowError) +MP_DEFINE_EXCEPTION(OSError) +MP_DEFINE_EXCEPTION(NotImplementedError) +MP_DEFINE_EXCEPTION(StopIteration) + +mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) { + return mp_obj_new_exception_msg_varg(exc_type, NULL); } -mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg) { - return mp_obj_new_exception_msg_varg(id, msg); +mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg) { + return mp_obj_new_exception_msg_varg(exc_type, msg); } -mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) { +mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) { + // check that the given type is an exception type + 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); - o->base.type = &exception_type; + mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, 0); + o->base.type = exc_type; o->traceback = MP_OBJ_NULL; - o->id = id; o->args.len = 0; + if (fmt == NULL) { + // no message o->msg = NULL; } else { // render exception message @@ -97,18 +124,41 @@ mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) { return o; } -qstr mp_obj_exception_get_type(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &exception_type)); +// return true if the given object is an exception type +// TODO make this work for user defined exceptions +bool mp_obj_is_exception_type(mp_obj_t self_in) { + if (MP_OBJ_IS_TYPE(self_in, &mp_type_type)) { + mp_obj_type_t *self = self_in; + return self->make_new == mp_obj_exception_make_new; + } else { + return false; + } +} + +// return true if the given object is an instance of an exception type +// TODO make this work for user defined exceptions +bool mp_obj_is_exception_instance(mp_obj_t self_in) { + return mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new; +} + +void mp_obj_exception_clear_traceback(mp_obj_t self_in) { + // make sure self_in is an exception instance + assert(mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new); mp_obj_exception_t *self = self_in; - return self->id; + + // just set the traceback to the null object + // we don't want to call any memory management functions here + self->traceback = MP_OBJ_NULL; } 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)); + // make sure self_in is an exception instance + assert(mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new); mp_obj_exception_t *self = self_in; + // 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); + self->traceback = mp_obj_new_list(3, 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); @@ -116,8 +166,10 @@ void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t } 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)); + // make sure self_in is an exception instance + assert(mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new); mp_obj_exception_t *self = self_in; + if (self->traceback == MP_OBJ_NULL) { *n = 0; *values = NULL; diff --git a/py/objfilter.c b/py/objfilter.c index 4dde7fac8..dc400f1a2 100644 --- a/py/objfilter.c +++ b/py/objfilter.c @@ -16,7 +16,7 @@ typedef struct _mp_obj_filter_t { STATIC mp_obj_t filter_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { if (n_args != 2 || n_kw != 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "filter expected 2 arguments")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "filter expected 2 arguments")); } assert(n_args == 2); mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t); @@ -45,7 +45,7 @@ STATIC mp_obj_t filter_iternext(mp_obj_t self_in) { } const mp_obj_type_t filter_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_filter, .make_new = filter_make_new, .getiter = mp_identity, diff --git a/py/objfloat.c b/py/objfloat.c index 83b98266e..9d7b79689 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -40,7 +40,7 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m } default: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "float takes at most 1 argument, %d given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "float takes at most 1 argument, %d given", n_args)); } } @@ -64,7 +64,7 @@ STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { } const mp_obj_type_t float_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_float, .print = float_print, .make_new = float_make_new, diff --git a/py/objfun.c b/py/objfun.c index 56ea692ea..433da039b 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -20,23 +20,23 @@ STATIC void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) { if (n_kw && !self->is_kw) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); } if (self->n_args_min == self->n_args_max) { if (n_args != self->n_args_min) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args_min, n_args)); } } else { if (n_args < self->n_args_min) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "() missing %d required positional arguments: ", self->n_args_min - n_args)); } else if (n_args > self->n_args_max) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, " expected at most %d arguments, got %d", self->n_args_max, n_args)); } @@ -89,7 +89,7 @@ STATIC mp_obj_t fun_native_call(mp_obj_t self_in, uint n_args, uint n_kw, const } const mp_obj_type_t fun_native_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_function, .call = fun_native_call, }; @@ -143,10 +143,10 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o mp_obj_fun_bc_t *self = self_in; if (n_args < self->n_args - self->n_def_args || n_args > self->n_args) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args)); } if (n_kw != 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); } uint use_def_args = self->n_args - n_args; @@ -159,7 +159,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o } const mp_obj_type_t fun_bc_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_function, .call = fun_bc_call, }; @@ -252,10 +252,10 @@ STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_ mp_obj_fun_asm_t *self = self_in; if (n_args != self->n_args) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args)); } if (n_kw != 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); } machine_uint_t ret; @@ -276,7 +276,7 @@ STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_ } STATIC const mp_obj_type_t fun_asm_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_function, .call = fun_asm_call, }; diff --git a/py/objgenerator.c b/py/objgenerator.c index 4e7d3a199..226b902da 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -28,17 +28,17 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp const byte *bc_code; mp_obj_fun_bc_get(self_fun, &bc_n_args, &bc_n_state, &bc_code); if (n_args != bc_n_args) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", bc_n_args, n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", bc_n_args, n_args)); } if (n_kw != 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); } return mp_obj_new_gen_instance(bc_code, bc_n_state, n_args, args); } const mp_obj_type_t gen_wrap_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_generator, .call = gen_wrap_call, }; @@ -77,7 +77,7 @@ STATIC mp_obj_t gen_next_send(mp_obj_t self_in, mp_obj_t send_value) { } if (self->sp == self->state - 1) { if (send_value != mp_const_none) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "can't send non-None value to a just-started generator")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator")); } } else { *self->sp = send_value; @@ -108,10 +108,12 @@ mp_obj_t gen_instance_iternext(mp_obj_t self_in) { STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) { mp_obj_t ret = gen_next_send(self_in, send_value); if (ret == mp_const_stop_iteration) { - nlr_jump(mp_obj_new_exception(MP_QSTR_StopIteration)); + nlr_jump(mp_obj_new_exception(&mp_type_StopIteration)); + } else { + return ret; } - return ret; } + STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send); STATIC const mp_method_t gen_type_methods[] = { @@ -120,7 +122,7 @@ STATIC const mp_method_t gen_type_methods[] = { }; const mp_obj_type_t gen_instance_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_generator, .print = gen_instance_print, .getiter = gen_instance_getiter, diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c index 28b118a52..bf466c05d 100644 --- a/py/objgetitemiter.c +++ b/py/objgetitemiter.c @@ -26,7 +26,7 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) { return value; } else { // an exception was raised - if (MP_OBJ_IS_TYPE(nlr.ret_val, &exception_type) && mp_obj_exception_get_type(nlr.ret_val) == MP_QSTR_StopIteration) { + if (mp_obj_get_type(nlr.ret_val) == &mp_type_StopIteration) { // return mp_const_stop_iteration instead of raising StopIteration return mp_const_stop_iteration; } else { @@ -37,7 +37,7 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) { } STATIC const mp_obj_type_t it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = it_iternext }; diff --git a/py/objint.c b/py/objint.c index 1ae3cebbf..b33557b64 100644 --- a/py/objint.c +++ b/py/objint.c @@ -39,7 +39,7 @@ STATIC mp_obj_t int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_ } default: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "int takes at most 2 arguments, %d given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "int takes at most 2 arguments, %d given", n_args)); } } @@ -65,7 +65,7 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // This is called only with strings whose value doesn't fit in SMALL_INT mp_obj_t mp_obj_new_int_from_long_str(const char *s) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OverflowError, "long int not supported in this build")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_OverflowError, "long int not supported in this build")); return mp_const_none; } @@ -75,7 +75,7 @@ mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) { if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) { return MP_OBJ_NEW_SMALL_INT(value); } - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OverflowError, "small int overflow")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); return mp_const_none; } @@ -83,7 +83,7 @@ mp_obj_t mp_obj_new_int(machine_int_t value) { if (MP_OBJ_FITS_SMALL_INT(value)) { return MP_OBJ_NEW_SMALL_INT(value); } - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OverflowError, "small int overflow")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); return mp_const_none; } @@ -98,7 +98,7 @@ machine_int_t mp_obj_int_get_checked(mp_obj_t self_in) { #endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE const mp_obj_type_t int_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_int, .print = int_print, .make_new = int_make_new, diff --git a/py/objlist.c b/py/objlist.c index 844f9cc81..a6fbe4e42 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -62,7 +62,7 @@ STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp } default: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "list takes at most 1 argument, %d given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "list takes at most 1 argument, %d given", n_args)); } return NULL; } @@ -188,7 +188,7 @@ STATIC mp_obj_t list_pop(uint n_args, const mp_obj_t *args) { assert(MP_OBJ_IS_TYPE(args[0], &list_type)); mp_obj_list_t *self = args[0]; if (self->len == 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "pop from empty list")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list")); } uint index = mp_get_index(self->base.type, self->len, n_args == 1 ? mp_obj_new_int(-1) : args[1]); mp_obj_t ret = self->items[index]; @@ -228,7 +228,7 @@ mp_obj_t mp_obj_list_sort(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) { assert(n_args >= 1); assert(MP_OBJ_IS_TYPE(args[0], &list_type)); if (n_args > 1) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "list.sort takes no positional arguments")); } mp_obj_list_t *self = args[0]; @@ -346,7 +346,7 @@ STATIC const mp_method_t list_type_methods[] = { }; const mp_obj_type_t list_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_list, .print = list_print, .make_new = list_make_new, @@ -408,7 +408,7 @@ mp_obj_t list_it_iternext(mp_obj_t self_in) { } STATIC const mp_obj_type_t list_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = list_it_iternext, }; diff --git a/py/objmap.c b/py/objmap.c index 012f0aadb..cbaef6fb9 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -17,7 +17,7 @@ typedef struct _mp_obj_map_t { STATIC mp_obj_t map_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { if (n_args < 2 || n_kw != 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "map must have at least 2 arguments and no keyword arguments")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "map must have at least 2 arguments and no keyword arguments")); } assert(n_args >= 2); mp_obj_map_t *o = m_new_obj_var(mp_obj_map_t, mp_obj_t, n_args - 1); @@ -51,7 +51,7 @@ STATIC mp_obj_t map_iternext(mp_obj_t self_in) { } const mp_obj_type_t map_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_map, .make_new = map_make_new, .getiter = map_getiter, diff --git a/py/objmodule.c b/py/objmodule.c index 14a249171..ab460fbd3 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -38,7 +38,7 @@ STATIC bool module_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { } const mp_obj_type_t module_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_module, .print = module_print, .load_attr = module_load_attr, diff --git a/py/objnone.c b/py/objnone.c index 73f2601be..489d34d13 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -24,7 +24,7 @@ STATIC mp_obj_t none_unary_op(int op, mp_obj_t o_in) { } const mp_obj_type_t none_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_NoneType, .print = none_print, .unary_op = none_unary_op, diff --git a/py/objrange.c b/py/objrange.c index a526ebcec..80c592838 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -24,7 +24,7 @@ STATIC mp_obj_t range_getiter(mp_obj_t o_in) { } STATIC const mp_obj_type_t range_type = { - { &mp_const_type} , + { &mp_type_type} , .name = MP_QSTR_range, .getiter = range_getiter, }; @@ -62,7 +62,7 @@ STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) { } STATIC const mp_obj_type_t range_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = range_it_iternext, }; diff --git a/py/objset.c b/py/objset.c index 580b9de8e..aea107fc1 100644 --- a/py/objset.c +++ b/py/objset.c @@ -67,12 +67,12 @@ STATIC mp_obj_t set_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_ } default: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "set takes at most 1 argument, %d given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "set takes at most 1 argument, %d given", n_args)); } } const mp_obj_type_t set_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = set_it_iternext, }; @@ -310,7 +310,7 @@ STATIC mp_obj_t set_pop(mp_obj_t self_in) { mp_obj_set_t *self = self_in; if (self->set.used == 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "pop from an empty set")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "pop from an empty set")); } mp_obj_t obj = mp_set_lookup(&self->set, NULL, MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_FIRST); @@ -322,7 +322,7 @@ STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) { assert(MP_OBJ_IS_TYPE(self_in, &set_type)); mp_obj_set_t *self = self_in; if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) { - nlr_jump(mp_obj_new_exception(MP_QSTR_KeyError)); + nlr_jump(mp_obj_new_exception(&mp_type_KeyError)); } return mp_const_none; } @@ -446,7 +446,7 @@ STATIC const mp_method_t set_type_methods[] = { }; const mp_obj_type_t set_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_set, .print = set_print, .make_new = set_make_new, diff --git a/py/objslice.c b/py/objslice.c index 66a3c7a7a..10df671fe 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -22,7 +22,7 @@ void ellipsis_print(void (*print)(void *env, const char *fmt, ...), void *env, m } const mp_obj_type_t ellipsis_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_Ellipsis, .print = ellipsis_print, }; @@ -49,7 +49,7 @@ void slice_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_o } const mp_obj_type_t slice_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_slice, .print = slice_print, }; diff --git a/py/objstr.c b/py/objstr.c index 6ccd23995..a1291a220 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -124,7 +124,7 @@ STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { } else { // Message doesn't match CPython, but we don't have so much bytes as they // to spend them on verbose wording - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "index must be int")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "index must be int")); } case RT_BINARY_OP_ADD: @@ -235,7 +235,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { return mp_obj_str_builder_end(joined_str); bad_arg: - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "?str.join expecting a list of str's")); } #define is_ws(c) ((c) == ' ' || (c) == '\t') @@ -387,7 +387,7 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) { } else { while (str < top && *str != '}') str++; if (arg_i >= n_args) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "tuple index out of range")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range")); } // TODO: may be PRINT_REPR depending on formatting code mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[arg_i], PRINT_STR); @@ -507,7 +507,7 @@ STATIC const mp_method_t str_type_methods[] = { }; const mp_obj_type_t str_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_str, .print = str_print, .binary_op = str_binary_op, @@ -517,7 +517,7 @@ const mp_obj_type_t str_type = { // Reuses most of methods from str const mp_obj_type_t bytes_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_bytes, .print = str_print, .binary_op = str_binary_op, @@ -589,7 +589,7 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) { void bad_implicit_conversion(mp_obj_t self_in) __attribute__((noreturn)); void bad_implicit_conversion(mp_obj_t self_in) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in))); } uint mp_obj_str_get_hash(mp_obj_t self_in) { @@ -667,7 +667,7 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { } STATIC const mp_obj_type_t str_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = str_it_iternext, }; @@ -685,7 +685,7 @@ STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) { } STATIC const mp_obj_type_t bytes_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = bytes_it_iternext, }; diff --git a/py/objtuple.c b/py/objtuple.c index de49ce74e..41ad8a5d5 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -70,7 +70,7 @@ STATIC mp_obj_t tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m } default: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "tuple takes at most 1 argument, %d given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "tuple takes at most 1 argument, %d given", n_args)); } } @@ -174,7 +174,7 @@ STATIC const mp_method_t tuple_type_methods[] = { }; const mp_obj_type_t tuple_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_tuple, .print = tuple_print, .make_new = tuple_make_new, @@ -241,7 +241,7 @@ STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) { } STATIC const mp_obj_type_t tuple_it_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_iterator, .iternext = tuple_it_iternext, }; diff --git a/py/objtype.c b/py/objtype.c index a1592140c..46b96c731 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -64,7 +64,7 @@ STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr) { return NULL; } for (uint i = 0; i < len - 1; i++) { - assert(MP_OBJ_IS_TYPE(items[i], &mp_const_type)); + assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); mp_obj_t obj = mp_obj_class_lookup((mp_obj_type_t*)items[i], attr); if (obj != MP_OBJ_NULL) { return obj; @@ -72,7 +72,7 @@ STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr) { } // search last base (simple tail recursion elimination) - assert(MP_OBJ_IS_TYPE(items[len - 1], &mp_const_type)); + assert(MP_OBJ_IS_TYPE(items[len - 1], &mp_type_type)); type = (mp_obj_type_t*)items[len - 1]; } } @@ -82,7 +82,7 @@ STATIC void class_print(void (*print)(void *env, const char *fmt, ...), void *en } STATIC mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type)); + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type)); mp_obj_type_t *self = self_in; mp_obj_t o = mp_obj_new_class(self_in); @@ -103,13 +103,13 @@ STATIC mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const m m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw); } if (init_ret != mp_const_none) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); } } else { // TODO if (n_args != 0) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "function takes 0 positional arguments but %d were given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 0 positional arguments but %d were given", n_args)); } } @@ -252,7 +252,7 @@ bool class_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { /******************************************************************************/ // type object // - the struct is mp_obj_type_t and is defined in obj.h so const types can be made -// - there is a constant mp_obj_type_t (called mp_const_type) for the 'type' object +// - there is a constant mp_obj_type_t (called mp_type_type) for the 'type' object // - creating a new class (a new type) creates a new mp_obj_type_t STATIC void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { @@ -274,7 +274,7 @@ STATIC mp_obj_t type_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]); default: - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "type takes 1 or 3 arguments")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "type takes 1 or 3 arguments")); } } @@ -284,7 +284,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj mp_obj_type_t *self = self_in; if (self->make_new == NULL) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "cannot create '%s' instances", qstr_str(self->name))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%s' instances", qstr_str(self->name))); } // make new instance @@ -296,7 +296,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj // for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self STATIC void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type)); + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type)); mp_obj_type_t *self = self_in; mp_obj_t member = mp_obj_class_lookup(self, attr); if (member != MP_OBJ_NULL) { @@ -318,7 +318,7 @@ STATIC void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } STATIC bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type)); + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type)); mp_obj_type_t *self = self_in; // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation? @@ -333,8 +333,8 @@ STATIC bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { } } -const mp_obj_type_t mp_const_type = { - { &mp_const_type }, +const mp_obj_type_t mp_type_type = { + { &mp_type_type }, .name = MP_QSTR_type, .print = type_print, .make_new = type_make_new, @@ -347,7 +347,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) assert(MP_OBJ_IS_TYPE(bases_tuple, &tuple_type)); // Micro Python restriction, for now assert(MP_OBJ_IS_TYPE(locals_dict, &dict_type)); // Micro Python restriction, for now mp_obj_type_t *o = m_new0(mp_obj_type_t, 1); - o->base.type = &mp_const_type; + o->base.type = &mp_type_type; o->name = name; o->print = class_print; o->make_new = class_make_new; @@ -383,7 +383,7 @@ STATIC mp_obj_t super_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m if (n_args != 2 || n_kw != 0) { // 0 arguments are turned into 2 in the compiler // 1 argument is not yet implemented - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "super() requires 2 arguments")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "super() requires 2 arguments")); } return mp_obj_new_super(args[0], args[1]); } @@ -393,7 +393,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { assert(MP_OBJ_IS_TYPE(self_in, &super_type)); mp_obj_super_t *self = self_in; - assert(MP_OBJ_IS_TYPE(self->type, &mp_const_type)); + assert(MP_OBJ_IS_TYPE(self->type, &mp_type_type)); mp_obj_type_t *type = self->type; @@ -406,7 +406,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_t *items; mp_obj_tuple_get(type->bases_tuple, &len, &items); for (uint i = 0; i < len; i++) { - assert(MP_OBJ_IS_TYPE(items[i], &mp_const_type)); + assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); mp_obj_t member = mp_obj_class_lookup((mp_obj_type_t*)items[i], attr); if (member != MP_OBJ_NULL) { // XXX this and the code in class_load_attr need to be factored out @@ -438,7 +438,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } const mp_obj_type_t super_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_super, .print = super_print, .make_new = super_make_new, @@ -452,42 +452,42 @@ mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj) { } /******************************************************************************/ -// built-ins specific to types +// subclassing and built-ins specific to types -STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { - if (!MP_OBJ_IS_TYPE(object, &mp_const_type)) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "issubclass() arg 1 must be a class")); +bool mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { + if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) { + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class")); } // TODO support a tuple of classes for second argument - if (!MP_OBJ_IS_TYPE(classinfo, &mp_const_type)) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "issubclass() arg 2 must be a class")); + if (!MP_OBJ_IS_TYPE(classinfo, &mp_type_type)) { + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class")); } for (;;) { if (object == classinfo) { - return mp_const_true; + return true; } // not equivalent classes, keep searching base classes - assert(MP_OBJ_IS_TYPE(object, &mp_const_type)); + assert(MP_OBJ_IS_TYPE(object, &mp_type_type)); mp_obj_type_t *self = object; // for a const struct, this entry might be NULL if (self->bases_tuple == MP_OBJ_NULL) { - return mp_const_false; + return false; } uint len; mp_obj_t *items; mp_obj_tuple_get(self->bases_tuple, &len, &items); if (len == 0) { - return mp_const_false; + return false; } for (uint i = 0; i < len - 1; i++) { - if (mp_builtin_issubclass(items[i], classinfo) == mp_const_true) { - return mp_const_true; + if (mp_obj_is_subclass(items[i], classinfo)) { + return true; } } @@ -496,10 +496,14 @@ STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { } } +STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { + return MP_BOOL(mp_obj_is_subclass(object, classinfo)); +} + MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass); STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) { - return mp_builtin_issubclass(mp_obj_get_type(object), classinfo); + return MP_BOOL(mp_obj_is_subclass(mp_obj_get_type(object), classinfo)); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance); @@ -511,7 +515,7 @@ STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, uint n_args, uint assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod); if (n_args != 1 || n_kw != 0) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "function takes 1 positional argument but %d were given", n_args)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 1 positional argument but %d were given", n_args)); } mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t); @@ -520,13 +524,13 @@ STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, uint n_args, uint } const mp_obj_type_t mp_type_staticmethod = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_staticmethod, .make_new = static_class_method_make_new }; const mp_obj_type_t mp_type_classmethod = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_classmethod, .make_new = static_class_method_make_new }; diff --git a/py/objzip.c b/py/objzip.c index 8f1bfe143..b939ff6cb 100644 --- a/py/objzip.c +++ b/py/objzip.c @@ -51,7 +51,7 @@ STATIC mp_obj_t zip_iternext(mp_obj_t self_in) { } const mp_obj_type_t zip_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_zip, .make_new = zip_make_new, .getiter = zip_getiter, diff --git a/py/parse.c b/py/parse.c index d2e892b39..bbab19d35 100644 --- a/py/parse.c +++ b/py/parse.c @@ -302,7 +302,7 @@ STATIC void push_result_rule(parser_t *parser, int src_line, const rule_t *rule, push_result_node(parser, (mp_parse_node_t)pn); } -mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr *exc_id_out, const char **exc_msg_out) { +mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_parse_error_kind_t *parse_error_kind_out) { // allocate memory for the parser and its stacks @@ -634,18 +634,17 @@ finished: syntax_error: if (mp_lexer_is_kind(lex, MP_TOKEN_INDENT)) { - *exc_id_out = MP_QSTR_IndentationError; - *exc_msg_out = "unexpected indent"; + *parse_error_kind_out = MP_PARSE_ERROR_UNEXPECTED_INDENT; } else if (mp_lexer_is_kind(lex, MP_TOKEN_DEDENT_MISMATCH)) { - *exc_id_out = MP_QSTR_IndentationError; - *exc_msg_out = "unindent does not match any outer indentation level"; + *parse_error_kind_out = MP_PARSE_ERROR_UNMATCHED_UNINDENT; } else { - *exc_id_out = MP_QSTR_SyntaxError; - *exc_msg_out = "invalid syntax"; + *parse_error_kind_out = MP_PARSE_ERROR_INVALID_SYNTAX; #ifdef USE_RULE_NAME // debugging: print the rule name that failed and the token - mp_lexer_show_error_pythonic(lex, rule->rule_name); + printf("rule: %s\n", rule->rule_name); +#if MICROPY_DEBUG_PRINTERS mp_token_show(mp_lexer_cur(lex)); +#endif #endif } result = MP_PARSE_NODE_NULL; diff --git a/py/parse.h b/py/parse.h index 9797873d1..66efd8a20 100644 --- a/py/parse.h +++ b/py/parse.h @@ -63,5 +63,11 @@ typedef enum { MP_PARSE_EVAL_INPUT, } mp_parse_input_kind_t; -// returns MP_PARSE_NODE_NULL on error, and then exc_id_out and exc_msg_out are valid -mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr *exc_id_out, const char **exc_msg_out); +typedef enum { + MP_PARSE_ERROR_UNEXPECTED_INDENT, + MP_PARSE_ERROR_UNMATCHED_UNINDENT, + MP_PARSE_ERROR_INVALID_SYNTAX, +} mp_parse_error_kind_t; + +// returns MP_PARSE_NODE_NULL on error, and then parse_error_kind_out is valid +mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_parse_error_kind_t *parse_error_kind_out); diff --git a/py/parsehelper.c b/py/parsehelper.c new file mode 100644 index 000000000..3177e9a34 --- /dev/null +++ b/py/parsehelper.c @@ -0,0 +1,49 @@ +// these functions are separate from parse.c to keep parser independent of mp_obj_t + +#include +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "lexer.h" +#include "parse.h" +#include "obj.h" +#include "parsehelper.h" + +#define STR_UNEXPECTED_INDENT "unexpected indent" +#define STR_UNMATCHED_UNINDENT "unindent does not match any outer indentation level" +#define STR_INVALID_SYNTAX "invalid syntax" + +void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind) { + printf(" File \"%s\", line %d, column %d\n", qstr_str(mp_lexer_source_name(lex)), mp_lexer_cur(lex)->src_line, mp_lexer_cur(lex)->src_column); + switch (parse_error_kind) { + case MP_PARSE_ERROR_UNEXPECTED_INDENT: + printf("IndentationError: %s\n", STR_UNEXPECTED_INDENT); + break; + + case MP_PARSE_ERROR_UNMATCHED_UNINDENT: + printf("IndentationError: %s\n", STR_UNMATCHED_UNINDENT); + break; + + case MP_PARSE_ERROR_INVALID_SYNTAX: + default: + printf("SyntaxError: %s\n", STR_INVALID_SYNTAX); + break; + } +} + +mp_obj_t mp_parse_make_exception(mp_parse_error_kind_t parse_error_kind) { + // TODO add source file and line number to exception? + switch (parse_error_kind) { + case MP_PARSE_ERROR_UNEXPECTED_INDENT: + return mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNEXPECTED_INDENT); + + case MP_PARSE_ERROR_UNMATCHED_UNINDENT: + return mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNMATCHED_UNINDENT); + + case MP_PARSE_ERROR_INVALID_SYNTAX: + default: + return mp_obj_new_exception_msg(&mp_type_SyntaxError, STR_INVALID_SYNTAX); + } +} diff --git a/py/parsehelper.h b/py/parsehelper.h new file mode 100644 index 000000000..1de70d19d --- /dev/null +++ b/py/parsehelper.h @@ -0,0 +1,2 @@ +void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind); +mp_obj_t mp_parse_make_exception(mp_parse_error_kind_t parse_error_kind); diff --git a/py/py.mk b/py/py.mk index 1d9eb535a..cbb63b4bf 100644 --- a/py/py.mk +++ b/py/py.mk @@ -19,6 +19,7 @@ PY_O_BASENAME = \ lexerstr.o \ lexerunix.o \ parse.o \ + parsehelper.o \ scope.o \ compile.o \ emitcommon.o \ diff --git a/py/qstrdefs.h b/py/qstrdefs.h index ac106f983..9f002777b 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -30,6 +30,7 @@ Q(asm_thumb) Q(Ellipsis) Q(StopIteration) +Q(BaseException) Q(AssertionError) Q(AttributeError) Q(ImportError) diff --git a/py/runtime.c b/py/runtime.c index b473a951f..68b8fe077 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -108,7 +108,7 @@ STATIC const mp_builtin_elem_t builtin_table[] = { { MP_QSTR_set, (mp_obj_t)&set_type }, { MP_QSTR_super, (mp_obj_t)&super_type }, { MP_QSTR_tuple, (mp_obj_t)&tuple_type }, - { MP_QSTR_type, (mp_obj_t)&mp_const_type }, + { MP_QSTR_type, (mp_obj_t)&mp_type_type }, { MP_QSTR_zip, (mp_obj_t)&zip_type }, { MP_QSTR_classmethod, (mp_obj_t)&mp_type_classmethod }, @@ -144,6 +144,25 @@ STATIC const mp_builtin_elem_t builtin_table[] = { { MP_QSTR_str, (mp_obj_t)&mp_builtin_str_obj }, { MP_QSTR_bytearray, (mp_obj_t)&mp_builtin_bytearray_obj }, + // built-in exceptions + { MP_QSTR_BaseException, (mp_obj_t)&mp_type_BaseException }, + { MP_QSTR_AssertionError, (mp_obj_t)&mp_type_AssertionError }, + { MP_QSTR_AttributeError, (mp_obj_t)&mp_type_AttributeError }, + { MP_QSTR_ImportError, (mp_obj_t)&mp_type_ImportError }, + { MP_QSTR_IndentationError, (mp_obj_t)&mp_type_IndentationError }, + { MP_QSTR_IndexError, (mp_obj_t)&mp_type_IndexError }, + { MP_QSTR_KeyError, (mp_obj_t)&mp_type_KeyError }, + { MP_QSTR_NameError, (mp_obj_t)&mp_type_NameError }, + { MP_QSTR_SyntaxError, (mp_obj_t)&mp_type_SyntaxError }, + { MP_QSTR_TypeError, (mp_obj_t)&mp_type_TypeError }, + { MP_QSTR_ValueError, (mp_obj_t)&mp_type_ValueError }, + // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/ + // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation + { MP_QSTR_OverflowError, (mp_obj_t)&mp_type_OverflowError }, + { MP_QSTR_OSError, (mp_obj_t)&mp_type_OSError }, + { MP_QSTR_NotImplementedError, (mp_obj_t)&mp_type_NotImplementedError }, + { MP_QSTR_StopIteration, (mp_obj_t)&mp_type_StopIteration }, + // Extra builtins as defined by a port MICROPY_EXTRA_BUILTINS @@ -166,23 +185,6 @@ void rt_init(void) { // init loaded modules table mp_map_init(&map_loaded_modules, 3); - // built-in exceptions (TODO, make these proper classes, and const if possible) - mp_map_add_qstr(&map_builtins, MP_QSTR_AttributeError, mp_obj_new_exception(MP_QSTR_AttributeError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_ImportError, mp_obj_new_exception(MP_QSTR_ImportError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_IndexError, mp_obj_new_exception(MP_QSTR_IndexError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_KeyError, mp_obj_new_exception(MP_QSTR_KeyError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_NameError, mp_obj_new_exception(MP_QSTR_NameError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_TypeError, mp_obj_new_exception(MP_QSTR_TypeError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_SyntaxError, mp_obj_new_exception(MP_QSTR_SyntaxError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_ValueError, mp_obj_new_exception(MP_QSTR_ValueError)); - // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/ - // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation - mp_map_add_qstr(&map_builtins, MP_QSTR_OverflowError, mp_obj_new_exception(MP_QSTR_OverflowError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_OSError, mp_obj_new_exception(MP_QSTR_OSError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_AssertionError, mp_obj_new_exception(MP_QSTR_AssertionError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_NotImplementedError, mp_obj_new_exception(MP_QSTR_NotImplementedError)); - mp_map_add_qstr(&map_builtins, MP_QSTR_StopIteration, mp_obj_new_exception(MP_QSTR_StopIteration)); - // built-in objects mp_map_add_qstr(&map_builtins, MP_QSTR_Ellipsis, mp_const_ellipsis); @@ -413,7 +415,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) { } } if (*s != 0) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_SyntaxError, "invalid syntax for number")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number")); } if (exp_neg) { exp_val = -exp_val; @@ -431,7 +433,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) { return mp_obj_new_float(dec_val); } #else - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_SyntaxError, "decimal numbers not supported")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "decimal numbers not supported")); #endif } @@ -470,7 +472,7 @@ mp_obj_t rt_load_global(qstr qstr) { return e->fun; } } - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%s' is not defined", qstr_str(qstr))); } } return elem->value; @@ -529,7 +531,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_varg(MP_QSTR_TypeError, "bad operand type for unary operator: '%s'", type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bad operand type for unary operator: '%s'", type->name)); } } @@ -569,9 +571,13 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { // deal with exception_match for all types if (op == RT_BINARY_OP_EXCEPTION_MATCH) { - // TODO properly! at the moment it just compares the exception identifier for equality - if (MP_OBJ_IS_TYPE(lhs, &exception_type) && MP_OBJ_IS_TYPE(rhs, &exception_type)) { - if (mp_obj_exception_get_type(lhs) == mp_obj_exception_get_type(rhs)) { + // rhs must be issubclass(rhs, BaseException) + if (mp_obj_is_exception_type(rhs)) { + // if lhs is an instance of an exception, then extract and use its type + if (mp_obj_is_exception_instance(lhs)) { + lhs = mp_obj_get_type(lhs); + } + if (mp_obj_is_subclass(lhs, rhs)) { return mp_const_true; } else { return mp_const_false; @@ -673,7 +679,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } nlr_jump(mp_obj_new_exception_msg_varg( - MP_QSTR_TypeError, "'%s' object is not iterable", + &mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(rhs))); return mp_const_none; } @@ -690,7 +696,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { // TODO implement dispatch for reverse binary ops // TODO specify in error message what the operator is - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported operand types for binary operator: '%s', '%s'", mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs))); return mp_const_none; @@ -772,7 +778,7 @@ mp_obj_t rt_call_function_n_kw(mp_obj_t fun_in, uint n_args, uint n_kw, const mp if (type->call != NULL) { return type->call(fun_in, n_args, n_kw, args); } else { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not callable", type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", type->name)); } } @@ -836,9 +842,9 @@ void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) { return; too_short: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "need more than %d values to unpack", seq_len)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", seq_len)); too_long: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "too many values to unpack (expected %d)", num)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num)); } mp_obj_t rt_build_map(int n_args) { @@ -925,10 +931,10 @@ void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // no attribute/method called attr // following CPython, we give a more detailed error message for type objects - if (MP_OBJ_IS_TYPE(base, &mp_const_type)) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_AttributeError, "type object '%s' has no attribute '%s'", ((mp_obj_type_t*)base)->name, qstr_str(attr))); + if (MP_OBJ_IS_TYPE(base, &mp_type_type)) { + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "type object '%s' has no attribute '%s'", ((mp_obj_type_t*)base)->name, qstr_str(attr))); } else { - 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))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } } } @@ -941,7 +947,7 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { return; } } - 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))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { @@ -961,7 +967,7 @@ void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { } // TODO: call base classes here? } - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base))); } } @@ -978,7 +984,7 @@ mp_obj_t rt_getiter(mp_obj_t o_in) { return mp_obj_new_getitem_iter(dest); } else { // object not iterable - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not iterable", type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", type->name)); } } } @@ -988,7 +994,22 @@ mp_obj_t rt_iternext(mp_obj_t o_in) { if (type->iternext != NULL) { return type->iternext(o_in); } else { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "'%s' object is not an iterator", type->name)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", type->name)); + } +} + +mp_obj_t rt_make_raise_obj(mp_obj_t o) { + DEBUG_printf("raise %p\n", o); + if (mp_obj_is_exception_type(o)) { + // o is an exception type (it is derived from BaseException (or is BaseException)) + // create and return a new exception instance by calling o + return rt_call_function_n_kw(o, 0, 0, NULL); + } else if (mp_obj_is_exception_instance(o)) { + // o is an instance of an exception, so use it as the exception + return o; + } else { + // o cannot be used as an exception, so return a type error (which will be raised by the caller) + return mp_obj_new_exception_msg(&mp_type_TypeError, "exceptions must derive from BaseException"); } } diff --git a/py/runtime.h b/py/runtime.h index f5a9f2abc..1eef99d2f 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -37,6 +37,7 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t val); void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val); mp_obj_t rt_getiter(mp_obj_t o); mp_obj_t rt_iternext(mp_obj_t o); +mp_obj_t rt_make_raise_obj(mp_obj_t o); mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level); mp_obj_t rt_import_from(mp_obj_t module, qstr name); void rt_import_all(mp_obj_t module); diff --git a/py/sequence.c b/py/sequence.c index f5310737a..d3c3e3285 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -162,7 +162,7 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp } } - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "object not in sequence")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "object not in sequence")); } mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value) { diff --git a/py/stream.c b/py/stream.c index f3487cc6e..59877d724 100644 --- a/py/stream.c +++ b/py/stream.c @@ -16,7 +16,7 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0]; if (o->type->stream_p.read == NULL) { // CPython: io.UnsupportedOperation, OSError subclass - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported")); } machine_int_t sz; @@ -27,7 +27,7 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { int error; machine_int_t out_sz = o->type->stream_p.read(o, buf, sz, &error); if (out_sz == -1) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } else { mp_obj_t s = mp_obj_new_str(buf, out_sz, false); // will reallocate to use exact size m_free(buf, sz); @@ -39,7 +39,7 @@ STATIC mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in; if (o->type->stream_p.write == NULL) { // CPython: io.UnsupportedOperation, OSError subclass - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported")); } uint sz; @@ -47,7 +47,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_varg(MP_QSTR_OSError, "[Errno %d]", error)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_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." @@ -62,7 +62,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in; if (o->type->stream_p.read == NULL) { // CPython: io.UnsupportedOperation, OSError subclass - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported")); } int total_size = 0; @@ -74,7 +74,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { while (true) { machine_int_t out_sz = o->type->stream_p.read(self_in, p, current_read, &error); if (out_sz == -1) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } if (out_sz == 0) { break; @@ -88,7 +88,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { p = vstr_extend(vstr, current_read); if (p == NULL) { // TODO - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError/*MP_QSTR_RuntimeError*/, "Out of memory")); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory")); } } } @@ -103,7 +103,7 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0]; if (o->type->stream_p.read == NULL) { // CPython: io.UnsupportedOperation, OSError subclass - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Operation not supported")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported")); } machine_int_t max_size = -1; @@ -123,12 +123,12 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) { char *p = vstr_add_len(vstr, 1); if (p == NULL) { // TODO - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError/*MP_QSTR_RuntimeError*/, "Out of memory")); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory")); } machine_int_t out_sz = o->type->stream_p.read(o, p, 1, &error); if (out_sz == -1) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } if (out_sz == 0) { // Back out previously added byte diff --git a/py/strtonum.c b/py/strtonum.c index 74fa3d675..e83b9751d 100644 --- a/py/strtonum.c +++ b/py/strtonum.c @@ -18,7 +18,7 @@ long strtonum(const char *restrict s, int base) { // check radix base if ((base != 0 && base < 2) || base > 36) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36")); } // skip surrounded whitespace while (isspace((c = *(p++)))); @@ -84,7 +84,7 @@ done: return (found ^ neg) - neg; value_error: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "invalid literal for int() with base %d: '%s'", base, s)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid literal for int() with base %d: '%s'", base, s)); } #else /* defined(UNIX) */ diff --git a/py/vm.c b/py/vm.c index 1fc5b4a57..461fecbda 100644 --- a/py/vm.c +++ b/py/vm.c @@ -371,7 +371,7 @@ unwind_jump: // if TOS is None, just pops it and continues // if TOS is an integer, does something else // else error - if (MP_OBJ_IS_TYPE(TOP(), &exception_type)) { + if (mp_obj_is_exception_instance(TOP())) { nlr_jump(TOP()); } if (TOP() == mp_const_none) { @@ -575,7 +575,7 @@ unwind_return: unum = *ip++; assert(unum == 1); obj1 = POP(); - nlr_jump(obj1); + nlr_jump(rt_make_raise_obj(obj1)); case MP_BC_YIELD_VALUE: nlr_pop(); @@ -613,7 +613,7 @@ unwind_return: // set file and line number that the exception occurred at // TODO: don't set traceback for exceptions re-raised by END_FINALLY. // But consider how to handle nested exceptions. - if (MP_OBJ_IS_TYPE(nlr.ret_val, &exception_type)) { + if (mp_obj_is_exception_instance(nlr.ret_val)) { machine_uint_t code_info_size = code_info[0] | (code_info[1] << 8) | (code_info[2] << 16) | (code_info[3] << 24); qstr source_file = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24); qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24); diff --git a/stm/adc.c b/stm/adc.c index 89f137a08..cd915b172 100644 --- a/stm/adc.c +++ b/stm/adc.c @@ -332,7 +332,7 @@ static const mp_method_t adc_all_methods[] = { }; static const mp_obj_type_t adc_all_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_ADC, .print = adc_all_print, .methods = adc_all_methods, @@ -386,7 +386,7 @@ static const mp_method_t adc_methods[] = { }; static const mp_obj_type_t adc_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_ADC, .print = adc_print, .methods = adc_methods, @@ -427,7 +427,7 @@ mp_obj_t pyb_ADC(mp_obj_t pin_name_obj) { } if (i == ADC_NUM_CHANNELS) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %s does not have ADC capabilities", pin_name)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not have ADC capabilities", pin_name)); } // init ADC just for this channel @@ -438,7 +438,7 @@ mp_obj_t pyb_ADC(mp_obj_t pin_name_obj) { return o; pin_error: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %s does not exist", pin_name)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not exist", pin_name)); } MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_obj, pyb_ADC); diff --git a/stm/file.c b/stm/file.c index f50d3771a..283159a69 100644 --- a/stm/file.c +++ b/stm/file.c @@ -60,7 +60,7 @@ static const mp_method_t file_methods[] = { }; static const mp_obj_type_t file_obj_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_File, .print = file_obj_print, .methods = file_methods, diff --git a/stm/i2c.c b/stm/i2c.c index f355878f2..33d9a43f3 100644 --- a/stm/i2c.c +++ b/stm/i2c.c @@ -335,7 +335,7 @@ static const mp_method_t i2c_methods[] = { }; static const mp_obj_type_t i2c_obj_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_I2C, .print = i2c_obj_print, .methods = i2c_methods, diff --git a/stm/led.c b/stm/led.c index 3a7d8a7a7..683e82bc6 100644 --- a/stm/led.c +++ b/stm/led.c @@ -148,7 +148,7 @@ static const mp_method_t led_methods[] = { }; static const mp_obj_type_t led_obj_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_Led, .print = led_obj_print, .methods = led_methods, diff --git a/stm/main.c b/stm/main.c index 3484fd28d..2bf7c1ba3 100644 --- a/stm/main.c +++ b/stm/main.c @@ -24,6 +24,7 @@ #include "lexerfatfs.h" #include "parse.h" #include "obj.h" +#include "parsehelper.h" #include "compile.h" #include "runtime0.h" #include "runtime.h" @@ -404,15 +405,13 @@ void do_repl(void) { } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0); - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind); qstr source_name = mp_lexer_source_name(lex); if (pn == MP_PARSE_NODE_NULL) { // parse error - mp_lexer_show_error_pythonic_prefix(lex); - printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); } else { // parse okay @@ -456,15 +455,13 @@ bool do_file(const char *filename) { return false; } - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); qstr source_name = mp_lexer_source_name(lex); if (pn == MP_PARSE_NODE_NULL) { // parse error - mp_lexer_show_error_pythonic_prefix(lex); - printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return false; } @@ -536,7 +533,7 @@ mp_obj_t pyb_gpio(uint n_args, mp_obj_t *args) { } pin_error: - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %s does not exist", pin_name)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not exist", pin_name)); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio); diff --git a/stm/sdcard.c b/stm/sdcard.c index c98bab4d9..0b5fdb2c8 100644 --- a/stm/sdcard.c +++ b/stm/sdcard.c @@ -202,7 +202,7 @@ static const mp_method_t sdcard_methods[] = { }; static const mp_obj_type_t sdcard_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_SDcard, .methods = sdcard_methods, }; diff --git a/stm/servo.c b/stm/servo.c index 4b69eefcf..4943a6442 100644 --- a/stm/servo.c +++ b/stm/servo.c @@ -144,7 +144,7 @@ static const mp_method_t servo_methods[] = { }; static const mp_obj_type_t servo_obj_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_Servo, .print = servo_obj_print, .methods = servo_methods, diff --git a/stm/usart.c b/stm/usart.c index e24211a83..6478f0115 100644 --- a/stm/usart.c +++ b/stm/usart.c @@ -242,7 +242,7 @@ static const mp_method_t usart_methods[] = { }; static const mp_obj_type_t usart_obj_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_Usart, .print = usart_obj_print, .methods = usart_methods, diff --git a/stm/usb.c b/stm/usb.c index 0fe56d321..718d432e6 100644 --- a/stm/usb.c +++ b/stm/usb.c @@ -41,7 +41,7 @@ void pyb_usb_dev_init(void) { dev_is_enabled = 1; // create an exception object for interrupting by VCP - mp_const_vcp_interrupt = mp_obj_new_exception(qstr_from_str("VCPInterrupt")); + mp_const_vcp_interrupt = mp_obj_new_exception_msg(&mp_type_OSError, "VCPInterrupt"); #endif } @@ -66,6 +66,7 @@ void usb_vcp_receive(const char *buf, uint32_t len) { // catch special interrupt character if (buf[i] == interrupt_char) { // raise exception when interrupts are finished + mp_obj_exception_clear_traceback(mp_const_vcp_interrupt); pendsv_nlr_jump(mp_const_vcp_interrupt); interrupt_char = VCP_CHAR_NONE; continue; diff --git a/teensy/led.c b/teensy/led.c index 49ba46b4d..e2a057416 100644 --- a/teensy/led.c +++ b/teensy/led.c @@ -70,7 +70,7 @@ static const mp_method_t led_methods[] = { }; static const mp_obj_type_t led_obj_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_Led, .print = led_obj_print, .methods = led_methods, diff --git a/teensy/main.c b/teensy/main.c index 70067927f..ab7bd4681 100644 --- a/teensy/main.c +++ b/teensy/main.c @@ -346,15 +346,13 @@ bool do_file(const char *filename) { return false; } - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); qstr source_name = mp_lexer_source_name(lex); if (pn == MP_PARSE_NODE_NULL) { // parse error - mp_lexer_show_error_pythonic_prefix(lex); - printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return false; } @@ -413,15 +411,13 @@ void do_repl(void) { } mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr_str(&line), vstr_len(&line), 0); - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind); qstr source_name = mp_lexer_source_name(lex); if (pn == MP_PARSE_NODE_NULL) { // parse error - mp_lexer_show_error_pythonic_prefix(lex); - printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); } else { // parse okay diff --git a/teensy/servo.c b/teensy/servo.c index c3a2b2888..51714dbcc 100644 --- a/teensy/servo.c +++ b/teensy/servo.c @@ -189,7 +189,7 @@ static const mp_method_t servo_methods[] = { */ static const mp_obj_type_t servo_obj_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_Servo, .print = servo_obj_print, .methods = servo_methods, @@ -217,7 +217,7 @@ mp_obj_t pyb_Servo(void) { self->servo_id++; } m_del_obj(pyb_servo_obj_t, self); - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "No available servo ids")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "No available servo ids")); return mp_const_none; } diff --git a/unix-cpy/main.c b/unix-cpy/main.c index 10003c992..52d63273c 100644 --- a/unix-cpy/main.c +++ b/unix-cpy/main.c @@ -10,6 +10,7 @@ #include "lexerunix.h" #include "parse.h" #include "obj.h" +#include "parsehelper.h" #include "compile.h" #include "runtime0.h" @@ -29,14 +30,12 @@ void do_file(const char *file) { } else { // parse - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); if (pn == MP_PARSE_NODE_NULL) { // parse error - mp_lexer_show_error_pythonic_prefix(lex); - printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return; } diff --git a/unix/ffi.c b/unix/ffi.c index a82e4e338..ef9c6ea9d 100644 --- a/unix/ffi.c +++ b/unix/ffi.c @@ -46,7 +46,7 @@ typedef struct _mp_obj_fficallback_t { ffi_type *params[]; } mp_obj_fficallback_t; -static const mp_obj_type_t opaque_type; +//static const mp_obj_type_t opaque_type; static const mp_obj_type_t ffimod_type; static const mp_obj_type_t ffifunc_type; static const mp_obj_type_t fficallback_type; @@ -80,7 +80,7 @@ static ffi_type *get_ffi_type(mp_obj_t o_in) } // TODO: Support actual libffi type objects - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "Unknown type")); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Unknown type")); } static mp_obj_t return_ffi_value(ffi_arg val, char type) @@ -118,7 +118,7 @@ static mp_obj_t ffimod_func(uint n_args, const mp_obj_t *args) { void *sym = dlsym(self->handle, symname); if (sym == NULL) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", errno)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno)); } int nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(args[3])); mp_obj_ffifunc_t *o = m_new_obj_var(mp_obj_ffifunc_t, ffi_type*, nparams); @@ -136,7 +136,7 @@ static mp_obj_t ffimod_func(uint n_args, const mp_obj_t *args) { int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); if (res != FFI_OK) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "Error in ffi_prep_cif")); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error in ffi_prep_cif")); } return o; @@ -173,12 +173,12 @@ static mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params); if (res != FFI_OK) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "Error in ffi_prep_cif")); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error in ffi_prep_cif")); } res = ffi_prep_closure_loc(o->clo, &o->cif, call_py_func, func_in, o->func); if (res != FFI_OK) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "ffi_prep_closure_loc")); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "ffi_prep_closure_loc")); } return o; @@ -192,7 +192,7 @@ static mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symna void *sym = dlsym(self->handle, symname); if (sym == NULL) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", errno)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno)); } mp_obj_ffivar_t *o = m_new_obj(mp_obj_ffivar_t); o->base.type = &ffivar_type; @@ -208,7 +208,7 @@ static mp_obj_t ffimod_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const void *mod = dlopen(fname, RTLD_NOW | RTLD_LOCAL); if (mod == NULL) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", errno)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno)); } mp_obj_ffimod_t *o = m_new_obj(mp_obj_ffimod_t); o->base.type = type_in; @@ -224,8 +224,8 @@ static const mp_method_t ffimod_type_methods[] = { }; static const mp_obj_type_t ffimod_type = { - { &mp_const_type }, - "ffimod", + { &mp_type_type }, + .name = MP_QSTR_ffimod, .print = ffimod_print, .make_new = ffimod_make_new, .methods = ffimod_type_methods, @@ -270,8 +270,8 @@ mp_obj_t ffifunc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t * } static const mp_obj_type_t ffifunc_type = { - { &mp_const_type }, - "ffifunc", + { &mp_type_type }, + .name = MP_QSTR_ffifunc, .print = ffifunc_print, .call = ffifunc_call, }; @@ -284,8 +284,8 @@ static void fficallback_print(void (*print)(void *env, const char *fmt, ...), vo } static const mp_obj_type_t fficallback_type = { - { &mp_const_type }, - "fficallback", + { &mp_type_type }, + .name = MP_QSTR_fficallback, .print = fficallback_print, }; @@ -316,20 +316,21 @@ static const mp_method_t ffivar_type_methods[] = { }; static const mp_obj_type_t ffivar_type = { - { &mp_const_type }, - "ffivar", + { &mp_type_type }, + .name = MP_QSTR_ffivar, .print = ffivar_print, .methods = ffivar_type_methods, }; -// Generic opaque storage object +// Generic opaque storage object (unused) +/* static const mp_obj_type_t opaque_type = { - { &mp_const_type }, - "opaqueval", + { &mp_type_type }, + .name = MP_QSTR_opaqueval, // .print = opaque_print, }; - +*/ mp_obj_t mod_ffi_open(uint n_args, const mp_obj_t *args) { return ffimod_make_new((mp_obj_t)&ffimod_type, n_args, 0, args); diff --git a/unix/file.c b/unix/file.c index 4e8fba54c..444a05d49 100644 --- a/unix/file.c +++ b/unix/file.c @@ -99,7 +99,7 @@ static mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const int fd = open(fname, mode, 0644); if (fd == -1) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", errno)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno)); } return fdfile_new(fd); } @@ -115,7 +115,7 @@ static const mp_method_t rawfile_type_methods[] = { }; static const mp_obj_type_t rawfile_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_io_dot_FileIO, .print = fdfile_print, .make_new = fdfile_make_new, diff --git a/unix/main.c b/unix/main.c index 6aafe94dd..8e6a76bba 100644 --- a/unix/main.c +++ b/unix/main.c @@ -11,6 +11,7 @@ #include "lexerunix.h" #include "parse.h" #include "obj.h" +#include "parsehelper.h" #include "compile.h" #include "runtime0.h" #include "runtime.h" @@ -49,14 +50,12 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind return; } - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind); if (pn == MP_PARSE_NODE_NULL) { // parse error - mp_lexer_show_error_pythonic_prefix(lex); - printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return; } @@ -194,7 +193,7 @@ static const mp_method_t test_methods[] = { }; static const mp_obj_type_t test_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_Test, .print = test_print, .methods = test_methods, diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h index 42c88b469..867afaeac 100644 --- a/unix/qstrdefsport.h +++ b/unix/qstrdefsport.h @@ -17,3 +17,7 @@ Q(getaddrinfo) Q(microsocket) Q(io.FileIO) +Q(ffimod) +Q(ffifunc) +Q(fficallback) +Q(ffivar) diff --git a/unix/socket.c b/unix/socket.c index 25c4bfcb4..a9cf4a81a 100644 --- a/unix/socket.c +++ b/unix/socket.c @@ -29,7 +29,7 @@ static const mp_obj_type_t microsocket_type; // Helper functions #define RAISE_ERRNO(err_flag, error_val) \ { if (err_flag == -1) \ - { nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error_val)); } } + { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error_val)); } } static void get_buffer(mp_obj_t obj, buffer_info_t *bufinfo) { mp_obj_base_t *o = (mp_obj_base_t *)obj; @@ -43,7 +43,7 @@ static void get_buffer(mp_obj_t obj, buffer_info_t *bufinfo) { return; error: - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "Operation not supported")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "Operation not supported")); } static mp_obj_socket_t *socket_new(int fd) { @@ -237,7 +237,7 @@ static const mp_method_t microsocket_type_methods[] = { }; static const mp_obj_type_t microsocket_type = { - { &mp_const_type }, + { &mp_type_type }, .name = MP_QSTR_socket, .print = socket_print, .make_new = socket_make_new, @@ -260,7 +260,7 @@ static mp_obj_t mod_socket_inet_aton(mp_obj_t arg) { const char *s = mp_obj_str_get_str(arg); struct in_addr addr; if (!inet_aton(s, &addr)) { - nlr_jump(mp_obj_new_exception_msg(MP_QSTR_OSError, "Invalid IP address")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Invalid IP address")); } return mp_obj_new_int(addr.s_addr); @@ -273,7 +273,7 @@ static mp_obj_t mod_socket_gethostbyname(mp_obj_t arg) { const char *s = mp_obj_str_get_str(arg); struct hostent *h = gethostbyname(s); if (h == NULL) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", errno)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno)); } assert(h->h_length == 4); return mp_obj_new_int(*(int*)*h->h_addr_list); @@ -305,7 +305,7 @@ static mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) { int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr); if (res != 0) { - nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[addrinfo error %d]", res)); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res)); } assert(addr); diff --git a/windows/main.c b/windows/main.c index da0cbca44..4456a796d 100644 --- a/windows/main.c +++ b/windows/main.c @@ -11,6 +11,7 @@ #include "lexerunix.h" #include "parse.h" #include "obj.h" +#include "parsehelper.h" #include "compile.h" #include "runtime0.h" #include "runtime.h" @@ -39,14 +40,12 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind return; } - qstr parse_exc_id; - const char *parse_exc_msg; - mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_exc_id, &parse_exc_msg); + mp_parse_error_kind_t parse_error_kind; + mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind); if (pn == MP_PARSE_NODE_NULL) { // parse error - mp_lexer_show_error_pythonic_prefix(lex); - printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg); + mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return; }