diff options
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 203 |
1 files changed, 107 insertions, 96 deletions
diff --git a/Python/compile.c b/Python/compile.c index 1d16e69a08..9ed29f4a1f 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1007,10 +1007,6 @@ stack_effect(int opcode, int oparg, int jump) case BUILD_SET: case BUILD_STRING: return 1-oparg; - case BUILD_LIST_UNPACK: - case BUILD_TUPLE_UNPACK: - case BUILD_TUPLE_UNPACK_WITH_CALL: - case BUILD_SET_UNPACK: case BUILD_MAP_UNPACK: case BUILD_MAP_UNPACK_WITH_CALL: return 1 - oparg; @@ -1125,6 +1121,11 @@ stack_effect(int opcode, int oparg, int jump) return 1; case LOAD_ASSERTION_ERROR: return 1; + case LIST_TO_TUPLE: + return 0; + case LIST_EXTEND: + case SET_UPDATE: + return -1; default: return PY_INVALID_STACK_EFFECT; } @@ -1705,7 +1706,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, compiler_pop_fblock(c, POP_VALUE, NULL); } return 1; - + case FINALLY_END: if (preserve_tos) { ADDOP(c, ROT_FOUR); @@ -3675,11 +3676,11 @@ compiler_boolop(struct compiler *c, expr_ty e) } static int -starunpack_helper(struct compiler *c, asdl_seq *elts, - int single_op, int inner_op, int outer_op) +starunpack_helper(struct compiler *c, asdl_seq *elts, int pushed, + int build, int add, int extend, int tuple) { Py_ssize_t n = asdl_seq_LEN(elts); - Py_ssize_t i, nsubitems = 0, nseen = 0; + Py_ssize_t i, seen_star = 0; if (n > 2 && are_all_items_const(elts, 0, n)) { PyObject *folded = PyTuple_New(n); if (folded == NULL) { @@ -3691,41 +3692,63 @@ starunpack_helper(struct compiler *c, asdl_seq *elts, Py_INCREF(val); PyTuple_SET_ITEM(folded, i, val); } - if (outer_op == BUILD_SET_UNPACK) { - Py_SETREF(folded, PyFrozenSet_New(folded)); - if (folded == NULL) { - return 0; + if (tuple) { + ADDOP_LOAD_CONST_NEW(c, folded); + } else { + if (add == SET_ADD) { + Py_SETREF(folded, PyFrozenSet_New(folded)); + if (folded == NULL) { + return 0; + } } + ADDOP_I(c, build, pushed); + ADDOP_LOAD_CONST_NEW(c, folded); + ADDOP_I(c, extend, 1); } - ADDOP_LOAD_CONST_NEW(c, folded); - ADDOP_I(c, outer_op, 1); return 1; } + for (i = 0; i < n; i++) { expr_ty elt = asdl_seq_GET(elts, i); if (elt->kind == Starred_kind) { - if (nseen) { - ADDOP_I(c, inner_op, nseen); - nseen = 0; - nsubitems++; + seen_star = 1; + } + } + if (seen_star) { + seen_star = 0; + for (i = 0; i < n; i++) { + expr_ty elt = asdl_seq_GET(elts, i); + if (elt->kind == Starred_kind) { + if (seen_star == 0) { + ADDOP_I(c, build, i+pushed); + seen_star = 1; + } + VISIT(c, expr, elt->v.Starred.value); + ADDOP_I(c, extend, 1); + } + else { + VISIT(c, expr, elt); + if (seen_star) { + ADDOP_I(c, add, 1); + } } - VISIT(c, expr, elt->v.Starred.value); - nsubitems++; } - else { - VISIT(c, expr, elt); - nseen++; + assert(seen_star); + if (tuple) { + ADDOP(c, LIST_TO_TUPLE); } } - if (nsubitems) { - if (nseen) { - ADDOP_I(c, inner_op, nseen); - nsubitems++; + else { + for (i = 0; i < n; i++) { + expr_ty elt = asdl_seq_GET(elts, i); + VISIT(c, expr, elt); + } + if (tuple) { + ADDOP_I(c, BUILD_TUPLE, n+pushed); + } else { + ADDOP_I(c, build, n+pushed); } - ADDOP_I(c, outer_op, nsubitems); } - else - ADDOP_I(c, single_op, nseen); return 1; } @@ -3767,8 +3790,8 @@ compiler_list(struct compiler *c, expr_ty e) return assignment_helper(c, elts); } else if (e->v.List.ctx == Load) { - return starunpack_helper(c, elts, - BUILD_LIST, BUILD_TUPLE, BUILD_LIST_UNPACK); + return starunpack_helper(c, elts, 0, BUILD_LIST, + LIST_APPEND, LIST_EXTEND, 0); } else VISIT_SEQ(c, expr, elts); @@ -3783,8 +3806,8 @@ compiler_tuple(struct compiler *c, expr_ty e) return assignment_helper(c, elts); } else if (e->v.Tuple.ctx == Load) { - return starunpack_helper(c, elts, - BUILD_TUPLE, BUILD_TUPLE, BUILD_TUPLE_UNPACK); + return starunpack_helper(c, elts, 0, BUILD_LIST, + LIST_APPEND, LIST_EXTEND, 1); } else VISIT_SEQ(c, expr, elts); @@ -3794,8 +3817,8 @@ compiler_tuple(struct compiler *c, expr_ty e) static int compiler_set(struct compiler *c, expr_ty e) { - return starunpack_helper(c, e->v.Set.elts, BUILD_SET, - BUILD_SET, BUILD_SET_UNPACK); + return starunpack_helper(c, e->v.Set.elts, 0, BUILD_SET, + SET_ADD, SET_UPDATE, 0); } static int @@ -4184,57 +4207,65 @@ compiler_call_helper(struct compiler *c, asdl_seq *keywords) { Py_ssize_t i, nseen, nelts, nkwelts; - int mustdictunpack = 0; - - /* the number of tuples and dictionaries on the stack */ - Py_ssize_t nsubargs = 0, nsubkwargs = 0; nelts = asdl_seq_LEN(args); nkwelts = asdl_seq_LEN(keywords); + for (i = 0; i < nelts; i++) { + expr_ty elt = asdl_seq_GET(args, i); + if (elt->kind == Starred_kind) { + goto ex_call; + } + } for (i = 0; i < nkwelts; i++) { keyword_ty kw = asdl_seq_GET(keywords, i); if (kw->arg == NULL) { - mustdictunpack = 1; - break; + goto ex_call; } } - nseen = n; /* the number of positional arguments on the stack */ + /* No * or ** args, so can use faster calling sequence */ for (i = 0; i < nelts; i++) { expr_ty elt = asdl_seq_GET(args, i); - if (elt->kind == Starred_kind) { - /* A star-arg. If we've seen positional arguments, - pack the positional arguments into a tuple. */ - if (nseen) { - ADDOP_I(c, BUILD_TUPLE, nseen); - nseen = 0; - nsubargs++; - } - VISIT(c, expr, elt->v.Starred.value); - nsubargs++; + assert(elt->kind != Starred_kind); + VISIT(c, expr, elt); + } + if (nkwelts) { + PyObject *names; + VISIT_SEQ(c, keyword, keywords); + names = PyTuple_New(nkwelts); + if (names == NULL) { + return 0; } - else { - VISIT(c, expr, elt); - nseen++; + for (i = 0; i < nkwelts; i++) { + keyword_ty kw = asdl_seq_GET(keywords, i); + Py_INCREF(kw->arg); + PyTuple_SET_ITEM(names, i, kw->arg); } + ADDOP_LOAD_CONST_NEW(c, names); + ADDOP_I(c, CALL_FUNCTION_KW, n + nelts + nkwelts); + return 1; + } + else { + ADDOP_I(c, CALL_FUNCTION, n + nelts); + return 1; } - /* Same dance again for keyword arguments */ - if (nsubargs || mustdictunpack) { - if (nseen) { - /* Pack up any trailing positional arguments. */ - ADDOP_I(c, BUILD_TUPLE, nseen); - nsubargs++; - } - if (nsubargs > 1) { - /* If we ended up with more than one stararg, we need - to concatenate them into a single sequence. */ - ADDOP_I(c, BUILD_TUPLE_UNPACK_WITH_CALL, nsubargs); - } - else if (nsubargs == 0) { - ADDOP_I(c, BUILD_TUPLE, 0); - } +ex_call: + + /* Do positional arguments. */ + if (n ==0 && nelts == 1 && ((expr_ty)asdl_seq_GET(args, 0))->kind == Starred_kind) { + VISIT(c, expr, ((expr_ty)asdl_seq_GET(args, 0))->v.Starred.value); + } + else if (starunpack_helper(c, args, n, BUILD_LIST, + LIST_APPEND, LIST_EXTEND, 1) == 0) { + return 0; + } + /* Then keyword arguments */ + if (nkwelts) { + /* the number of dictionaries on the stack */ + Py_ssize_t nsubkwargs = 0; + nseen = 0; /* the number of keyword arguments on the stack following */ for (i = 0; i < nkwelts; i++) { keyword_ty kw = asdl_seq_GET(keywords, i); @@ -4263,29 +4294,9 @@ compiler_call_helper(struct compiler *c, /* Pack it all up */ ADDOP_I(c, BUILD_MAP_UNPACK_WITH_CALL, nsubkwargs); } - ADDOP_I(c, CALL_FUNCTION_EX, nsubkwargs > 0); - return 1; - } - else if (nkwelts) { - PyObject *names; - VISIT_SEQ(c, keyword, keywords); - names = PyTuple_New(nkwelts); - if (names == NULL) { - return 0; - } - for (i = 0; i < nkwelts; i++) { - keyword_ty kw = asdl_seq_GET(keywords, i); - Py_INCREF(kw->arg); - PyTuple_SET_ITEM(names, i, kw->arg); - } - ADDOP_LOAD_CONST_NEW(c, names); - ADDOP_I(c, CALL_FUNCTION_KW, n + nelts + nkwelts); - return 1; - } - else { - ADDOP_I(c, CALL_FUNCTION, n + nelts); - return 1; } + ADDOP_I(c, CALL_FUNCTION_EX, nkwelts > 0); + return 1; } @@ -4860,9 +4871,9 @@ compiler_with(struct compiler *c, stmt_ty s, int pos) ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, WITH, block); - + /* End of body; start the cleanup. */ - + /* For successful outcome: * call __exit__(None, None, None) */ @@ -5984,7 +5995,7 @@ makecode(struct compiler *c, struct assembler *a) goto error; } co = PyCode_NewWithPosOnlyArgs(posonlyargcount+posorkeywordargcount, - posonlyargcount, kwonlyargcount, nlocals_int, + posonlyargcount, kwonlyargcount, nlocals_int, maxdepth, flags, bytecode, consts, names, varnames, freevars, cellvars, c->c_filename, c->u->u_name, c->u->u_firstlineno, a->a_lnotab); |