blob: 1f9cb773ea7b958ba08d6216dd61e5b6cbed16de [file] [log] [blame]
INADA Naoki7ea143a2017-12-14 16:47:20 +09001/* AST Optimizer */
2#include "Python.h"
3#include "Python-ast.h"
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +03004#include "node.h"
5#include "ast.h"
INADA Naoki7ea143a2017-12-14 16:47:20 +09006
7
INADA Naoki7ea143a2017-12-14 16:47:20 +09008static int
9make_const(expr_ty node, PyObject *val, PyArena *arena)
10{
11 if (val == NULL) {
12 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
13 return 0;
14 }
15 PyErr_Clear();
16 return 1;
17 }
18 if (PyArena_AddPyObject(arena, val) < 0) {
19 Py_DECREF(val);
20 return 0;
21 }
22 node->kind = Constant_kind;
23 node->v.Constant.value = val;
24 return 1;
25}
26
27#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
28
29static PyObject*
30unary_not(PyObject *v)
31{
32 int r = PyObject_IsTrue(v);
33 if (r < 0)
34 return NULL;
35 return PyBool_FromLong(!r);
36}
37
38static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +020039fold_unaryop(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +090040{
41 expr_ty arg = node->v.UnaryOp.operand;
42
Serhiy Storchaka3f228112018-09-27 17:42:37 +030043 if (arg->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090044 /* Fold not into comparison */
45 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
46 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
47 /* Eq and NotEq are often implemented in terms of one another, so
48 folding not (self == other) into self != other breaks implementation
49 of !=. Detecting such cases doesn't seem worthwhile.
50 Python uses </> for 'is subset'/'is superset' operations on sets.
51 They don't satisfy not folding laws. */
52 int op = asdl_seq_GET(arg->v.Compare.ops, 0);
53 switch (op) {
54 case Is:
55 op = IsNot;
56 break;
57 case IsNot:
58 op = Is;
59 break;
60 case In:
61 op = NotIn;
62 break;
63 case NotIn:
64 op = In;
65 break;
66 default:
67 op = 0;
68 }
69 if (op) {
70 asdl_seq_SET(arg->v.Compare.ops, 0, op);
71 COPY_NODE(node, arg);
72 return 1;
73 }
74 }
75 return 1;
76 }
77
78 typedef PyObject *(*unary_op)(PyObject*);
79 static const unary_op ops[] = {
80 [Invert] = PyNumber_Invert,
81 [Not] = unary_not,
82 [UAdd] = PyNumber_Positive,
83 [USub] = PyNumber_Negative,
84 };
Serhiy Storchaka3f228112018-09-27 17:42:37 +030085 PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +090086 return make_const(node, newval, arena);
87}
88
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +020089/* Check whether a collection doesn't containing too much items (including
90 subcollections). This protects from creating a constant that needs
91 too much time for calculating a hash.
92 "limit" is the maximal number of items.
93 Returns the negative number if the total number of items exceeds the
94 limit. Otherwise returns the limit minus the total number of items.
95*/
96
97static Py_ssize_t
98check_complexity(PyObject *obj, Py_ssize_t limit)
99{
100 if (PyTuple_Check(obj)) {
101 Py_ssize_t i;
102 limit -= PyTuple_GET_SIZE(obj);
103 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
104 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
105 }
106 return limit;
107 }
108 else if (PyFrozenSet_Check(obj)) {
109 Py_ssize_t i = 0;
110 PyObject *item;
111 Py_hash_t hash;
112 limit -= PySet_GET_SIZE(obj);
113 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
114 limit = check_complexity(item, limit);
115 }
116 }
117 return limit;
118}
119
120#define MAX_INT_SIZE 128 /* bits */
121#define MAX_COLLECTION_SIZE 256 /* items */
122#define MAX_STR_SIZE 4096 /* characters */
123#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
124
125static PyObject *
126safe_multiply(PyObject *v, PyObject *w)
127{
128 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
129 size_t vbits = _PyLong_NumBits(v);
130 size_t wbits = _PyLong_NumBits(w);
131 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
132 return NULL;
133 }
134 if (vbits + wbits > MAX_INT_SIZE) {
135 return NULL;
136 }
137 }
138 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
139 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
140 PySet_GET_SIZE(w);
141 if (size) {
142 long n = PyLong_AsLong(v);
143 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
144 return NULL;
145 }
146 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
147 return NULL;
148 }
149 }
150 }
151 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
152 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
153 PyBytes_GET_SIZE(w);
154 if (size) {
155 long n = PyLong_AsLong(v);
156 if (n < 0 || n > MAX_STR_SIZE / size) {
157 return NULL;
158 }
159 }
160 }
161 else if (PyLong_Check(w) &&
162 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
163 PyUnicode_Check(v) || PyBytes_Check(v)))
164 {
165 return safe_multiply(w, v);
166 }
167
168 return PyNumber_Multiply(v, w);
169}
170
171static PyObject *
172safe_power(PyObject *v, PyObject *w)
173{
174 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
175 size_t vbits = _PyLong_NumBits(v);
176 size_t wbits = PyLong_AsSize_t(w);
177 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
178 return NULL;
179 }
180 if (vbits > MAX_INT_SIZE / wbits) {
181 return NULL;
182 }
183 }
184
185 return PyNumber_Power(v, w, Py_None);
186}
187
188static PyObject *
189safe_lshift(PyObject *v, PyObject *w)
190{
191 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
192 size_t vbits = _PyLong_NumBits(v);
193 size_t wbits = PyLong_AsSize_t(w);
194 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
195 return NULL;
196 }
197 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
198 return NULL;
199 }
200 }
201
202 return PyNumber_Lshift(v, w);
203}
204
205static PyObject *
206safe_mod(PyObject *v, PyObject *w)
207{
208 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
209 return NULL;
210 }
211
212 return PyNumber_Remainder(v, w);
213}
214
INADA Naoki7ea143a2017-12-14 16:47:20 +0900215static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200216fold_binop(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900217{
218 expr_ty lhs, rhs;
219 lhs = node->v.BinOp.left;
220 rhs = node->v.BinOp.right;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300221 if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900222 return 1;
223 }
224
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300225 PyObject *lv = lhs->v.Constant.value;
226 PyObject *rv = rhs->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900227 PyObject *newval;
228
229 switch (node->v.BinOp.op) {
230 case Add:
231 newval = PyNumber_Add(lv, rv);
232 break;
233 case Sub:
234 newval = PyNumber_Subtract(lv, rv);
235 break;
236 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200237 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900238 break;
239 case Div:
240 newval = PyNumber_TrueDivide(lv, rv);
241 break;
242 case FloorDiv:
243 newval = PyNumber_FloorDivide(lv, rv);
244 break;
245 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200246 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900247 break;
248 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200249 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900250 break;
251 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200252 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900253 break;
254 case RShift:
255 newval = PyNumber_Rshift(lv, rv);
256 break;
257 case BitOr:
258 newval = PyNumber_Or(lv, rv);
259 break;
260 case BitXor:
261 newval = PyNumber_Xor(lv, rv);
262 break;
263 case BitAnd:
264 newval = PyNumber_And(lv, rv);
265 break;
266 default: // Unknown operator
267 return 1;
268 }
269
INADA Naoki7ea143a2017-12-14 16:47:20 +0900270 return make_const(node, newval, arena);
271}
272
273static PyObject*
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200274make_const_tuple(asdl_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900275{
276 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
277 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300278 if (e->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900279 return NULL;
280 }
281 }
282
283 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
284 if (newval == NULL) {
285 return NULL;
286 }
287
288 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
289 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300290 PyObject *v = e->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900291 Py_INCREF(v);
292 PyTuple_SET_ITEM(newval, i, v);
293 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900294 return newval;
295}
296
297static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200298fold_tuple(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900299{
300 PyObject *newval;
301
302 if (node->v.Tuple.ctx != Load)
303 return 1;
304
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200305 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900306 return make_const(node, newval, arena);
307}
308
309static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200310fold_subscr(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900311{
312 PyObject *newval;
313 expr_ty arg, idx;
314 slice_ty slice;
315
316 arg = node->v.Subscript.value;
317 slice = node->v.Subscript.slice;
318 if (node->v.Subscript.ctx != Load ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300319 arg->kind != Constant_kind ||
INADA Naoki7ea143a2017-12-14 16:47:20 +0900320 /* TODO: handle other types of slices */
321 slice->kind != Index_kind ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300322 slice->v.Index.value->kind != Constant_kind)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900323 {
324 return 1;
325 }
326
327 idx = slice->v.Index.value;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300328 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900329 return make_const(node, newval, arena);
330}
331
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200332/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200333 tuple or frozenset respectively. Change literal list of
334 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200335 Used for right operand of "in" and "not in" tests and for iterable
336 in "for" loop and comprehensions.
337*/
338static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200339fold_iter(expr_ty arg, PyArena *arena, int optimize)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200340{
341 PyObject *newval;
342 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200343 /* First change a list into tuple. */
344 asdl_seq *elts = arg->v.List.elts;
345 Py_ssize_t n = asdl_seq_LEN(elts);
346 for (Py_ssize_t i = 0; i < n; i++) {
347 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
348 if (e->kind == Starred_kind) {
349 return 1;
350 }
351 }
352 expr_context_ty ctx = arg->v.List.ctx;
353 arg->kind = Tuple_kind;
354 arg->v.Tuple.elts = elts;
355 arg->v.Tuple.ctx = ctx;
356 /* Try to create a constant tuple. */
357 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200358 }
359 else if (arg->kind == Set_kind) {
360 newval = make_const_tuple(arg->v.Set.elts);
361 if (newval) {
362 Py_SETREF(newval, PyFrozenSet_New(newval));
363 }
364 }
365 else {
366 return 1;
367 }
368 return make_const(arg, newval, arena);
369}
370
INADA Naoki7ea143a2017-12-14 16:47:20 +0900371static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200372fold_compare(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900373{
374 asdl_int_seq *ops;
375 asdl_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100376 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900377
378 ops = node->v.Compare.ops;
379 args = node->v.Compare.comparators;
380 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200381 /* Change literal list or set in 'in' or 'not in' into
382 tuple or frozenset respectively. */
383 i = asdl_seq_LEN(ops) - 1;
384 int op = asdl_seq_GET(ops, i);
385 if (op == In || op == NotIn) {
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200386 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, optimize)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200387 return 0;
388 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900389 }
390 return 1;
391}
392
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200393static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_);
394static int astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_);
395static int astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_);
396static int astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_);
397static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_);
398static int astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_);
399static int astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_);
400static int astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_);
401static int astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_);
402static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900403#define CALL(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200404 if (!FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900405 return 0;
406
407#define CALL_OPT(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200408 if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900409 return 0;
410
411#define CALL_SEQ(FUNC, TYPE, ARG) { \
412 int i; \
413 asdl_seq *seq = (ARG); /* avoid variable capture */ \
414 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
415 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200416 if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900417 return 0; \
418 } \
419}
420
421#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
422 int i; \
423 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
424 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
425 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200426 if (!FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900427 return 0; \
428 } \
429}
430
431static int
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300432astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
433{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300434 int docstring = _PyAST_GetDocString(stmts) != NULL;
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300435 CALL_SEQ(astfold_stmt, stmt_ty, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300436 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
437 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300438 asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
439 if (!values) {
440 return 0;
441 }
442 asdl_seq_SET(values, 0, st->v.Expr.value);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300443 expr_ty expr = JoinedStr(values, st->lineno, st->col_offset, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300444 if (!expr) {
445 return 0;
446 }
447 st->v.Expr.value = expr;
448 }
449 return 1;
450}
451
452static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200453astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900454{
455 switch (node_->kind) {
456 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300457 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900458 break;
459 case Interactive_kind:
460 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
461 break;
462 case Expression_kind:
463 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
464 break;
465 case Suite_kind:
466 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Suite.body);
467 break;
468 default:
469 break;
470 }
471 return 1;
472}
473
474static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200475astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900476{
477 switch (node_->kind) {
478 case BoolOp_kind:
479 CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
480 break;
481 case BinOp_kind:
482 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
483 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
484 CALL(fold_binop, expr_ty, node_);
485 break;
486 case UnaryOp_kind:
487 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
488 CALL(fold_unaryop, expr_ty, node_);
489 break;
490 case Lambda_kind:
491 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
492 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
493 break;
494 case IfExp_kind:
495 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
496 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
497 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
498 break;
499 case Dict_kind:
500 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
501 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
502 break;
503 case Set_kind:
504 CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
505 break;
506 case ListComp_kind:
507 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
508 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
509 break;
510 case SetComp_kind:
511 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
512 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
513 break;
514 case DictComp_kind:
515 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
516 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
517 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
518 break;
519 case GeneratorExp_kind:
520 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
521 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
522 break;
523 case Await_kind:
524 CALL(astfold_expr, expr_ty, node_->v.Await.value);
525 break;
526 case Yield_kind:
527 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
528 break;
529 case YieldFrom_kind:
530 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
531 break;
532 case Compare_kind:
533 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
534 CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
535 CALL(fold_compare, expr_ty, node_);
536 break;
537 case Call_kind:
538 CALL(astfold_expr, expr_ty, node_->v.Call.func);
539 CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
540 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
541 break;
542 case FormattedValue_kind:
543 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
544 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
545 break;
546 case JoinedStr_kind:
547 CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
548 break;
549 case Attribute_kind:
550 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
551 break;
552 case Subscript_kind:
553 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
554 CALL(astfold_slice, slice_ty, node_->v.Subscript.slice);
555 CALL(fold_subscr, expr_ty, node_);
556 break;
557 case Starred_kind:
558 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
559 break;
560 case List_kind:
561 CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
562 break;
563 case Tuple_kind:
564 CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
565 CALL(fold_tuple, expr_ty, node_);
566 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200567 case Name_kind:
568 if (_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
569 return make_const(node_, PyBool_FromLong(!optimize_), ctx_);
570 }
571 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900572 default:
573 break;
574 }
575 return 1;
576}
577
578static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200579astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900580{
581 switch (node_->kind) {
582 case Slice_kind:
583 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
584 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
585 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
586 break;
587 case ExtSlice_kind:
588 CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims);
589 break;
590 case Index_kind:
591 CALL(astfold_expr, expr_ty, node_->v.Index.value);
592 break;
593 default:
594 break;
595 }
596 return 1;
597}
598
599static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200600astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900601{
602 CALL(astfold_expr, expr_ty, node_->value);
603 return 1;
604}
605
606static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200607astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900608{
609 CALL(astfold_expr, expr_ty, node_->target);
610 CALL(astfold_expr, expr_ty, node_->iter);
611 CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200612
613 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900614 return 1;
615}
616
617static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200618astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900619{
620 CALL_SEQ(astfold_arg, arg_ty, node_->args);
621 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
622 CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
623 CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
624 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
625 CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
626 return 1;
627}
628
629static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200630astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900631{
632 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
633 return 1;
634}
635
636static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200637astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900638{
639 switch (node_->kind) {
640 case FunctionDef_kind:
641 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300642 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900643 CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
644 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
645 break;
646 case AsyncFunctionDef_kind:
647 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300648 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900649 CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
650 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
651 break;
652 case ClassDef_kind:
653 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
654 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300655 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900656 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
657 break;
658 case Return_kind:
659 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
660 break;
661 case Delete_kind:
662 CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
663 break;
664 case Assign_kind:
665 CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
666 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
667 break;
668 case AugAssign_kind:
669 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
670 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
671 break;
672 case AnnAssign_kind:
673 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
674 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
675 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
676 break;
677 case For_kind:
678 CALL(astfold_expr, expr_ty, node_->v.For.target);
679 CALL(astfold_expr, expr_ty, node_->v.For.iter);
680 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
681 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200682
683 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900684 break;
685 case AsyncFor_kind:
686 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
687 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
688 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
689 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
690 break;
691 case While_kind:
692 CALL(astfold_expr, expr_ty, node_->v.While.test);
693 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
694 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
695 break;
696 case If_kind:
697 CALL(astfold_expr, expr_ty, node_->v.If.test);
698 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
699 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
700 break;
701 case With_kind:
702 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
703 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
704 break;
705 case AsyncWith_kind:
706 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
707 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
708 break;
709 case Raise_kind:
710 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
711 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
712 break;
713 case Try_kind:
714 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
715 CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
716 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
717 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
718 break;
719 case Assert_kind:
720 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
721 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
722 break;
723 case Expr_kind:
724 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
725 break;
726 default:
727 break;
728 }
729 return 1;
730}
731
732static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200733astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900734{
735 switch (node_->kind) {
736 case ExceptHandler_kind:
737 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
738 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
739 break;
740 default:
741 break;
742 }
743 return 1;
744}
745
746static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200747astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900748{
749 CALL(astfold_expr, expr_ty, node_->context_expr);
750 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
751 return 1;
752}
753
754#undef CALL
755#undef CALL_OPT
756#undef CALL_SEQ
757#undef CALL_INT_SEQ
758
759int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200760_PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900761{
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200762 int ret = astfold_mod(mod, arena, optimize);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900763 assert(ret || PyErr_Occurred());
764 return ret;
765}