diff options
Diffstat (limited to 'py/compile.c')
-rw-r--r-- | py/compile.c | 105 |
1 files changed, 66 insertions, 39 deletions
diff --git a/py/compile.c b/py/compile.c index 2110867291..42c2cc3a24 100644 --- a/py/compile.c +++ b/py/compile.c @@ -115,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 @@ -762,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(...):") @@ -836,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]); } } @@ -2175,36 +2172,83 @@ 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_generic_all_nodes(comp, pns); -} + // compile_atom_expr_await may call us with a NULL node + if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { + return; + } -STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) { - compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power - EMIT_ARG(binary_op, MP_BINARY_OP_POWER); -} + // 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]; + } -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 + // the current index into the array of trailers + size_t i = 0; - // 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) { + // 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") - for (int i = 0; i < comp->scope_cur->id_info_len; i++) { - id_info_t *id = &comp->scope_cur->id_info[i]; + 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 and call super + // first argument found; load it compile_load_id(comp, id->qst); - EMIT_ARG(call_function, 2, 0, 0); - return; + found = true; + break; } } - compile_syntax_error(comp, MP_PARSE_NODE_NULL, "super() call cannot find self"); // really a TypeError - return; + if (!found) { + compile_syntax_error(comp, (mp_parse_node_t)pns_trail[0], + "super() can't find self"); // really a TypeError + return; + } + + // 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])); + 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) { + compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power + EMIT_ARG(binary_op, MP_BINARY_OP_POWER); +} + +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 // get the list of arguments mp_parse_node_t *args; @@ -2285,23 +2329,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; - } -} - // 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); |