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.
This commit is contained in:
Damien George 2014-02-15 16:10:44 +00:00
parent a71c83a1d1
commit c5966128c7
64 changed files with 473 additions and 347 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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)));
}
}

View File

@ -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);

View File

@ -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,
};

View File

@ -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,

View File

@ -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,
};

View File

@ -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
};

View File

@ -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,
};

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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,
};

View File

@ -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,

View File

@ -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
};

View File

@ -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,

View File

@ -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,
};

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,
};

View File

@ -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,

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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
};

View File

@ -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,

View File

@ -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;

View File

@ -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);

49
py/parsehelper.c Normal file
View File

@ -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);
}
}

2
py/parsehelper.h Normal file
View File

@ -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);

View File

@ -19,6 +19,7 @@ PY_O_BASENAME = \
lexerstr.o \
lexerunix.o \
parse.o \
parsehelper.o \
scope.o \
compile.o \
emitcommon.o \

View File

@ -30,6 +30,7 @@ Q(asm_thumb)
Q(Ellipsis)
Q(StopIteration)
Q(BaseException)
Q(AssertionError)
Q(AttributeError)
Q(ImportError)

View File

@ -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");
}
}

View File

@ -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);

View File

@ -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) {

View File

@ -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

View File

@ -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) */

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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,
};

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -17,3 +17,7 @@ Q(getaddrinfo)
Q(microsocket)
Q(io.FileIO)
Q(ffimod)
Q(ffifunc)
Q(fficallback)
Q(ffivar)

View File

@ -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);

View File

@ -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;
}