From c5966128c7c8a768f6726f299d85d5daef6bed48 Mon Sep 17 00:00:00 2001 From: Damien George <damien.p.george@gmail.com> Date: Sat, 15 Feb 2014 16:10:44 +0000 Subject: [PATCH] Implement proper exception type hierarchy. Each built-in exception is now a type, with base type BaseException. C exceptions are created by passing a pointer to the exception type to make an instance of. When raising an exception from the VM, an instance is created automatically if an exception type is raised (as opposed to an exception instance). Exception matching (RT_BINARY_OP_EXCEPTION_MATCH) is now proper. Handling of parse error changed to match new exceptions. mp_const_type renamed to mp_type_type for consistency. --- py/builtin.c | 18 ++++---- py/builtinevex.c | 9 ++-- py/builtinimport.c | 12 ++--- py/lexer.c | 34 +------------- py/mpconfig.h | 1 + py/obj.c | 18 ++++---- py/obj.h | 32 ++++++++++--- py/objarray.c | 6 +-- py/objbool.c | 4 +- py/objboundmeth.c | 2 +- py/objcell.c | 2 +- py/objclosure.c | 2 +- py/objcomplex.c | 4 +- py/objdict.c | 16 +++---- py/objenumerate.c | 2 +- py/objexcept.c | 108 ++++++++++++++++++++++++++++++++------------ py/objfilter.c | 4 +- py/objfloat.c | 4 +- py/objfun.c | 22 ++++----- py/objgenerator.c | 16 ++++--- py/objgetitemiter.c | 4 +- py/objint.c | 10 ++-- py/objlist.c | 10 ++-- py/objmap.c | 4 +- py/objmodule.c | 2 +- py/objnone.c | 2 +- py/objrange.c | 4 +- py/objset.c | 10 ++-- py/objslice.c | 4 +- py/objstr.c | 16 +++---- py/objtuple.c | 6 +-- py/objtype.c | 70 ++++++++++++++-------------- py/objzip.c | 2 +- py/parse.c | 15 +++--- py/parse.h | 10 +++- py/parsehelper.c | 49 ++++++++++++++++++++ py/parsehelper.h | 2 + py/py.mk | 1 + py/qstrdefs.h | 1 + py/runtime.c | 95 +++++++++++++++++++++++--------------- py/runtime.h | 1 + py/sequence.c | 2 +- py/stream.c | 20 ++++---- py/strtonum.c | 4 +- py/vm.c | 6 +-- stm/adc.c | 8 ++-- stm/file.c | 2 +- stm/i2c.c | 2 +- stm/led.c | 2 +- stm/main.c | 19 ++++---- stm/sdcard.c | 2 +- stm/servo.c | 2 +- stm/usart.c | 2 +- stm/usb.c | 3 +- teensy/led.c | 2 +- teensy/main.c | 16 +++---- teensy/servo.c | 4 +- unix-cpy/main.c | 9 ++-- unix/ffi.c | 41 +++++++++-------- unix/file.c | 4 +- unix/main.c | 11 ++--- unix/qstrdefsport.h | 4 ++ unix/socket.c | 12 ++--- windows/main.c | 9 ++-- 64 files changed, 473 insertions(+), 347 deletions(-) create mode 100644 py/parsehelper.c create mode 100644 py/parsehelper.h 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, "<value>")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>")); } 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, "<value>")); + nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>")); } 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, "<fun name>() missing %d required positional arguments: <list of names of params>", 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, "<fun name> 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 <stdint.h> +#include <stdio.h> + +#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; } -- GitLab