Skip to content

Commit 15a8728

Browse files
bpo-29469: Optimize literal lists and sets iterating on the AST level. (#4866)
1 parent 233ef24 commit 15a8728

File tree

4 files changed

+3761
-3775
lines changed

4 files changed

+3761
-3775
lines changed

‎Python/ast_opt.c‎

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ fold_binop(expr_ty node, PyArena *arena)
205205
}
206206

207207
static PyObject*
208-
make_const_tuple(asdl_seq *elts, int make_set)
208+
make_const_tuple(asdl_seq *elts)
209209
{
210210
for (int i = 0; i < asdl_seq_LEN(elts); i++) {
211211
expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
@@ -225,11 +225,6 @@ make_const_tuple(asdl_seq *elts, int make_set)
225225
Py_INCREF(v);
226226
PyTuple_SET_ITEM(newval, i, v);
227227
}
228-
229-
/* Need to create frozen_set instead. */
230-
if (make_set) {
231-
Py_SETREF(newval, PyFrozenSet_New(newval));
232-
}
233228
return newval;
234229
}
235230

@@ -241,7 +236,7 @@ fold_tuple(expr_ty node, PyArena *arena)
241236
if (node->v.Tuple.ctx != Load)
242237
return 1;
243238

244-
newval = make_const_tuple(node->v.Tuple.elts, 0);
239+
newval = make_const_tuple(node->v.Tuple.elts);
245240
return make_const(node, newval, arena);
246241
}
247242

@@ -268,38 +263,48 @@ fold_subscr(expr_ty node, PyArena *arena)
268263
return make_const(node, newval, arena);
269264
}
270265

266+
/* Change literal list or set of constants into constant
267+
tuple or frozenset respectively.
268+
Used for right operand of "in" and "not in" tests and for iterable
269+
in "for" loop and comprehensions.
270+
*/
271+
static int
272+
fold_iter(expr_ty arg, PyArena *arena)
273+
{
274+
PyObject *newval;
275+
if (arg->kind == List_kind) {
276+
newval = make_const_tuple(arg->v.List.elts);
277+
}
278+
else if (arg->kind == Set_kind) {
279+
newval = make_const_tuple(arg->v.Set.elts);
280+
if (newval) {
281+
Py_SETREF(newval, PyFrozenSet_New(newval));
282+
}
283+
}
284+
else {
285+
return 1;
286+
}
287+
return make_const(arg, newval, arena);
288+
}
289+
271290
static int
272291
fold_compare(expr_ty node, PyArena *arena)
273292
{
274293
asdl_int_seq *ops;
275294
asdl_seq *args;
276-
PyObject *newval;
277295
int i;
278296

279297
ops = node->v.Compare.ops;
280298
args = node->v.Compare.comparators;
281299
/* TODO: optimize cases with literal arguments. */
282-
for (i = 0; i < asdl_seq_LEN(ops); i++) {
283-
int op;
284-
expr_ty arg;
285-
asdl_seq *elts;
286-
287-
op = asdl_seq_GET(ops, i);
288-
arg = (expr_ty)asdl_seq_GET(args, i);
289-
/* Change literal list or set in 'in' or 'not in' into
290-
tuple or frozenset respectively. */
291-
/* TODO: do the same when list or set is used as iterable
292-
in for loop and comprehensions? */
293-
if (op != In && op != NotIn)
294-
continue;
295-
if (arg->kind == List_kind)
296-
elts = arg->v.List.elts;
297-
else if (arg->kind == Set_kind)
298-
elts = arg->v.Set.elts;
299-
else continue;
300-
301-
newval = make_const_tuple(elts, arg->kind == Set_kind);
302-
make_const(arg, newval, arena);
300+
/* Change literal list or set in 'in' or 'not in' into
301+
tuple or frozenset respectively. */
302+
i = asdl_seq_LEN(ops) - 1;
303+
int op = asdl_seq_GET(ops, i);
304+
if (op == In || op == NotIn) {
305+
if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena)) {
306+
return 0;
307+
}
303308
}
304309
return 1;
305310
}
@@ -497,6 +502,8 @@ astfold_comprehension(comprehension_ty node_, PyArena* ctx_)
497502
CALL(astfold_expr, expr_ty, node_->target);
498503
CALL(astfold_expr, expr_ty, node_->iter);
499504
CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
505+
506+
CALL(fold_iter, expr_ty, node_->iter);
500507
return 1;
501508
}
502509

@@ -565,6 +572,8 @@ astfold_stmt(stmt_ty node_, PyArena* ctx_)
565572
CALL(astfold_expr, expr_ty, node_->v.For.iter);
566573
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
567574
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
575+
576+
CALL(fold_iter, expr_ty, node_->v.For.iter);
568577
break;
569578
case AsyncFor_kind:
570579
CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);

0 commit comments

Comments
 (0)