summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-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
14 files changed, 138 insertions, 120 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);