summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--py/builtin.c2
-rw-r--r--py/compile.c54
-rw-r--r--py/emitbc.c27
-rw-r--r--py/emitglue.c9
-rw-r--r--py/emitnative.c16
-rw-r--r--py/objdict.c2
-rw-r--r--py/objfun.c6
-rw-r--r--py/objgenerator.c12
-rw-r--r--py/objstr.c4
-rw-r--r--py/objtype.c4
-rw-r--r--py/runtime.c70
-rw-r--r--py/runtime.h13
-rw-r--r--py/vm.c35
-rw-r--r--py/vstr.c4
-rw-r--r--stm/accel.c4
-rw-r--r--stmhal/accel.c2
-rw-r--r--tests/basics/class_inherit_mul.py37
-rw-r--r--tests/basics/for2.py8
-rw-r--r--tests/misc/features.py159
-rw-r--r--unix/main.c2
-rw-r--r--unix/socket.c4
-rw-r--r--windows/main.c2
22 files changed, 349 insertions, 127 deletions
diff --git a/py/builtin.c b/py/builtin.c
index d606db17f4..57d3aa70b7 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -192,7 +192,7 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
mp_obj_t args[2];
args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
- return mp_build_tuple(2, args);
+ return mp_obj_new_tuple(2, args);
} else {
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)));
}
diff --git a/py/compile.c b/py/compile.c
index dc5a8b38a2..25830eb6f9 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -776,17 +776,14 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
}
// stuff for lambda and comprehensions and generators
+// if we are not in CPython compatibility mode then:
+// if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults
+// if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults
+// if both exist, the tuple is above the dictionary (ie the first pop gets the tuple)
void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
assert(n_pos_defaults >= 0);
assert(n_kw_defaults >= 0);
-#if !MICROPY_EMIT_CPYTHON
- // in Micro Python we put the default params into a tuple using the bytecode
- if (n_pos_defaults) {
- EMIT_ARG(build_tuple, n_pos_defaults);
- }
-#endif
-
// make closed over variables, if any
// ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
int nfree = 0;
@@ -870,8 +867,19 @@ void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
if (comp->have_bare_star) {
comp->param_pass_num_dict_params += 1;
if (comp->param_pass == 1) {
+#if !MICROPY_EMIT_CPYTHON
+ // in Micro Python we put the default dict parameters into a dictionary using the bytecode
+ if (comp->param_pass_num_dict_params == 1) {
+ // first default dict param, so make the map
+ EMIT_ARG(build_map, 0);
+ }
+#endif
EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pn_id));
compile_node(comp, pn_equal);
+#if !MICROPY_EMIT_CPYTHON
+ // in Micro Python we put the default dict parameters into a dictionary using the bytecode
+ EMIT(store_map);
+#endif
}
} else {
comp->param_pass_num_default_params += 1;
@@ -922,6 +930,13 @@ qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint
comp->param_pass_num_default_params = 0;
apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
+#if !MICROPY_EMIT_CPYTHON
+ // in Micro Python we put the default positional parameters into a tuple using the bytecode
+ if (comp->param_pass_num_default_params > 0) {
+ EMIT_ARG(build_tuple, comp->param_pass_num_default_params);
+ }
+#endif
+
// get the scope for this function
scope_t *fscope = (scope_t*)pns->nodes[4];
@@ -1519,35 +1534,41 @@ void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
// TODO preload end and step onto stack if they are not constants
-// TODO check if step is negative and do opposite test
+// Note that, as per semantics of for .. range, the final failing value should not be stored in the loop variable
+// And, if the loop never runs, the loop variable should never be assigned
void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) {
START_BREAK_CONTINUE_BLOCK
int top_label = comp_next_label(comp);
int entry_label = comp_next_label(comp);
- // compile: var = start
+ // compile: start, duplicated on stack
compile_node(comp, pn_start);
- c_assign(comp, pn_var, ASSIGN_STORE);
+ EMIT(dup_top);
EMIT_ARG(jump, entry_label);
EMIT_ARG(label_assign, top_label);
+ // at this point we actually have 1 less element on the stack
+ EMIT_ARG(set_stack_size, EMIT(get_stack_size) - 1);
+
+ // store next value to var
+ c_assign(comp, pn_var, ASSIGN_STORE);
+
// compile body
compile_node(comp, pn_body);
EMIT_ARG(label_assign, continue_label);
- // compile: var += step
- c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
+ // compile: var + step, duplicated on stack
+ compile_node(comp, pn_var);
compile_node(comp, pn_step);
EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);
- c_assign(comp, pn_var, ASSIGN_AUG_STORE);
+ EMIT(dup_top);
EMIT_ARG(label_assign, entry_label);
// compile: if var <cond> end: goto top
- compile_node(comp, pn_var);
compile_node(comp, pn_end);
assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
@@ -1557,6 +1578,9 @@ void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var,
}
EMIT_ARG(pop_jump_if_true, top_label);
+ // discard final value of var that failed the loop condition
+ EMIT(pop_top);
+
// break/continue apply to outer loop (if any) in the else block
END_BREAK_CONTINUE_BLOCK
@@ -3327,7 +3351,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
#else
// return function that executes the outer module
// we can free the unique_code slot because no-one has reference to this unique_code_id anymore
- return mp_make_function_from_id(unique_code_id, true, MP_OBJ_NULL);
+ return mp_make_function_from_id(unique_code_id, true, MP_OBJ_NULL, MP_OBJ_NULL);
#endif
}
}
diff --git a/py/emitbc.c b/py/emitbc.c
index 595c7ac196..0a83448559 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -732,23 +732,38 @@ STATIC void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
}
STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
- assert(n_kw_defaults == 0);
- if (n_pos_defaults == 0) {
+ if (n_pos_defaults == 0 && n_kw_defaults == 0) {
emit_bc_pre(emit, 1);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
} else {
- emit_bc_pre(emit, 0);
+ if (n_pos_defaults == 0) {
+ // load dummy entry for non-existent positional default tuple
+ emit_bc_load_null(emit);
+ } else if (n_kw_defaults == 0) {
+ // load dummy entry for non-existent keyword default dict
+ emit_bc_load_null(emit);
+ emit_bc_rot_two(emit);
+ }
+ emit_bc_pre(emit, -1);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id);
}
}
STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
- assert(n_kw_defaults == 0);
- if (n_pos_defaults == 0) {
+ if (n_pos_defaults == 0 && n_kw_defaults == 0) {
emit_bc_pre(emit, 0);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
} else {
- emit_bc_pre(emit, -1);
+ if (n_pos_defaults == 0) {
+ // load dummy entry for non-existent positional default tuple
+ emit_bc_load_null(emit);
+ emit_bc_rot_two(emit);
+ } else if (n_kw_defaults == 0) {
+ // load dummy entry for non-existent keyword default dict
+ emit_bc_load_null(emit);
+ emit_bc_rot_three(emit);
+ }
+ emit_bc_pre(emit, -2);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->unique_code_id);
}
}
diff --git a/py/emitglue.c b/py/emitglue.c
index 73304de27a..dc084e159c 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -190,13 +190,16 @@ void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint le
#endif
}
-mp_obj_t mp_make_function_from_id(uint unique_code_id, bool free_unique_code, mp_obj_t def_args) {
+mp_obj_t mp_make_function_from_id(uint unique_code_id, bool free_unique_code, mp_obj_t def_args, mp_obj_t def_kw_args) {
DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
if (unique_code_id >= unique_codes_total) {
// illegal code id
return mp_const_none;
}
+ // TODO implement default kw args
+ assert(def_kw_args == MP_OBJ_NULL);
+
// make the function, depending on the code kind
mp_code_t *c = &unique_codes[unique_code_id];
mp_obj_t fun;
@@ -231,10 +234,10 @@ mp_obj_t mp_make_function_from_id(uint unique_code_id, bool free_unique_code, mp
return fun;
}
-mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args) {
+mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) {
DEBUG_OP_printf("make_closure_from_id %d\n", unique_code_id);
// make function object
- mp_obj_t ffun = mp_make_function_from_id(unique_code_id, false, def_args);
+ mp_obj_t ffun = mp_make_function_from_id(unique_code_id, false, def_args, def_kw_args);
// wrap function in closure object
return mp_obj_new_closure(ffun, closure_tuple);
}
diff --git a/py/emitnative.c b/py/emitnative.c
index 73851120ad..da0aa60381 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -1063,14 +1063,14 @@ STATIC void emit_native_build_tuple(emit_t *emit, int n_args) {
// if wrapped in byte_array, or something, allocates memory and fills it
emit_native_pre(emit);
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
- emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE, mp_build_tuple, n_args, REG_ARG_1);
+ emit_call_with_imm_arg(emit, MP_F_BUILD_TUPLE, mp_obj_new_tuple, n_args, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple
}
STATIC void emit_native_build_list(emit_t *emit, int n_args) {
emit_native_pre(emit);
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
- emit_call_with_imm_arg(emit, MP_F_BUILD_LIST, mp_build_list, n_args, REG_ARG_1);
+ emit_call_with_imm_arg(emit, MP_F_BUILD_LIST, mp_obj_new_list, n_args, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list
}
@@ -1081,13 +1081,13 @@ STATIC void emit_native_list_append(emit_t *emit, int list_index) {
emit_access_stack(emit, list_index, &vtype_list, REG_ARG_1);
assert(vtype_list == VTYPE_PYOBJ);
assert(vtype_item == VTYPE_PYOBJ);
- emit_call(emit, MP_F_LIST_APPEND, mp_list_append);
+ emit_call(emit, MP_F_LIST_APPEND, mp_obj_list_append);
emit_post(emit);
}
STATIC void emit_native_build_map(emit_t *emit, int n_args) {
emit_native_pre(emit);
- emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, mp_build_map, n_args, REG_ARG_1);
+ emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, mp_obj_new_dict, n_args, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new map
}
@@ -1097,7 +1097,7 @@ STATIC void emit_native_store_map(emit_t *emit) {
assert(vtype_key == VTYPE_PYOBJ);
assert(vtype_value == VTYPE_PYOBJ);
assert(vtype_map == VTYPE_PYOBJ);
- emit_call(emit, MP_F_STORE_MAP, mp_store_map);
+ emit_call(emit, MP_F_STORE_MAP, mp_obj_dict_store);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map
}
@@ -1109,14 +1109,14 @@ STATIC void emit_native_map_add(emit_t *emit, int map_index) {
assert(vtype_map == VTYPE_PYOBJ);
assert(vtype_key == VTYPE_PYOBJ);
assert(vtype_value == VTYPE_PYOBJ);
- emit_call(emit, MP_F_STORE_MAP, mp_store_map);
+ emit_call(emit, MP_F_STORE_MAP, mp_obj_dict_store);
emit_post(emit);
}
STATIC void emit_native_build_set(emit_t *emit, int n_args) {
emit_native_pre(emit);
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_args); // pointer to items
- emit_call_with_imm_arg(emit, MP_F_BUILD_SET, mp_build_set, n_args, REG_ARG_1);
+ emit_call_with_imm_arg(emit, MP_F_BUILD_SET, mp_obj_new_set, n_args, REG_ARG_1);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new set
}
@@ -1127,7 +1127,7 @@ STATIC void emit_native_set_add(emit_t *emit, int set_index) {
emit_access_stack(emit, set_index, &vtype_set, REG_ARG_1);
assert(vtype_set == VTYPE_PYOBJ);
assert(vtype_item == VTYPE_PYOBJ);
- emit_call(emit, MP_F_STORE_SET, mp_store_set);
+ emit_call(emit, MP_F_STORE_SET, mp_obj_set_store);
emit_post(emit);
}
diff --git a/py/objdict.c b/py/objdict.c
index 01c7294a46..afd1d0da0f 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -33,7 +33,7 @@ STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env
STATIC mp_obj_t dict_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// TODO create from an iterable!
- return mp_build_map(0);
+ return mp_obj_new_dict(0);
}
STATIC mp_obj_t dict_unary_op(int op, mp_obj_t self_in) {
diff --git a/py/objfun.c b/py/objfun.c
index 154630afb6..3b48b570fd 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -151,15 +151,17 @@ typedef struct _mp_obj_fun_bc_t {
mp_obj_t extra_args[]; // values of default args (if any), plus a slot at the end for var args and/or kw args (if it takes them)
} mp_obj_fun_bc_t;
-void dump_args(const mp_obj_t *a, int sz) {
#if DEBUG_PRINT
+STATIC void dump_args(const mp_obj_t *a, int sz) {
DEBUG_printf("%p: ", a);
for (int i = 0; i < sz; i++) {
DEBUG_printf("%p ", a[i]);
}
DEBUG_printf("\n");
-#endif
}
+#else
+#define dump_args(...) (void)0
+#endif
// If it's possible to call a function without allocating new argument array,
// this function returns true, together with pointers to 2 subarrays to be used
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 8f6bb17cfd..78694c866b 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -127,13 +127,16 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o
switch (mp_obj_gen_resume(self_in, send_value, throw_value, &ret)) {
case MP_VM_RETURN_NORMAL:
// Optimize return w/o value in case generator is used in for loop
- if (ret == mp_const_none) {
+ if (ret == mp_const_none || ret == MP_OBJ_NULL) {
return MP_OBJ_NULL;
} else {
nlr_jump(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret));
}
case MP_VM_RETURN_YIELD:
+ if (throw_value != MP_OBJ_NULL && mp_obj_is_subclass_fast(mp_obj_get_type(throw_value), &mp_type_GeneratorExit)) {
+ nlr_jump(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"));
+ }
return ret;
case MP_VM_RETURN_EXCEPTION:
@@ -171,13 +174,6 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in);
STATIC mp_obj_t gen_instance_throw(uint n_args, const mp_obj_t *args) {
mp_obj_t exc = (n_args == 2) ? args[1] : args[2];
exc = mp_make_raise_obj(exc);
- if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_GeneratorExit)) {
- // Throwing GeneratorExit is equivalent of calling close aka
- // GeneratorExit should be handled specially
- // TODO: Calling .close() will throw new exception instance, not one
- // given to throw, which is not ok.
- return gen_instance_close(args[0]);
- }
mp_obj_t ret = gen_resume_and_raise(args[0], mp_const_none, exc);
if (ret == MP_OBJ_NULL) {
diff --git a/py/objstr.c b/py/objstr.c
index 751f93afd7..2ca2248b24 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -372,7 +372,7 @@ STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) {
while (s < top && splits != 0) {
start = s;
while (s < top && !is_ws(*s)) s++;
- mp_list_append(res, mp_obj_new_str(start, s - start, false));
+ mp_obj_list_append(res, mp_obj_new_str(start, s - start, false));
if (s >= top) {
break;
}
@@ -383,7 +383,7 @@ STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) {
}
if (s < top) {
- mp_list_append(res, mp_obj_new_str(s, top - s, false));
+ mp_obj_list_append(res, mp_obj_new_str(s, top - s, false));
}
return res;
diff --git a/py/objtype.c b/py/objtype.c
index 1275124803..ee3ce12abe 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -297,6 +297,10 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj
STATIC void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
mp_obj_type_t *self = self_in;
+ if (attr == MP_QSTR___name__) {
+ dest[0] = MP_OBJ_NEW_QSTR(self->name);
+ return;
+ }
mp_obj_t member = mp_obj_class_lookup(self, attr);
if (member != MP_OBJ_NULL) {
// check if the methods are functions, static or class methods
diff --git a/py/runtime.c b/py/runtime.c
index f827fd831e..daa555e4a2 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -72,10 +72,6 @@ void mp_deinit(void) {
mp_emit_glue_deinit();
}
-mp_obj_t mp_list_append(mp_obj_t self_in, mp_obj_t arg) {
- return mp_obj_list_append(self_in, arg);
-}
-
mp_obj_t mp_load_const_dec(qstr qstr) {
DEBUG_OP_printf("load '%s'\n", qstr_str(qstr));
uint len;
@@ -136,14 +132,6 @@ mp_obj_t mp_load_build_class(void) {
}
}
-mp_obj_t mp_get_cell(mp_obj_t cell) {
- return mp_obj_cell_get(cell);
-}
-
-void mp_set_cell(mp_obj_t cell, mp_obj_t val) {
- mp_obj_cell_set(cell, val);
-}
-
void mp_store_name(qstr qstr, mp_obj_t obj) {
DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = obj;
@@ -656,23 +644,6 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_
return res;
}
-mp_obj_t mp_build_tuple(int n_args, mp_obj_t *items) {
- return mp_obj_new_tuple(n_args, items);
-}
-
-mp_obj_t mp_build_list(int n_args, mp_obj_t *items) {
- return mp_obj_new_list(n_args, items);
-}
-
-mp_obj_t mp_build_set(int n_args, mp_obj_t *items) {
- return mp_obj_new_set(n_args, items);
-}
-
-mp_obj_t mp_store_set(mp_obj_t set, mp_obj_t item) {
- mp_obj_set_store(set, item);
- return set;
-}
-
// unpacked items are stored in reverse order into the array pointed to by items
void mp_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
uint seq_len;
@@ -713,15 +684,6 @@ too_long:
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
}
-mp_obj_t mp_build_map(int n_args) {
- return mp_obj_new_dict(n_args);
-}
-
-mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value) {
- // map should always be a dict
- return mp_obj_dict_store(map, key, value);
-}
-
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
// use load_method
@@ -915,6 +877,7 @@ mp_obj_t mp_iternext(mp_obj_t o_in) {
// TODO: Unclear what to do with StopIterarion exception here.
mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
+ assert((send_value != MP_OBJ_NULL) ^ (throw_value != MP_OBJ_NULL));
mp_obj_type_t *type = mp_obj_get_type(self_in);
if (type == &mp_type_gen_instance) {
@@ -960,9 +923,20 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
return MP_VM_RETURN_NORMAL;
}
}
- mp_load_method(self_in, MP_QSTR_throw, dest);
- *ret_val = mp_call_method_n_kw(1, 0, &throw_value);
- return MP_VM_RETURN_YIELD;
+ mp_load_method_maybe(self_in, MP_QSTR_throw, dest);
+ if (dest[0] != MP_OBJ_NULL) {
+ *ret_val = mp_call_method_n_kw(1, 0, &throw_value);
+ // If .throw() method returned, we assume it's value to yield
+ // - any exception would be thrown with nlr_jump().
+ return MP_VM_RETURN_YIELD;
+ }
+ // If there's nowhere to throw exception into, then we assume that object
+ // is just incapable to handle it, so any exception thrown into it
+ // 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;
+ return MP_VM_RETURN_EXCEPTION;
}
assert(0);
@@ -1057,13 +1031,13 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_obj_is_true,
mp_unary_op,
mp_binary_op,
- mp_build_tuple,
- mp_build_list,
- mp_list_append,
- mp_build_map,
- mp_store_map,
- mp_build_set,
- mp_store_set,
+ mp_obj_new_tuple,
+ mp_obj_new_list,
+ mp_obj_list_append,
+ mp_obj_new_dict,
+ mp_obj_dict_store,
+ mp_obj_new_set,
+ mp_obj_set_store,
mp_make_function_from_id,
mp_call_function_n_kw_for_native,
mp_call_method_n_kw,
diff --git a/py/runtime.h b/py/runtime.h
index d71e045b01..b817d61aec 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -28,14 +28,11 @@ mp_obj_t mp_load_const_dec(qstr qstr);
mp_obj_t mp_load_const_str(qstr qstr);
mp_obj_t mp_load_const_bytes(qstr qstr);
-mp_obj_t mp_get_cell(mp_obj_t cell);
-void mp_set_cell(mp_obj_t cell, mp_obj_t val);
-
-mp_obj_t mp_make_function_from_id(uint unique_code_id, bool free_unique_code, mp_obj_t def_args);
+mp_obj_t mp_make_function_from_id(uint unique_code_id, bool free_unique_code, mp_obj_t def_args, mp_obj_t def_kw_args);
mp_obj_t mp_make_function_n(int n_args, void *fun); // fun must have the correct signature for n_args fixed arguments
mp_obj_t mp_make_function_var(int n_args_min, mp_fun_var_t fun);
mp_obj_t mp_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive
-mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args);
+mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args);
mp_obj_t mp_call_function_0(mp_obj_t fun);
mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);
@@ -45,13 +42,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun, uint n_args, uint n_kw, const mp_ob
mp_obj_t mp_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_t *args);
-mp_obj_t mp_build_tuple(int n_args, mp_obj_t *items);
-mp_obj_t mp_build_list(int n_args, mp_obj_t *items);
-mp_obj_t mp_list_append(mp_obj_t list, mp_obj_t arg);
-mp_obj_t mp_build_set(int n_args, mp_obj_t *items);
-mp_obj_t mp_store_set(mp_obj_t set, mp_obj_t item);
void mp_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items);
-mp_obj_t mp_build_map(int n_args);
mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
diff --git a/py/vm.c b/py/vm.c
index 599a1d862e..69f350f9fd 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -243,7 +243,7 @@ dispatch_loop:
case MP_BC_LOAD_DEREF:
DECODE_UINT;
- PUSH(mp_get_cell(fastn[-unum]));
+ PUSH(mp_obj_cell_get(fastn[-unum]));
break;
case MP_BC_LOAD_NAME:
@@ -290,7 +290,7 @@ dispatch_loop:
case MP_BC_STORE_DEREF:
DECODE_UINT;
- mp_set_cell(fastn[-unum], POP());
+ mp_obj_cell_set(fastn[-unum], POP());
break;
case MP_BC_STORE_NAME:
@@ -580,49 +580,49 @@ unwind_jump:
case MP_BC_BUILD_TUPLE:
DECODE_UINT;
sp -= unum - 1;
- SET_TOP(mp_build_tuple(unum, sp));
+ SET_TOP(mp_obj_new_tuple(unum, sp));
break;
case MP_BC_BUILD_LIST:
DECODE_UINT;
sp -= unum - 1;
- SET_TOP(mp_build_list(unum, sp));
+ SET_TOP(mp_obj_new_list(unum, sp));
break;
case MP_BC_LIST_APPEND:
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[unum] is a list
- mp_list_append(sp[-unum], sp[0]);
+ mp_obj_list_append(sp[-unum], sp[0]);
sp--;
break;
case MP_BC_BUILD_MAP:
DECODE_UINT;
- PUSH(mp_build_map(unum));
+ PUSH(mp_obj_new_dict(unum));
break;
case MP_BC_STORE_MAP:
sp -= 2;
- mp_store_map(sp[0], sp[2], sp[1]);
+ mp_obj_dict_store(sp[0], sp[2], sp[1]);
break;
case MP_BC_MAP_ADD:
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[-unum - 1] is a map
- mp_store_map(sp[-unum - 1], sp[0], sp[-1]);
+ mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]);
sp -= 2;
break;
case MP_BC_BUILD_SET:
DECODE_UINT;
sp -= unum - 1;
- SET_TOP(mp_build_set(unum, sp));
+ SET_TOP(mp_obj_new_set(unum, sp));
break;
case MP_BC_SET_ADD:
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[-unum] is a set
- mp_store_set(sp[-unum], sp[0]);
+ mp_obj_set_store(sp[-unum], sp[0]);
sp--;
break;
@@ -648,23 +648,28 @@ unwind_jump:
case MP_BC_MAKE_FUNCTION:
DECODE_UINT;
- PUSH(mp_make_function_from_id(unum, false, MP_OBJ_NULL));
+ PUSH(mp_make_function_from_id(unum, false, MP_OBJ_NULL, MP_OBJ_NULL));
break;
case MP_BC_MAKE_FUNCTION_DEFARGS:
DECODE_UINT;
- SET_TOP(mp_make_function_from_id(unum, false, TOP()));
+ // Stack layout: def_dict def_tuple <- TOS
+ obj1 = POP();
+ SET_TOP(mp_make_function_from_id(unum, false, obj1, TOP()));
break;
case MP_BC_MAKE_CLOSURE:
DECODE_UINT;
- SET_TOP(mp_make_closure_from_id(unum, TOP(), MP_OBJ_NULL));
+ // Stack layout: closure_tuple <- TOS
+ SET_TOP(mp_make_closure_from_id(unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL));
break;
case MP_BC_MAKE_CLOSURE_DEFARGS:
DECODE_UINT;
+ // Stack layout: def_dict def_tuple closure_tuple <- TOS
obj1 = POP();
- SET_TOP(mp_make_closure_from_id(unum, obj1, TOP()));
+ obj2 = POP();
+ SET_TOP(mp_make_closure_from_id(unum, obj1, obj2, TOP()));
break;
case MP_BC_CALL_FUNCTION:
@@ -764,7 +769,7 @@ yield:
if (inject_exc != MP_OBJ_NULL) {
t_exc = inject_exc;
inject_exc = MP_OBJ_NULL;
- ret_kind = mp_resume(TOP(), mp_const_none, t_exc, &obj2);
+ ret_kind = mp_resume(TOP(), MP_OBJ_NULL, t_exc, &obj2);
} else {
ret_kind = mp_resume(TOP(), obj1, MP_OBJ_NULL, &obj2);
}
diff --git a/py/vstr.c b/py/vstr.c
index 032acc61bc..4fc4326e23 100644
--- a/py/vstr.c
+++ b/py/vstr.c
@@ -10,6 +10,10 @@
#define ROUND_ALLOC(a) (((a) & ((~0) - 7)) + 8)
void vstr_init(vstr_t *vstr, int alloc) {
+ if (alloc < 2) {
+ // need at least 1 byte for the null byte at the end
+ alloc = 2;
+ }
vstr->alloc = alloc;
vstr->len = 0;
vstr->buf = m_new(char, vstr->alloc);
diff --git a/stm/accel.c b/stm/accel.c
index c55bc6ba2d..99ce9b0636 100644
--- a/stm/accel.c
+++ b/stm/accel.c
@@ -268,7 +268,7 @@ mp_obj_t pyb_accel_read(void) {
data[2] = mp_obj_new_int(accel_buf[2] + accel_buf[5] + accel_buf[8] + accel_buf[11]);
data[3] = mp_obj_new_int(jolt_info);
- return mp_build_tuple(4, data);
+ return mp_obj_new_tuple(4, data);
}
MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_obj, pyb_accel_read);
@@ -283,7 +283,7 @@ mp_obj_t pyb_accel_read_all(void) {
}
data[10] = mp_obj_new_int(accel_read_nack());
- return mp_build_tuple(11, data);
+ return mp_obj_new_tuple(11, data);
}
MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_all_obj, pyb_accel_read_all);
diff --git a/stmhal/accel.c b/stmhal/accel.c
index ffccddc861..e8b73cdfba 100644
--- a/stmhal/accel.c
+++ b/stmhal/accel.c
@@ -134,7 +134,7 @@ STATIC mp_obj_t pyb_accel_filtered_xyz(mp_obj_t self_in) {
tuple[i] = mp_obj_new_int(val);
}
- return mp_build_tuple(3, tuple);
+ return mp_obj_new_tuple(3, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_filtered_xyz_obj, pyb_accel_filtered_xyz);
diff --git a/tests/basics/class_inherit_mul.py b/tests/basics/class_inherit_mul.py
new file mode 100644
index 0000000000..23476132ba
--- /dev/null
+++ b/tests/basics/class_inherit_mul.py
@@ -0,0 +1,37 @@
+class A:
+ def __init__(self, x):
+ print('A init', x)
+ self.x = x
+
+ def f(self):
+ print(self.x)
+
+ def f2(self):
+ print(self.x)
+
+class B:
+ def __init__(self, x):
+ print('B init', x)
+ self.x = x
+
+ def f(self):
+ print(self.x)
+
+ def f3(self):
+ print(self.x)
+
+
+class Sub(A, B):
+ def __init__(self):
+ A.__init__(self, 1)
+ B.__init__(self, 2)
+ print('Sub init')
+
+ def g(self):
+ print(self.x)
+
+o = Sub()
+print(o.x)
+o.f()
+o.f2()
+o.f3()
diff --git a/tests/basics/for2.py b/tests/basics/for2.py
new file mode 100644
index 0000000000..62f056e760
--- /dev/null
+++ b/tests/basics/for2.py
@@ -0,0 +1,8 @@
+i = 'init'
+for i in range(0):
+ pass
+print(i) # should not have been modified
+
+for i in range(10):
+ pass
+print(i) # should be last successful value of loop
diff --git a/tests/misc/features.py b/tests/misc/features.py
new file mode 100644
index 0000000000..d2fd8865c3
--- /dev/null
+++ b/tests/misc/features.py
@@ -0,0 +1,159 @@
+# mad.py
+# Alf Clement 27-Mar-2014
+#
+zero=0
+three=3
+print("1")
+print("2")
+print(three)
+print("{}".format(4))
+five=25/5
+print(int(five))
+j=0
+for i in range(4):
+ j += i
+print(j)
+print(3+4)
+try:
+ a=4/zero
+except:
+ print(8)
+print("xxxxxxxxx".count("x"))
+def ten():
+ return 10
+print(ten())
+a=[]
+for i in range(13):
+ a.append(i)
+print(a[11])
+print(a[-1])
+str="0123456789"
+print(str[1]+str[3])
+def p(s):
+ print(s)
+p("14")
+p(15)
+class A:
+ def __init__(self):
+ self.a=16
+ def print(self):
+ print(self.a)
+ def set(self,b):
+ self.a=b
+a=A()
+a.print()
+a.set(17)
+a.print()
+b=A()
+b.set(a.a + 1)
+b.print()
+for i in range(20):
+ pass
+print(i)
+if 20 > 30:
+ a="1"
+else:
+ a="2"
+if 0 < 4:
+ print(a+"0")
+else:
+ print(a+"1")
+a=[20,21,22,23,24]
+for i in a:
+ if i < 21:
+ continue
+ if i > 21:
+ break
+ print(i)
+b=[a,a,a]
+print(b[1][2])
+print(161//7)
+a=24
+while True:
+ try:
+ def gcheck():
+ global a
+ print(a)
+ gcheck()
+ class c25():
+ x=25
+ x=c25()
+ print(x.x)
+ raise
+ except:
+ print(26)
+ print(27+zero)
+ break
+print(28)
+k=29
+def f():
+ global k
+ k = yield k
+print(next(f()))
+while True:
+ k+= 1
+ if k < 30:
+ continue
+ break
+print(k)
+for i in [1,2,3]:
+ class A():
+ def __init__(self, c):
+ self.a = i+10*c
+ b = A(3)
+ print(b.a)
+print(34)
+p=0
+for i in range(35, -1, -1):
+ print(i)
+ p = p + 1
+ if p > 0:
+ break
+p=36
+while p == 36:
+ print(p)
+ p=37
+print(p)
+for i in [38]:
+ print(i)
+print(int(exec("def foo(): return 38") == None)+foo())
+d = {}
+exec("def bar(): return 40", d)
+print(d["bar"]())
+def fib2(n):
+ result = []
+ a, b = 0, 1
+ while a < n:
+ result.append(a)
+ a, b = b, a+b
+ return result
+print(fib2(100)[-2]-14)
+Answer={}
+Answer["ForAll"]=42
+print(Answer["ForAll"])
+i = 43
+def f(i=i):
+ print(i)
+i = 44
+f()
+print(i)
+while True:
+ try:
+ if None != True:
+ print(45)
+ break
+ else:
+ print(0)
+ except:
+ print(0)
+print(46)
+print(46+1)
+def u(p):
+ if p > 3:
+ return 3*p
+ else:
+ return u(2*p)-3*u(p)
+print(u(16))
+def u49():
+ return 49
+print(u49())
diff --git a/unix/main.c b/unix/main.c
index 959499ac34..57eaa19976 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -377,7 +377,7 @@ int main(int argc, char **argv) {
free(basedir);
}
for (int i = a; i < argc; i++) {
- mp_list_append(py_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
+ mp_obj_list_append(py_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
}
do_file(argv[a]);
executed = true;
diff --git a/unix/socket.c b/unix/socket.c
index 113b657fff..915400e442 100644
--- a/unix/socket.c
+++ b/unix/socket.c
@@ -313,7 +313,7 @@ static mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
}
assert(addr);
- mp_obj_t list = mp_build_list(0, NULL);
+ mp_obj_t list = mp_obj_new_list(0, NULL);
for (; addr; addr = addr->ai_next) {
mp_obj_tuple_t *t = mp_obj_new_tuple(5, NULL);
t->items[0] = MP_OBJ_NEW_SMALL_INT((machine_int_t)addr->ai_family);
@@ -327,7 +327,7 @@ static mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
t->items[3] = mp_const_none;
}
t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr);
- mp_list_append(list, t);
+ mp_obj_list_append(list, t);
}
return list;
}
diff --git a/windows/main.c b/windows/main.c
index 8ba5ebc672..59174d73df 100644
--- a/windows/main.c
+++ b/windows/main.c
@@ -217,7 +217,7 @@ int main(int argc, char **argv) {
}
} else {
for (int i = a; i < argc; i++) {
- mp_list_append(py_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
+ mp_obj_list_append(py_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
}
do_file(argv[a]);
break;