diff options
Diffstat (limited to 'py/compile.c')
-rw-r--r-- | py/compile.c | 323 |
1 files changed, 159 insertions, 164 deletions
diff --git a/py/compile.c b/py/compile.c index b84793d10..8533e0528 100644 --- a/py/compile.c +++ b/py/compile.c @@ -41,13 +41,19 @@ // TODO need to mangle __attr names typedef enum { +// define rules with a compile function #define DEF_RULE(rule, comp, kind, ...) PN_##rule, +#define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" #undef DEF_RULE - PN_maximum_number_of, - PN_string, // special node for non-interned string - PN_bytes, // special node for non-interned bytes +#undef DEF_RULE_NC PN_const_object, // special node for a constant, generic Python object +// define rules without a compile function +#define DEF_RULE(rule, comp, kind, ...) +#define DEF_RULE_NC(rule, kind, ...) PN_##rule, +#include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC } pn_kind_t; #define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE @@ -109,7 +115,6 @@ typedef struct _compiler_t { uint8_t is_repl; uint8_t pass; // holds enum type pass_kind_t - uint8_t func_arg_is_super; // used to compile special case of super() function call uint8_t have_star; // try to keep compiler clean from nlr @@ -450,8 +455,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_ break; } } else { - compile_syntax_error(comp, pn, "can't assign to literal"); - return; + goto cannot_assign; } } else { // pn must be a struct @@ -466,7 +470,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_ case PN_exprlist: // lhs is a tuple if (assign_kind != ASSIGN_STORE) { - goto bad_aug; + goto cannot_assign; } c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes); break; @@ -479,7 +483,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_ } else { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)); if (assign_kind != ASSIGN_STORE) { - goto bad_aug; + goto cannot_assign; } pns = (mp_parse_node_struct_t*)pns->nodes[0]; goto testlist_comp; @@ -489,7 +493,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_ case PN_atom_bracket: // lhs is something in brackets if (assign_kind != ASSIGN_STORE) { - goto bad_aug; + goto cannot_assign; } if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty list, assignment allowed @@ -537,10 +541,6 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_ cannot_assign: compile_syntax_error(comp, pn, "can't assign to expression"); - return; - - bad_aug: - compile_syntax_error(comp, pn, "illegal expression for augmented assignment"); } // stuff for lambda and comprehensions and generators: @@ -585,8 +585,16 @@ STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int } STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) { - if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star) - || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_star)) { + // For efficiency of the code below we extract the parse-node kind here + int pn_kind; + if (MP_PARSE_NODE_IS_ID(pn)) { + pn_kind = -1; + } else { + assert(MP_PARSE_NODE_IS_STRUCT(pn)); + pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn); + } + + if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) { comp->have_star = true; /* don't need to distinguish bare from named star mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; @@ -597,8 +605,7 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) } */ - } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star) - || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_dbl_star)) { + } else if (pn_kind == PN_typedargslist_dbl_star || pn_kind == PN_varargslist_dbl_star) { // named double star // TODO do we need to do anything with this? @@ -606,14 +613,14 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) mp_parse_node_t pn_id; mp_parse_node_t pn_colon; mp_parse_node_t pn_equal; - if (MP_PARSE_NODE_IS_ID(pn)) { + if (pn_kind == -1) { // this parameter is just an id pn_id = pn; pn_colon = MP_PARSE_NODE_NULL; pn_equal = MP_PARSE_NODE_NULL; - } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) { + } else if (pn_kind == PN_typedargslist_name) { // this parameter has a colon and/or equal specifier mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; @@ -622,7 +629,7 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) pn_equal = pns->nodes[2]; } else { - assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_name)); // should be + assert(pn_kind == PN_varargslist_name); // should be // this parameter has an equal specifier mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; @@ -754,7 +761,6 @@ STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pn if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) { parents = MP_PARSE_NODE_NULL; } - comp->func_arg_is_super = false; compile_trailer_paren_helper(comp, parents, false, 2); // return its name (the 'C' in class C(...):") @@ -828,7 +834,6 @@ STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) { // nodes[1] contains arguments to the decorator function, if any if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) { // call the decorator function with the arguments in nodes[1] - comp->func_arg_is_super = false; compile_node(comp, pns_decorator->nodes[1]); } } @@ -972,7 +977,8 @@ STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // no argument to 'return', so return None EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); - } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) { + } else if (MICROPY_COMP_RETURN_IF_EXPR + && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) { // special case when returning an if-expression; to match CPython optimisation mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0]; mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1]; @@ -1421,7 +1427,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1]; if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range - && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)) { + && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pns_it->nodes[1]) == PN_trailer_paren) { mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0]; mp_parse_node_t *args; int n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args); @@ -1443,8 +1449,9 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { pn_range_start = args[0]; pn_range_end = args[1]; pn_range_step = args[2]; - // We need to know sign of step. This is possible only if it's constant - if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) { + // the step must be a non-zero constant integer to do the optimisation + if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step) + || MP_PARSE_NODE_LEAF_SMALL_INT(pn_range_step) == 0) { optimize = false; } } @@ -1475,7 +1482,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { uint pop_label = comp_next_label(comp); compile_node(comp, pns->nodes[1]); // iterator - EMIT(get_iter); + EMIT_ARG(get_iter, true); EMIT_ARG(label_assign, continue_label); EMIT_ARG(for_iter, pop_label); c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable @@ -1523,7 +1530,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) { // this is a catch all exception handler if (i + 1 != n_except) { - compile_syntax_error(comp, pn_excepts[i], "default 'except:' must be last"); + compile_syntax_error(comp, pn_excepts[i], "default 'except' must be last"); compile_decrease_except_level(comp); return; } @@ -1680,14 +1687,14 @@ STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } STATIC void compile_yield_from(compiler_t *comp) { - EMIT(get_iter); + EMIT_ARG(get_iter, false); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT(yield_from); } #if MICROPY_PY_ASYNC_AWAIT STATIC void compile_await_object_method(compiler_t *comp, qstr method) { - EMIT_ARG(load_method, method); + EMIT_ARG(load_method, method, false); EMIT_ARG(call_method, 0, 0, 0); compile_yield_from(comp); } @@ -1778,7 +1785,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod } compile_load_id(comp, context); - EMIT_ARG(load_method, MP_QSTR___aexit__); + EMIT_ARG(load_method, MP_QSTR___aexit__, false); EMIT_ARG(setup_except, try_exception_label); compile_increase_except_level(comp); @@ -1872,8 +1879,6 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } else { // for non-REPL, evaluate then discard the expression if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_bytes) || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) { // do nothing with a lonely constant } else { @@ -2167,10 +2172,85 @@ STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) { } STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) { - // this is to handle special super() call - comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super; + // compile the subject of the expression + compile_node(comp, pns->nodes[0]); + + // compile_atom_expr_await may call us with a NULL node + if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { + return; + } + + // get the array of trailers (known to be an array of PARSE_NODE_STRUCT) + size_t num_trail = 1; + mp_parse_node_struct_t **pns_trail = (mp_parse_node_struct_t**)&pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_atom_expr_trailers) { + num_trail = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_trail[0]); + pns_trail = (mp_parse_node_struct_t**)&pns_trail[0]->nodes[0]; + } + + // the current index into the array of trailers + size_t i = 0; + + // handle special super() call + if (comp->scope_cur->kind == SCOPE_FUNCTION + && MP_PARSE_NODE_IS_ID(pns->nodes[0]) + && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super + && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren + && MP_PARSE_NODE_IS_NULL(pns_trail[0]->nodes[0])) { + // at this point we have matched "super()" within a function + + // load the class for super to search for a parent + compile_load_id(comp, MP_QSTR___class__); + + // look for first argument to function (assumes it's "self") + bool found = false; + id_info_t *id = &comp->scope_cur->id_info[0]; + for (size_t n = comp->scope_cur->id_info_len; n > 0; --n, ++id) { + if (id->flags & ID_FLAG_IS_PARAM) { + // first argument found; load it + compile_load_id(comp, id->qst); + found = true; + break; + } + } + if (!found) { + compile_syntax_error(comp, (mp_parse_node_t)pns_trail[0], + "super() can't find self"); // really a TypeError + return; + } - compile_generic_all_nodes(comp, pns); + if (num_trail >= 3 + && MP_PARSE_NODE_STRUCT_KIND(pns_trail[1]) == PN_trailer_period + && MP_PARSE_NODE_STRUCT_KIND(pns_trail[2]) == PN_trailer_paren) { + // optimisation for method calls super().f(...), to eliminate heap allocation + mp_parse_node_struct_t *pns_period = pns_trail[1]; + mp_parse_node_struct_t *pns_paren = pns_trail[2]; + EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), true); + compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0); + i = 3; + } else { + // a super() call + EMIT_ARG(call_function, 2, 0, 0); + i = 1; + } + } + + // compile the remaining trailers + for (; i < num_trail; i++) { + if (i + 1 < num_trail + && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i]) == PN_trailer_period + && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i + 1]) == PN_trailer_paren) { + // optimisation for method calls a.f(...), following PyPy + mp_parse_node_struct_t *pns_period = pns_trail[i]; + mp_parse_node_struct_t *pns_paren = pns_trail[i + 1]; + EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false); + compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0); + i += 1; + } else { + // node is one of: trailer_paren, trailer_bracket, trailer_period + compile_node(comp, (mp_parse_node_t)pns_trail[i]); + } + } } STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) { @@ -2181,22 +2261,6 @@ STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) { STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) { // function to call is on top of stack - // this is to handle special super() call - if (MP_PARSE_NODE_IS_NULL(pn_arglist) && comp->func_arg_is_super && comp->scope_cur->kind == SCOPE_FUNCTION) { - compile_load_id(comp, MP_QSTR___class__); - // look for first argument to function (assumes it's "self") - for (int i = 0; i < comp->scope_cur->id_info_len; i++) { - if (comp->scope_cur->id_info[i].flags & ID_FLAG_IS_PARAM) { - // first argument found; load it and call super - EMIT_LOAD_FAST(MP_QSTR_, comp->scope_cur->id_info[i].local_num); - EMIT_ARG(call_function, 2, 0, 0); - return; - } - } - compile_syntax_error(comp, MP_PARSE_NODE_NULL, "super() call cannot find self"); // really a TypeError - return; - } - // get the list of arguments mp_parse_node_t *args; int n_args = mp_parse_node_extract_list(&pn_arglist, PN_arglist, &args); @@ -2276,82 +2340,6 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar } } -STATIC void compile_atom_expr_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) { - int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); - for (int i = 0; i < num_nodes; i++) { - if (i + 1 < num_nodes && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i], PN_trailer_period) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i + 1], PN_trailer_paren)) { - // optimisation for method calls a.f(...), following PyPy - mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i]; - mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1]; - EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method - compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0); - i += 1; - } else { - compile_node(comp, pns->nodes[i]); - } - comp->func_arg_is_super = false; - } -} - -STATIC void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) { - // a list of strings - - // check type of list (string or bytes) and count total number of bytes - int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); - size_t n_bytes = 0; - int string_kind = MP_PARSE_NODE_NULL; - for (int i = 0; i < n; i++) { - int pn_kind; - if (MP_PARSE_NODE_IS_LEAF(pns->nodes[i])) { - pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]); - assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES); - n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); - } else { - assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])); - mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i]; - if (MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_string) { - pn_kind = MP_PARSE_NODE_STRING; - } else { - assert(MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_bytes); - pn_kind = MP_PARSE_NODE_BYTES; - } - n_bytes += pns_string->nodes[1]; - } - if (i == 0) { - string_kind = pn_kind; - } else if (pn_kind != string_kind) { - compile_syntax_error(comp, (mp_parse_node_t)pns, "cannot mix bytes and nonbytes literals"); - return; - } - } - - // if we are not in the last pass, just load a dummy object - if (comp->pass != MP_PASS_EMIT) { - EMIT_ARG(load_const_obj, mp_const_none); - return; - } - - // concatenate string/bytes - vstr_t vstr; - vstr_init_len(&vstr, n_bytes); - byte *s_dest = (byte*)vstr.buf; - for (int i = 0; i < n; i++) { - if (MP_PARSE_NODE_IS_LEAF(pns->nodes[i])) { - size_t s_len; - const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len); - memcpy(s_dest, s, s_len); - s_dest += s_len; - } else { - mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i]; - memcpy(s_dest, (const char*)pns_string->nodes[0], pns_string->nodes[1]); - s_dest += pns_string->nodes[1]; - } - } - - // load the object - EMIT_ARG(load_const_obj, mp_obj_new_str_from_vstr(string_kind == MP_PARSE_NODE_STRING ? &mp_type_str : &mp_type_bytes, &vstr)); -} - // pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) { assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2); @@ -2372,7 +2360,9 @@ STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, close_over_variables_etc(comp, this_scope, 0, 0); compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator - EMIT(get_iter); + if (kind == SCOPE_GEN_EXPR) { + EMIT_ARG(get_iter, false); + } EMIT_ARG(call_function, 1, 0, 0); } @@ -2490,13 +2480,21 @@ STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pn_i); if (is_dict) { if (!is_key_value) { - compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dictionary"); + if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { + compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax"); + } else { + compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dict"); + } return; } EMIT(store_map); } else { if (is_key_value) { - compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set"); + if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { + compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax"); + } else { + compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set"); + } return; } } @@ -2649,45 +2647,29 @@ STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pn } #endif -STATIC void compile_string(compiler_t *comp, mp_parse_node_struct_t *pns) { - // only create and load the actual str object on the last pass - if (comp->pass != MP_PASS_EMIT) { - EMIT_ARG(load_const_obj, mp_const_none); - } else { - EMIT_ARG(load_const_obj, mp_obj_new_str((const char*)pns->nodes[0], pns->nodes[1], false)); - } -} - -STATIC void compile_bytes(compiler_t *comp, mp_parse_node_struct_t *pns) { - // only create and load the actual bytes object on the last pass - if (comp->pass != MP_PASS_EMIT) { - EMIT_ARG(load_const_obj, mp_const_none); - } else { - EMIT_ARG(load_const_obj, mp_obj_new_bytes((const byte*)pns->nodes[0], pns->nodes[1])); - } -} - -STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) { +STATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) { #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D // nodes are 32-bit pointers, but need to extract 64-bit object - EMIT_ARG(load_const_obj, (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32)); + return (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32); #else - EMIT_ARG(load_const_obj, (mp_obj_t)pns->nodes[0]); + return (mp_obj_t)pns->nodes[0]; #endif } +STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) { + EMIT_ARG(load_const_obj, get_const_object(pns)); +} + typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*); STATIC const compile_function_t compile_function[] = { -#define nc NULL +// only define rules with a compile function #define c(f) compile_##f #define DEF_RULE(rule, comp, kind, ...) comp, +#define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" -#undef nc #undef c #undef DEF_RULE - NULL, - compile_string, - compile_bytes, +#undef DEF_RULE_NC compile_const_object, }; @@ -2741,8 +2723,8 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) { } else { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; EMIT_ARG(set_source_line, pns->source_line); + assert(MP_PARSE_NODE_STRUCT_KIND(pns) <= PN_const_object); compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)]; - assert(f != NULL); f(comp, pns); } } @@ -2887,20 +2869,20 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn EMIT(yield_value); EMIT(pop_top); } else { - EMIT_ARG(store_comp, comp->scope_cur->kind, for_depth + 2); + EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5); } - } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) { + } else if (MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_if) { // if condition mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter; c_if_cond(comp, pns_comp_if->nodes[0], false, l_top); pn_iter = pns_comp_if->nodes[1]; goto tail_recursion; } else { - assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)); // should be + assert(MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_for); // should be // for loop mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter; compile_node(comp, pns_comp_for2->nodes[1]); - EMIT(get_iter); + EMIT_ARG(get_iter, true); compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1); } @@ -2940,7 +2922,8 @@ STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING) - || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)) { + || (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object) + && MP_OBJ_IS_STR(get_const_object((mp_parse_node_struct_t*)pns->nodes[0])))) { // compile the doc string compile_node(comp, pns->nodes[0]); // store the doc string @@ -3070,7 +3053,19 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { #endif } - compile_load_id(comp, qstr_arg); + // There are 4 slots on the stack for the iterator, and the first one is + // NULL to indicate that the second one points to the iterator object. + if (scope->kind == SCOPE_GEN_EXPR) { + // TODO static assert that MP_OBJ_ITER_BUF_NSLOTS == 4 + EMIT(load_null); + compile_load_id(comp, qstr_arg); + EMIT(load_null); + EMIT(load_null); + } else { + compile_load_id(comp, qstr_arg); + EMIT_ARG(get_iter, true); + } + compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0); if (scope->kind == SCOPE_GEN_EXPR) { |