[python] Update to MicroPython 1.9.4

This commit is contained in:
Romain Goyet
2018-05-23 11:35:29 +02:00
committed by EmilieNumworks
parent caff93cda0
commit 73250e727a
100 changed files with 2301 additions and 1417 deletions

View File

@@ -83,8 +83,10 @@ void mp_init(void) {
MICROPY_PORT_INIT_FUNC;
#endif
#if MICROPY_ENABLE_COMPILER
// optimization disabled by default
MP_STATE_VM(mp_optimise_value) = 0;
#endif
// init global module dict
mp_obj_dict_init(&MP_STATE_VM(mp_loaded_modules_dict), 3);
@@ -214,7 +216,7 @@ void mp_delete_global(qstr qst) {
}
mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
DEBUG_OP_printf("unary " UINT_FMT " %p\n", op, arg);
DEBUG_OP_printf("unary " UINT_FMT " %q %p\n", op, mp_unary_op_method_name[op], arg);
if (op == MP_UNARY_OP_NOT) {
// "not x" is the negative of whether "x" is true per Python semantics
@@ -275,7 +277,7 @@ mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
}
mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
DEBUG_OP_printf("binary " UINT_FMT " %p %p\n", op, lhs, rhs);
DEBUG_OP_printf("binary " UINT_FMT " %q %p %p\n", op, mp_binary_op_method_name[op], lhs, rhs);
// TODO correctly distinguish inplace operators for mutable objects
// lookup logic that CPython uses for +=:
@@ -413,7 +415,6 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
// use standard precision
return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
}
break;
}
case MP_BINARY_OP_FLOOR_DIVIDE:
case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
@@ -488,10 +489,10 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
return MP_OBJ_FROM_PTR(tuple);
}
case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); break;
case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); break;
case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); break;
case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); break;
case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val);
case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val);
case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val);
case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val);
default:
goto unsupported_op;
@@ -523,38 +524,12 @@ mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
}
}
/* deal with `in`
*
* NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch
* needs to go below with swapped arguments
*/
// Convert MP_BINARY_OP_IN to MP_BINARY_OP_CONTAINS with swapped args.
if (op == MP_BINARY_OP_IN) {
mp_obj_type_t *type = mp_obj_get_type(rhs);
if (type->binary_op != NULL) {
mp_obj_t res = type->binary_op(op, rhs, lhs);
if (res != MP_OBJ_NULL) {
return res;
}
}
if (type->getiter != NULL) {
/* second attempt, walk the iterator */
mp_obj_iter_buf_t iter_buf;
mp_obj_t iter = mp_getiter(rhs, &iter_buf);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
if (mp_obj_equal(next, lhs)) {
return mp_const_true;
}
}
return mp_const_false;
}
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_raise_TypeError("object not iterable");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object is not iterable", mp_obj_get_type_str(rhs)));
}
op = MP_BINARY_OP_CONTAINS;
mp_obj_t temp = lhs;
lhs = rhs;
rhs = temp;
}
// generic binary_op supplied by type
@@ -583,6 +558,20 @@ generic_binary_op:
}
#endif
if (op == MP_BINARY_OP_CONTAINS) {
// If type didn't support containment then explicitly walk the iterator.
// mp_getiter will raise the appropriate exception if lhs is not iterable.
mp_obj_iter_buf_t iter_buf;
mp_obj_t iter = mp_getiter(lhs, &iter_buf);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
if (mp_obj_equal(next, rhs)) {
return mp_const_true;
}
}
return mp_const_false;
}
unsupported_op:
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_raise_TypeError("unsupported type for operator");
@@ -681,7 +670,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
// allocate memory for the new array of args
args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len);
args2 = m_new(mp_obj_t, args2_alloc);
args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t));
// copy the self
if (self != MP_OBJ_NULL) {
@@ -702,7 +691,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
// allocate memory for the new array of args
args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len);
args2 = m_new(mp_obj_t, args2_alloc);
args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t));
// copy the self
if (self != MP_OBJ_NULL) {
@@ -718,7 +707,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
// allocate memory for the new array of args
args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len) + 3;
args2 = m_new(mp_obj_t, args2_alloc);
args2 = mp_nonlocal_alloc(args2_alloc * sizeof(mp_obj_t));
// copy the self
if (self != MP_OBJ_NULL) {
@@ -735,7 +724,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (args2_len >= args2_alloc) {
args2 = m_renew(mp_obj_t, args2, args2_alloc, args2_alloc * 2);
args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), args2_alloc * 2 * sizeof(mp_obj_t));
args2_alloc *= 2;
}
args2[args2_len++] = item;
@@ -761,8 +750,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
// the key must be a qstr, so intern it if it's a string
mp_obj_t key = map->table[i].key;
if (MP_OBJ_IS_TYPE(key, &mp_type_str)) {
key = mp_obj_str_intern(key);
if (!MP_OBJ_IS_QSTR(key)) {
key = mp_obj_str_intern_checked(key);
}
args2[args2_len++] = key;
args2[args2_len++] = map->table[i].value;
@@ -786,13 +775,13 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
if (new_alloc < 4) {
new_alloc = 4;
}
args2 = m_renew(mp_obj_t, args2, args2_alloc, new_alloc);
args2 = mp_nonlocal_realloc(args2, args2_alloc * sizeof(mp_obj_t), new_alloc * sizeof(mp_obj_t));
args2_alloc = new_alloc;
}
// the key must be a qstr, so intern it if it's a string
if (MP_OBJ_IS_TYPE(key, &mp_type_str)) {
key = mp_obj_str_intern(key);
if (!MP_OBJ_IS_QSTR(key)) {
key = mp_obj_str_intern_checked(key);
}
// get the value corresponding to the key
@@ -818,7 +807,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ob
mp_call_prepare_args_n_kw_var(have_self, n_args_n_kw, args, &out_args);
mp_obj_t res = mp_call_function_n_kw(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args);
m_del(mp_obj_t, out_args.args, out_args.n_alloc);
mp_nonlocal_free(out_args.args, out_args.n_alloc * sizeof(mp_obj_t));
return res;
}
@@ -1097,6 +1086,22 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
}
}
// Acts like mp_load_method_maybe but catches AttributeError, and all other exceptions if requested
void mp_load_method_protected(mp_obj_t obj, qstr attr, mp_obj_t *dest, bool catch_all_exc) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_load_method_maybe(obj, attr, dest);
nlr_pop();
} else {
if (!catch_all_exc
&& !mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type),
MP_OBJ_FROM_PTR(&mp_type_AttributeError))) {
// Re-raise the exception
nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val));
}
}
}
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
mp_obj_type_t *type = mp_obj_get_type(base);
@@ -1228,13 +1233,12 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
if (type->iternext != NULL && send_value == mp_const_none) {
mp_obj_t ret = type->iternext(self_in);
*ret_val = ret;
if (ret != MP_OBJ_STOP_ITERATION) {
*ret_val = ret;
return MP_VM_RETURN_YIELD;
} else {
// Emulate raise StopIteration()
// Special case, handled in vm.c
*ret_val = MP_OBJ_NULL;
return MP_VM_RETURN_NORMAL;
}
}
@@ -1296,7 +1300,7 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
// will be propagated up. This behavior is approved by test_pep380.py
// test_delegation_of_close_to_non_generator(),
// test_delegating_throw_to_non_generator()
*ret_val = throw_value;
*ret_val = mp_make_raise_obj(throw_value);
return MP_VM_RETURN_EXCEPTION;
}
}
@@ -1350,6 +1354,8 @@ import_error:
return dest[0];
}
#if MICROPY_ENABLE_EXTERNAL_IMPORT
// See if it's a package, then can try FS import
if (!mp_obj_is_package(module)) {
goto import_error;
@@ -1360,11 +1366,12 @@ import_error:
const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len);
const uint dot_name_len = pkg_name_len + 1 + qstr_len(name);
char *dot_name = alloca(dot_name_len);
char *dot_name = mp_local_alloc(dot_name_len);
memcpy(dot_name, pkg_name, pkg_name_len);
dot_name[pkg_name_len] = '.';
memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name));
qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len);
mp_local_free(dot_name);
mp_obj_t args[5];
args[0] = MP_OBJ_NEW_QSTR(dot_name_q);
@@ -1375,6 +1382,13 @@ import_error:
// TODO lookup __import__ and call that instead of going straight to builtin implementation
return mp_builtin___import__(5, args);
#else
// Package import not supported with external imports disabled
goto import_error;
#endif
}
void mp_import_all(mp_obj_t module) {
@@ -1468,3 +1482,10 @@ NORETURN void mp_raise_OSError(int errno_) {
NORETURN void mp_raise_NotImplementedError(const char *msg) {
mp_raise_msg(&mp_type_NotImplementedError, msg);
}
#if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK
NORETURN void mp_raise_recursion_depth(void) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
}
#endif