blob: a998d1fb601433efaaebf6869ff93add8acd6398 [file] [log] [blame]
INADA Naoki7ea143a2017-12-14 16:47:20 +09001/* AST Optimizer */
2#include "Python.h"
3#include "Python-ast.h"
4
5
6/* TODO: is_const and get_const_value are copied from Python/compile.c.
7 It should be deduped in the future. Maybe, we can include this file
8 from compile.c?
9*/
10static int
11is_const(expr_ty e)
12{
13 switch (e->kind) {
14 case Constant_kind:
15 case Num_kind:
16 case Str_kind:
17 case Bytes_kind:
18 case Ellipsis_kind:
19 case NameConstant_kind:
20 return 1;
21 default:
22 return 0;
23 }
24}
25
26static PyObject *
27get_const_value(expr_ty e)
28{
29 switch (e->kind) {
30 case Constant_kind:
31 return e->v.Constant.value;
32 case Num_kind:
33 return e->v.Num.n;
34 case Str_kind:
35 return e->v.Str.s;
36 case Bytes_kind:
37 return e->v.Bytes.s;
38 case Ellipsis_kind:
39 return Py_Ellipsis;
40 case NameConstant_kind:
41 return e->v.NameConstant.value;
42 default:
43 Py_UNREACHABLE();
44 }
45}
46
47static int
48make_const(expr_ty node, PyObject *val, PyArena *arena)
49{
50 if (val == NULL) {
51 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
52 return 0;
53 }
54 PyErr_Clear();
55 return 1;
56 }
57 if (PyArena_AddPyObject(arena, val) < 0) {
58 Py_DECREF(val);
59 return 0;
60 }
61 node->kind = Constant_kind;
62 node->v.Constant.value = val;
63 return 1;
64}
65
66#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
67
68static PyObject*
69unary_not(PyObject *v)
70{
71 int r = PyObject_IsTrue(v);
72 if (r < 0)
73 return NULL;
74 return PyBool_FromLong(!r);
75}
76
77static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +020078fold_unaryop(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +090079{
80 expr_ty arg = node->v.UnaryOp.operand;
81
82 if (!is_const(arg)) {
83 /* Fold not into comparison */
84 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
85 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
86 /* Eq and NotEq are often implemented in terms of one another, so
87 folding not (self == other) into self != other breaks implementation
88 of !=. Detecting such cases doesn't seem worthwhile.
89 Python uses </> for 'is subset'/'is superset' operations on sets.
90 They don't satisfy not folding laws. */
91 int op = asdl_seq_GET(arg->v.Compare.ops, 0);
92 switch (op) {
93 case Is:
94 op = IsNot;
95 break;
96 case IsNot:
97 op = Is;
98 break;
99 case In:
100 op = NotIn;
101 break;
102 case NotIn:
103 op = In;
104 break;
105 default:
106 op = 0;
107 }
108 if (op) {
109 asdl_seq_SET(arg->v.Compare.ops, 0, op);
110 COPY_NODE(node, arg);
111 return 1;
112 }
113 }
114 return 1;
115 }
116
117 typedef PyObject *(*unary_op)(PyObject*);
118 static const unary_op ops[] = {
119 [Invert] = PyNumber_Invert,
120 [Not] = unary_not,
121 [UAdd] = PyNumber_Positive,
122 [USub] = PyNumber_Negative,
123 };
124 PyObject *newval = ops[node->v.UnaryOp.op](get_const_value(arg));
125 return make_const(node, newval, arena);
126}
127
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200128/* Check whether a collection doesn't containing too much items (including
129 subcollections). This protects from creating a constant that needs
130 too much time for calculating a hash.
131 "limit" is the maximal number of items.
132 Returns the negative number if the total number of items exceeds the
133 limit. Otherwise returns the limit minus the total number of items.
134*/
135
136static Py_ssize_t
137check_complexity(PyObject *obj, Py_ssize_t limit)
138{
139 if (PyTuple_Check(obj)) {
140 Py_ssize_t i;
141 limit -= PyTuple_GET_SIZE(obj);
142 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
143 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
144 }
145 return limit;
146 }
147 else if (PyFrozenSet_Check(obj)) {
148 Py_ssize_t i = 0;
149 PyObject *item;
150 Py_hash_t hash;
151 limit -= PySet_GET_SIZE(obj);
152 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
153 limit = check_complexity(item, limit);
154 }
155 }
156 return limit;
157}
158
159#define MAX_INT_SIZE 128 /* bits */
160#define MAX_COLLECTION_SIZE 256 /* items */
161#define MAX_STR_SIZE 4096 /* characters */
162#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
163
164static PyObject *
165safe_multiply(PyObject *v, PyObject *w)
166{
167 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
168 size_t vbits = _PyLong_NumBits(v);
169 size_t wbits = _PyLong_NumBits(w);
170 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
171 return NULL;
172 }
173 if (vbits + wbits > MAX_INT_SIZE) {
174 return NULL;
175 }
176 }
177 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
178 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
179 PySet_GET_SIZE(w);
180 if (size) {
181 long n = PyLong_AsLong(v);
182 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
183 return NULL;
184 }
185 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
186 return NULL;
187 }
188 }
189 }
190 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
191 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
192 PyBytes_GET_SIZE(w);
193 if (size) {
194 long n = PyLong_AsLong(v);
195 if (n < 0 || n > MAX_STR_SIZE / size) {
196 return NULL;
197 }
198 }
199 }
200 else if (PyLong_Check(w) &&
201 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
202 PyUnicode_Check(v) || PyBytes_Check(v)))
203 {
204 return safe_multiply(w, v);
205 }
206
207 return PyNumber_Multiply(v, w);
208}
209
210static PyObject *
211safe_power(PyObject *v, PyObject *w)
212{
213 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
214 size_t vbits = _PyLong_NumBits(v);
215 size_t wbits = PyLong_AsSize_t(w);
216 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
217 return NULL;
218 }
219 if (vbits > MAX_INT_SIZE / wbits) {
220 return NULL;
221 }
222 }
223
224 return PyNumber_Power(v, w, Py_None);
225}
226
227static PyObject *
228safe_lshift(PyObject *v, PyObject *w)
229{
230 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
231 size_t vbits = _PyLong_NumBits(v);
232 size_t wbits = PyLong_AsSize_t(w);
233 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
234 return NULL;
235 }
236 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
237 return NULL;
238 }
239 }
240
241 return PyNumber_Lshift(v, w);
242}
243
244static PyObject *
245safe_mod(PyObject *v, PyObject *w)
246{
247 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
248 return NULL;
249 }
250
251 return PyNumber_Remainder(v, w);
252}
253
INADA Naoki7ea143a2017-12-14 16:47:20 +0900254static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200255fold_binop(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900256{
257 expr_ty lhs, rhs;
258 lhs = node->v.BinOp.left;
259 rhs = node->v.BinOp.right;
260 if (!is_const(lhs) || !is_const(rhs)) {
261 return 1;
262 }
263
264 PyObject *lv = get_const_value(lhs);
265 PyObject *rv = get_const_value(rhs);
266 PyObject *newval;
267
268 switch (node->v.BinOp.op) {
269 case Add:
270 newval = PyNumber_Add(lv, rv);
271 break;
272 case Sub:
273 newval = PyNumber_Subtract(lv, rv);
274 break;
275 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200276 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900277 break;
278 case Div:
279 newval = PyNumber_TrueDivide(lv, rv);
280 break;
281 case FloorDiv:
282 newval = PyNumber_FloorDivide(lv, rv);
283 break;
284 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200285 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900286 break;
287 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200288 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900289 break;
290 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200291 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900292 break;
293 case RShift:
294 newval = PyNumber_Rshift(lv, rv);
295 break;
296 case BitOr:
297 newval = PyNumber_Or(lv, rv);
298 break;
299 case BitXor:
300 newval = PyNumber_Xor(lv, rv);
301 break;
302 case BitAnd:
303 newval = PyNumber_And(lv, rv);
304 break;
305 default: // Unknown operator
306 return 1;
307 }
308
INADA Naoki7ea143a2017-12-14 16:47:20 +0900309 return make_const(node, newval, arena);
310}
311
312static PyObject*
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200313make_const_tuple(asdl_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900314{
315 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
316 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
317 if (!is_const(e)) {
318 return NULL;
319 }
320 }
321
322 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
323 if (newval == NULL) {
324 return NULL;
325 }
326
327 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
328 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
329 PyObject *v = get_const_value(e);
330 Py_INCREF(v);
331 PyTuple_SET_ITEM(newval, i, v);
332 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900333 return newval;
334}
335
336static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200337fold_tuple(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900338{
339 PyObject *newval;
340
341 if (node->v.Tuple.ctx != Load)
342 return 1;
343
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200344 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900345 return make_const(node, newval, arena);
346}
347
348static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200349fold_subscr(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900350{
351 PyObject *newval;
352 expr_ty arg, idx;
353 slice_ty slice;
354
355 arg = node->v.Subscript.value;
356 slice = node->v.Subscript.slice;
357 if (node->v.Subscript.ctx != Load ||
358 !is_const(arg) ||
359 /* TODO: handle other types of slices */
360 slice->kind != Index_kind ||
361 !is_const(slice->v.Index.value))
362 {
363 return 1;
364 }
365
366 idx = slice->v.Index.value;
367 newval = PyObject_GetItem(get_const_value(arg), get_const_value(idx));
368 return make_const(node, newval, arena);
369}
370
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200371/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200372 tuple or frozenset respectively. Change literal list of
373 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200374 Used for right operand of "in" and "not in" tests and for iterable
375 in "for" loop and comprehensions.
376*/
377static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200378fold_iter(expr_ty arg, PyArena *arena, int optimize)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200379{
380 PyObject *newval;
381 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200382 /* First change a list into tuple. */
383 asdl_seq *elts = arg->v.List.elts;
384 Py_ssize_t n = asdl_seq_LEN(elts);
385 for (Py_ssize_t i = 0; i < n; i++) {
386 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
387 if (e->kind == Starred_kind) {
388 return 1;
389 }
390 }
391 expr_context_ty ctx = arg->v.List.ctx;
392 arg->kind = Tuple_kind;
393 arg->v.Tuple.elts = elts;
394 arg->v.Tuple.ctx = ctx;
395 /* Try to create a constant tuple. */
396 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200397 }
398 else if (arg->kind == Set_kind) {
399 newval = make_const_tuple(arg->v.Set.elts);
400 if (newval) {
401 Py_SETREF(newval, PyFrozenSet_New(newval));
402 }
403 }
404 else {
405 return 1;
406 }
407 return make_const(arg, newval, arena);
408}
409
INADA Naoki7ea143a2017-12-14 16:47:20 +0900410static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200411fold_compare(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900412{
413 asdl_int_seq *ops;
414 asdl_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100415 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900416
417 ops = node->v.Compare.ops;
418 args = node->v.Compare.comparators;
419 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200420 /* Change literal list or set in 'in' or 'not in' into
421 tuple or frozenset respectively. */
422 i = asdl_seq_LEN(ops) - 1;
423 int op = asdl_seq_GET(ops, i);
424 if (op == In || op == NotIn) {
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200425 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, optimize)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200426 return 0;
427 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900428 }
429 return 1;
430}
431
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200432static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_);
433static int astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_);
434static int astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_);
435static int astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_);
436static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_);
437static int astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_);
438static int astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_);
439static int astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_);
440static int astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_);
441static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900442#define CALL(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200443 if (!FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900444 return 0;
445
446#define CALL_OPT(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200447 if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900448 return 0;
449
450#define CALL_SEQ(FUNC, TYPE, ARG) { \
451 int i; \
452 asdl_seq *seq = (ARG); /* avoid variable capture */ \
453 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
454 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200455 if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900456 return 0; \
457 } \
458}
459
460#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
461 int i; \
462 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
463 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
464 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200465 if (!FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900466 return 0; \
467 } \
468}
469
470static int
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300471isdocstring(stmt_ty s)
472{
473 if (s->kind != Expr_kind)
474 return 0;
475 if (s->v.Expr.value->kind == Str_kind)
476 return 1;
477 if (s->v.Expr.value->kind == Constant_kind)
478 return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value);
479 return 0;
480}
481
482static int
483astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
484{
485 if (!asdl_seq_LEN(stmts)) {
486 return 1;
487 }
488 int docstring = isdocstring((stmt_ty)asdl_seq_GET(stmts, 0));
489 CALL_SEQ(astfold_stmt, stmt_ty, stmts);
490 if (docstring) {
491 return 1;
492 }
493 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
494 if (isdocstring(st)) {
495 asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
496 if (!values) {
497 return 0;
498 }
499 asdl_seq_SET(values, 0, st->v.Expr.value);
500 expr_ty expr = _Py_JoinedStr(values, st->lineno, st->col_offset, ctx_);
501 if (!expr) {
502 return 0;
503 }
504 st->v.Expr.value = expr;
505 }
506 return 1;
507}
508
509static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200510astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900511{
512 switch (node_->kind) {
513 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300514 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900515 break;
516 case Interactive_kind:
517 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
518 break;
519 case Expression_kind:
520 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
521 break;
522 case Suite_kind:
523 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Suite.body);
524 break;
525 default:
526 break;
527 }
528 return 1;
529}
530
531static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200532astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900533{
534 switch (node_->kind) {
535 case BoolOp_kind:
536 CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
537 break;
538 case BinOp_kind:
539 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
540 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
541 CALL(fold_binop, expr_ty, node_);
542 break;
543 case UnaryOp_kind:
544 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
545 CALL(fold_unaryop, expr_ty, node_);
546 break;
547 case Lambda_kind:
548 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
549 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
550 break;
551 case IfExp_kind:
552 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
553 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
554 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
555 break;
556 case Dict_kind:
557 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
558 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
559 break;
560 case Set_kind:
561 CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
562 break;
563 case ListComp_kind:
564 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
565 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
566 break;
567 case SetComp_kind:
568 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
569 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
570 break;
571 case DictComp_kind:
572 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
573 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
574 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
575 break;
576 case GeneratorExp_kind:
577 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
578 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
579 break;
580 case Await_kind:
581 CALL(astfold_expr, expr_ty, node_->v.Await.value);
582 break;
583 case Yield_kind:
584 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
585 break;
586 case YieldFrom_kind:
587 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
588 break;
589 case Compare_kind:
590 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
591 CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
592 CALL(fold_compare, expr_ty, node_);
593 break;
594 case Call_kind:
595 CALL(astfold_expr, expr_ty, node_->v.Call.func);
596 CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
597 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
598 break;
599 case FormattedValue_kind:
600 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
601 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
602 break;
603 case JoinedStr_kind:
604 CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
605 break;
606 case Attribute_kind:
607 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
608 break;
609 case Subscript_kind:
610 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
611 CALL(astfold_slice, slice_ty, node_->v.Subscript.slice);
612 CALL(fold_subscr, expr_ty, node_);
613 break;
614 case Starred_kind:
615 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
616 break;
617 case List_kind:
618 CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
619 break;
620 case Tuple_kind:
621 CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
622 CALL(fold_tuple, expr_ty, node_);
623 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200624 case Name_kind:
625 if (_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
626 return make_const(node_, PyBool_FromLong(!optimize_), ctx_);
627 }
628 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900629 default:
630 break;
631 }
632 return 1;
633}
634
635static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200636astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900637{
638 switch (node_->kind) {
639 case Slice_kind:
640 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
641 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
642 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
643 break;
644 case ExtSlice_kind:
645 CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims);
646 break;
647 case Index_kind:
648 CALL(astfold_expr, expr_ty, node_->v.Index.value);
649 break;
650 default:
651 break;
652 }
653 return 1;
654}
655
656static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200657astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900658{
659 CALL(astfold_expr, expr_ty, node_->value);
660 return 1;
661}
662
663static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200664astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900665{
666 CALL(astfold_expr, expr_ty, node_->target);
667 CALL(astfold_expr, expr_ty, node_->iter);
668 CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200669
670 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900671 return 1;
672}
673
674static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200675astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900676{
677 CALL_SEQ(astfold_arg, arg_ty, node_->args);
678 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
679 CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
680 CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
681 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
682 CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
683 return 1;
684}
685
686static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200687astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900688{
689 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
690 return 1;
691}
692
693static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200694astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900695{
696 switch (node_->kind) {
697 case FunctionDef_kind:
698 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300699 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900700 CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
701 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
702 break;
703 case AsyncFunctionDef_kind:
704 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300705 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900706 CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
707 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
708 break;
709 case ClassDef_kind:
710 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
711 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300712 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900713 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
714 break;
715 case Return_kind:
716 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
717 break;
718 case Delete_kind:
719 CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
720 break;
721 case Assign_kind:
722 CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
723 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
724 break;
725 case AugAssign_kind:
726 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
727 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
728 break;
729 case AnnAssign_kind:
730 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
731 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
732 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
733 break;
734 case For_kind:
735 CALL(astfold_expr, expr_ty, node_->v.For.target);
736 CALL(astfold_expr, expr_ty, node_->v.For.iter);
737 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
738 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200739
740 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900741 break;
742 case AsyncFor_kind:
743 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
744 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
745 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
746 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
747 break;
748 case While_kind:
749 CALL(astfold_expr, expr_ty, node_->v.While.test);
750 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
751 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
752 break;
753 case If_kind:
754 CALL(astfold_expr, expr_ty, node_->v.If.test);
755 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
756 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
757 break;
758 case With_kind:
759 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
760 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
761 break;
762 case AsyncWith_kind:
763 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
764 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
765 break;
766 case Raise_kind:
767 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
768 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
769 break;
770 case Try_kind:
771 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
772 CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
773 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
774 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
775 break;
776 case Assert_kind:
777 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
778 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
779 break;
780 case Expr_kind:
781 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
782 break;
783 default:
784 break;
785 }
786 return 1;
787}
788
789static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200790astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900791{
792 switch (node_->kind) {
793 case ExceptHandler_kind:
794 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
795 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
796 break;
797 default:
798 break;
799 }
800 return 1;
801}
802
803static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200804astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900805{
806 CALL(astfold_expr, expr_ty, node_->context_expr);
807 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
808 return 1;
809}
810
811#undef CALL
812#undef CALL_OPT
813#undef CALL_SEQ
814#undef CALL_INT_SEQ
815
816int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200817_PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900818{
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200819 int ret = astfold_mod(mod, arena, optimize);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900820 assert(ret || PyErr_Occurred());
821 return ret;
822}