diff options
Diffstat (limited to 'py/compile.c')
-rw-r--r-- | py/compile.c | 54 |
1 files changed, 39 insertions, 15 deletions
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 } } |