static int codegen_visit_stmt(compiler *, stmt_ty);
static int codegen_visit_keyword(compiler *, keyword_ty);
static int codegen_visit_expr(compiler *, expr_ty);
+static int codegen_visit_unused_expr(compiler *, expr_ty);
static int codegen_augassign(compiler *, stmt_ty);
static int codegen_annassign(compiler *, stmt_ty);
static int codegen_subscript(compiler *, expr_ty);
asdl_comprehension_seq *generators, int gen_index,
int depth,
expr_ty elt, expr_ty val, int type,
- IterStackPosition iter_pos);
+ IterStackPosition iter_pos, bool avoid_creation);
static int codegen_async_comprehension_generator(
compiler *c, location loc,
asdl_comprehension_seq *generators, int gen_index,
int depth,
expr_ty elt, expr_ty val, int type,
- IterStackPosition iter_pos);
+ IterStackPosition iter_pos, bool avoid_creation);
static int codegen_pattern(compiler *, pattern_ty, pattern_context *);
static int codegen_match(compiler *, stmt_ty);
} \
} while (0)
+#define VISIT_UNUSED(C, TYPE, V) \
+ RETURN_IF_ERROR(codegen_visit_unused_ ## TYPE((C), (V)))
+
static int
codegen_call_exit_with_nones(compiler *c, location loc)
{
return SUCCESS;
}
- VISIT(c, expr, value);
+ VISIT_UNUSED(c, expr, value);
ADDOP(c, NO_LOCATION, POP_TOP); /* artificial */
return SUCCESS;
}
asdl_comprehension_seq *generators, int gen_index,
int depth,
expr_ty elt, expr_ty val, int type,
- IterStackPosition iter_pos)
+ IterStackPosition iter_pos, bool avoid_creation)
{
comprehension_ty gen;
gen = (comprehension_ty)asdl_seq_GET(generators, gen_index);
if (gen->is_async) {
return codegen_async_comprehension_generator(
c, loc, generators, gen_index, depth, elt, val, type,
- iter_pos);
+ iter_pos, avoid_creation);
} else {
return codegen_sync_comprehension_generator(
c, loc, generators, gen_index, depth, elt, val, type,
- iter_pos);
+ iter_pos, avoid_creation);
}
}
+static int
+codegen_unpack_starred(compiler *c, location loc, expr_ty value, bool yield)
+{
+ NEW_JUMP_TARGET_LABEL(c, unpack_start);
+ NEW_JUMP_TARGET_LABEL(c, unpack_end);
+ VISIT(c, expr, value);
+ ADDOP_I(c, loc, GET_ITER, 0);
+ USE_LABEL(c, unpack_start);
+ ADDOP_JUMP(c, loc, FOR_ITER, unpack_end);
+ if (yield) {
+ ADDOP_YIELD(c, loc);
+ }
+ ADDOP(c, loc, POP_TOP);
+ ADDOP_JUMP(c, NO_LOCATION, JUMP, unpack_start);
+ USE_LABEL(c, unpack_end);
+ ADDOP(c, NO_LOCATION, END_FOR);
+ ADDOP(c, NO_LOCATION, POP_ITER);
+ return SUCCESS;
+}
+
static int
codegen_sync_comprehension_generator(compiler *c, location loc,
asdl_comprehension_seq *generators,
int gen_index, int depth,
expr_ty elt, expr_ty val, int type,
- IterStackPosition iter_pos)
+ IterStackPosition iter_pos, bool avoid_creation)
{
/* generate code for the iterator, then each of the ifs,
and then write to the element */
RETURN_IF_ERROR(
codegen_comprehension_generator(c, loc,
generators, gen_index, depth,
- elt, val, type, ITERABLE_IN_LOCAL));
+ elt, val, type, ITERABLE_IN_LOCAL, avoid_creation));
}
location elt_loc = LOC(elt);
/* comprehension specific code */
switch (type) {
case COMP_GENEXP:
+ assert(!avoid_creation);
if (elt->kind == Starred_kind) {
- NEW_JUMP_TARGET_LABEL(c, unpack_start);
- NEW_JUMP_TARGET_LABEL(c, unpack_end);
- VISIT(c, expr, elt->v.Starred.value);
- ADDOP_I(c, elt_loc, GET_ITER, 0);
- USE_LABEL(c, unpack_start);
- ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end);
- ADDOP_YIELD(c, elt_loc);
- ADDOP(c, elt_loc, POP_TOP);
- ADDOP_JUMP(c, NO_LOCATION, JUMP, unpack_start);
- USE_LABEL(c, unpack_end);
- ADDOP(c, NO_LOCATION, END_FOR);
- ADDOP(c, NO_LOCATION, POP_ITER);
+ RETURN_IF_ERROR(codegen_unpack_starred(c, elt_loc, elt->v.Starred.value, /*yield=*/true));
}
else {
VISIT(c, expr, elt);
}
break;
case COMP_LISTCOMP:
+ if (avoid_creation) {
+ if (elt->kind == Starred_kind) {
+ RETURN_IF_ERROR(codegen_unpack_starred(c, elt_loc, elt->v.Starred.value, /*yield=*/false));
+ } else {
+ VISIT(c, expr, elt);
+ ADDOP(c, elt_loc, POP_TOP);
+ }
+ break;
+ }
if (elt->kind == Starred_kind) {
VISIT(c, expr, elt->v.Starred.value);
ADDOP_I(c, elt_loc, LIST_EXTEND, depth + 1);
asdl_comprehension_seq *generators,
int gen_index, int depth,
expr_ty elt, expr_ty val, int type,
- IterStackPosition iter_pos)
+ IterStackPosition iter_pos, bool avoid_creation)
{
NEW_JUMP_TARGET_LABEL(c, start);
NEW_JUMP_TARGET_LABEL(c, send);
RETURN_IF_ERROR(
codegen_comprehension_generator(c, loc,
generators, gen_index, depth,
- elt, val, type, 0));
+ elt, val, type, 0, avoid_creation));
}
location elt_loc = LOC(elt);
/* comprehension specific code */
switch (type) {
case COMP_GENEXP:
+ assert(!avoid_creation);
if (elt->kind == Starred_kind) {
NEW_JUMP_TARGET_LABEL(c, unpack_start);
NEW_JUMP_TARGET_LABEL(c, unpack_end);
}
break;
case COMP_LISTCOMP:
+ if (avoid_creation) {
+ if (elt->kind == Starred_kind) {
+ RETURN_IF_ERROR(codegen_unpack_starred(c, elt_loc, elt->v.Starred.value, /*yield=*/false));
+ } else {
+ VISIT(c, expr, elt);
+ ADDOP(c, elt_loc, POP_TOP);
+ }
+ break;
+ }
+
if (elt->kind == Starred_kind) {
VISIT(c, expr, elt->v.Starred.value);
ADDOP_I(c, elt_loc, LIST_EXTEND, depth + 1);
}
break;
case COMP_SETCOMP:
+ assert(!avoid_creation);
if (elt->kind == Starred_kind) {
VISIT(c, expr, elt->v.Starred.value);
ADDOP_I(c, elt_loc, SET_UPDATE, depth + 1);
}
break;
case COMP_DICTCOMP:
+ assert(!avoid_creation);
if (val == NULL) {
/* unpacking (**) case */
VISIT(c, expr, elt);
static int
codegen_comprehension(compiler *c, expr_ty e, int type,
identifier name, asdl_comprehension_seq *generators, expr_ty elt,
- expr_ty val)
+ expr_ty val, bool avoid_creation)
{
PyCodeObject *co = NULL;
_PyCompile_InlinedComprehensionState inline_state = {NULL, NULL, NULL, NO_LABEL};
goto error_in_scope;
}
- ADDOP_I(c, loc, op, 0);
- if (is_inlined) {
- ADDOP_I(c, loc, SWAP, 2);
+ if (!avoid_creation) {
+ ADDOP_I(c, loc, op, 0);
+ if (is_inlined) {
+ ADDOP_I(c, loc, SWAP, 2);
+ }
+ } else {
+ ADDOP_I(c, loc, COPY, 1);
}
}
if (codegen_comprehension_generator(c, loc, generators, 0, 0,
- elt, val, type, iter_state) < 0) {
+ elt, val, type, iter_state, avoid_creation) < 0) {
goto error_in_scope;
}
ADD_YIELD_FROM(c, loc, 1);
}
+ assert(!avoid_creation);
+
return SUCCESS;
error_in_scope:
if (!is_inlined) {
_Py_DECLARE_STR(anon_genexpr, "<genexpr>");
return codegen_comprehension(c, e, COMP_GENEXP, &_Py_STR(anon_genexpr),
e->v.GeneratorExp.generators,
- e->v.GeneratorExp.elt, NULL);
+ e->v.GeneratorExp.elt, NULL, false);
}
static int
-codegen_listcomp(compiler *c, expr_ty e)
+codegen_listcomp(compiler *c, expr_ty e, bool avoid_creation)
{
assert(e->kind == ListComp_kind);
_Py_DECLARE_STR(anon_listcomp, "<listcomp>");
return codegen_comprehension(c, e, COMP_LISTCOMP, &_Py_STR(anon_listcomp),
e->v.ListComp.generators,
- e->v.ListComp.elt, NULL);
+ e->v.ListComp.elt, NULL, avoid_creation);
}
static int
_Py_DECLARE_STR(anon_setcomp, "<setcomp>");
return codegen_comprehension(c, e, COMP_SETCOMP, &_Py_STR(anon_setcomp),
e->v.SetComp.generators,
- e->v.SetComp.elt, NULL);
+ e->v.SetComp.elt, NULL, /*avoid_creation=*/false);
}
_Py_DECLARE_STR(anon_dictcomp, "<dictcomp>");
return codegen_comprehension(c, e, COMP_DICTCOMP, &_Py_STR(anon_dictcomp),
e->v.DictComp.generators,
- e->v.DictComp.key, e->v.DictComp.value);
+ e->v.DictComp.key, e->v.DictComp.value, /*avoid_creation=*/false);
}
}
static int
-codegen_visit_expr(compiler *c, expr_ty e)
+codegen_visit_expr_impl(compiler *c, expr_ty e, bool result_is_unused)
{
if (Py_EnterRecursiveCall(" during compilation")) {
return ERROR;
case GeneratorExp_kind:
return codegen_genexp(c, e);
case ListComp_kind:
- return codegen_listcomp(c, e);
+ return codegen_listcomp(c, e, result_is_unused);
case SetComp_kind:
return codegen_setcomp(c, e);
case DictComp_kind:
return SUCCESS;
}
+static int
+codegen_visit_expr(compiler *c, expr_ty e)
+{
+ return codegen_visit_expr_impl(c, e, false);
+}
+
+static int
+codegen_visit_unused_expr(compiler *c, expr_ty e)
+{
+ return codegen_visit_expr_impl(c, e, true);
+}
+
static bool
is_constant_slice(expr_ty s)
{