summaryrefslogtreecommitdiff
path: root/Python/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c203
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);