diff options
-rw-r--r-- | py/builtin.c | 2 | ||||
-rw-r--r-- | py/compile.c | 54 | ||||
-rw-r--r-- | py/emitbc.c | 27 | ||||
-rw-r--r-- | py/emitglue.c | 9 | ||||
-rw-r--r-- | py/emitnative.c | 16 | ||||
-rw-r--r-- | py/objdict.c | 2 | ||||
-rw-r--r-- | py/objfun.c | 6 | ||||
-rw-r--r-- | py/objgenerator.c | 12 | ||||
-rw-r--r-- | py/objstr.c | 4 | ||||
-rw-r--r-- | py/objtype.c | 4 | ||||
-rw-r--r-- | py/runtime.c | 70 | ||||
-rw-r--r-- | py/runtime.h | 13 | ||||
-rw-r--r-- | py/vm.c | 35 | ||||
-rw-r--r-- | py/vstr.c | 4 | ||||
-rw-r--r-- | stm/accel.c | 4 | ||||
-rw-r--r-- | stmhal/accel.c | 2 | ||||
-rw-r--r-- | tests/basics/class_inherit_mul.py | 37 | ||||
-rw-r--r-- | tests/basics/for2.py | 8 | ||||
-rw-r--r-- | tests/misc/features.py | 159 | ||||
-rw-r--r-- | unix/main.c | 2 | ||||
-rw-r--r-- | unix/socket.c | 4 | ||||
-rw-r--r-- | windows/main.c | 2 |
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); @@ -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); } @@ -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; |