blob: 39e164adb8c9495814d45cc0fd78dd3df6ac5059 [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 "ast.h"
INADA Naoki7ea143a2017-12-14 16:47:20 +09005
6
INADA Naoki7ea143a2017-12-14 16:47:20 +09007static int
8make_const(expr_ty node, PyObject *val, PyArena *arena)
9{
10 if (val == NULL) {
11 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
12 return 0;
13 }
14 PyErr_Clear();
15 return 1;
16 }
17 if (PyArena_AddPyObject(arena, val) < 0) {
18 Py_DECREF(val);
19 return 0;
20 }
21 node->kind = Constant_kind;
22 node->v.Constant.value = val;
23 return 1;
24}
25
26#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
27
28static PyObject*
29unary_not(PyObject *v)
30{
31 int r = PyObject_IsTrue(v);
32 if (r < 0)
33 return NULL;
34 return PyBool_FromLong(!r);
35}
36
37static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +020038fold_unaryop(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +090039{
40 expr_ty arg = node->v.UnaryOp.operand;
41
Serhiy Storchaka3f228112018-09-27 17:42:37 +030042 if (arg->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090043 /* Fold not into comparison */
44 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
45 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
46 /* Eq and NotEq are often implemented in terms of one another, so
47 folding not (self == other) into self != other breaks implementation
48 of !=. Detecting such cases doesn't seem worthwhile.
49 Python uses </> for 'is subset'/'is superset' operations on sets.
50 They don't satisfy not folding laws. */
51 int op = asdl_seq_GET(arg->v.Compare.ops, 0);
52 switch (op) {
53 case Is:
54 op = IsNot;
55 break;
56 case IsNot:
57 op = Is;
58 break;
59 case In:
60 op = NotIn;
61 break;
62 case NotIn:
63 op = In;
64 break;
65 default:
66 op = 0;
67 }
68 if (op) {
69 asdl_seq_SET(arg->v.Compare.ops, 0, op);
70 COPY_NODE(node, arg);
71 return 1;
72 }
73 }
74 return 1;
75 }
76
77 typedef PyObject *(*unary_op)(PyObject*);
78 static const unary_op ops[] = {
79 [Invert] = PyNumber_Invert,
80 [Not] = unary_not,
81 [UAdd] = PyNumber_Positive,
82 [USub] = PyNumber_Negative,
83 };
Serhiy Storchaka3f228112018-09-27 17:42:37 +030084 PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +090085 return make_const(node, newval, arena);
86}
87
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +020088/* Check whether a collection doesn't containing too much items (including
89 subcollections). This protects from creating a constant that needs
90 too much time for calculating a hash.
91 "limit" is the maximal number of items.
92 Returns the negative number if the total number of items exceeds the
93 limit. Otherwise returns the limit minus the total number of items.
94*/
95
96static Py_ssize_t
97check_complexity(PyObject *obj, Py_ssize_t limit)
98{
99 if (PyTuple_Check(obj)) {
100 Py_ssize_t i;
101 limit -= PyTuple_GET_SIZE(obj);
102 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
103 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
104 }
105 return limit;
106 }
107 else if (PyFrozenSet_Check(obj)) {
108 Py_ssize_t i = 0;
109 PyObject *item;
110 Py_hash_t hash;
111 limit -= PySet_GET_SIZE(obj);
112 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
113 limit = check_complexity(item, limit);
114 }
115 }
116 return limit;
117}
118
119#define MAX_INT_SIZE 128 /* bits */
120#define MAX_COLLECTION_SIZE 256 /* items */
121#define MAX_STR_SIZE 4096 /* characters */
122#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
123
124static PyObject *
125safe_multiply(PyObject *v, PyObject *w)
126{
127 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
128 size_t vbits = _PyLong_NumBits(v);
129 size_t wbits = _PyLong_NumBits(w);
130 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
131 return NULL;
132 }
133 if (vbits + wbits > MAX_INT_SIZE) {
134 return NULL;
135 }
136 }
137 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
138 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
139 PySet_GET_SIZE(w);
140 if (size) {
141 long n = PyLong_AsLong(v);
142 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
143 return NULL;
144 }
145 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
146 return NULL;
147 }
148 }
149 }
150 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
151 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
152 PyBytes_GET_SIZE(w);
153 if (size) {
154 long n = PyLong_AsLong(v);
155 if (n < 0 || n > MAX_STR_SIZE / size) {
156 return NULL;
157 }
158 }
159 }
160 else if (PyLong_Check(w) &&
161 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
162 PyUnicode_Check(v) || PyBytes_Check(v)))
163 {
164 return safe_multiply(w, v);
165 }
166
167 return PyNumber_Multiply(v, w);
168}
169
170static PyObject *
171safe_power(PyObject *v, PyObject *w)
172{
173 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
174 size_t vbits = _PyLong_NumBits(v);
175 size_t wbits = PyLong_AsSize_t(w);
176 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
177 return NULL;
178 }
179 if (vbits > MAX_INT_SIZE / wbits) {
180 return NULL;
181 }
182 }
183
184 return PyNumber_Power(v, w, Py_None);
185}
186
187static PyObject *
188safe_lshift(PyObject *v, PyObject *w)
189{
190 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
191 size_t vbits = _PyLong_NumBits(v);
192 size_t wbits = PyLong_AsSize_t(w);
193 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
194 return NULL;
195 }
196 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
197 return NULL;
198 }
199 }
200
201 return PyNumber_Lshift(v, w);
202}
203
204static PyObject *
205safe_mod(PyObject *v, PyObject *w)
206{
207 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
208 return NULL;
209 }
210
211 return PyNumber_Remainder(v, w);
212}
213
INADA Naoki7ea143a2017-12-14 16:47:20 +0900214static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200215fold_binop(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900216{
217 expr_ty lhs, rhs;
218 lhs = node->v.BinOp.left;
219 rhs = node->v.BinOp.right;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300220 if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900221 return 1;
222 }
223
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300224 PyObject *lv = lhs->v.Constant.value;
225 PyObject *rv = rhs->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900226 PyObject *newval;
227
228 switch (node->v.BinOp.op) {
229 case Add:
230 newval = PyNumber_Add(lv, rv);
231 break;
232 case Sub:
233 newval = PyNumber_Subtract(lv, rv);
234 break;
235 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200236 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900237 break;
238 case Div:
239 newval = PyNumber_TrueDivide(lv, rv);
240 break;
241 case FloorDiv:
242 newval = PyNumber_FloorDivide(lv, rv);
243 break;
244 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200245 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900246 break;
247 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200248 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900249 break;
250 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200251 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900252 break;
253 case RShift:
254 newval = PyNumber_Rshift(lv, rv);
255 break;
256 case BitOr:
257 newval = PyNumber_Or(lv, rv);
258 break;
259 case BitXor:
260 newval = PyNumber_Xor(lv, rv);
261 break;
262 case BitAnd:
263 newval = PyNumber_And(lv, rv);
264 break;
265 default: // Unknown operator
266 return 1;
267 }
268
INADA Naoki7ea143a2017-12-14 16:47:20 +0900269 return make_const(node, newval, arena);
270}
271
272static PyObject*
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200273make_const_tuple(asdl_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900274{
275 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
276 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300277 if (e->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900278 return NULL;
279 }
280 }
281
282 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
283 if (newval == NULL) {
284 return NULL;
285 }
286
287 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
288 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300289 PyObject *v = e->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900290 Py_INCREF(v);
291 PyTuple_SET_ITEM(newval, i, v);
292 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900293 return newval;
294}
295
296static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200297fold_tuple(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900298{
299 PyObject *newval;
300
301 if (node->v.Tuple.ctx != Load)
302 return 1;
303
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200304 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900305 return make_const(node, newval, arena);
306}
307
308static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200309fold_subscr(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900310{
311 PyObject *newval;
312 expr_ty arg, idx;
313 slice_ty slice;
314
315 arg = node->v.Subscript.value;
316 slice = node->v.Subscript.slice;
317 if (node->v.Subscript.ctx != Load ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300318 arg->kind != Constant_kind ||
INADA Naoki7ea143a2017-12-14 16:47:20 +0900319 /* TODO: handle other types of slices */
320 slice->kind != Index_kind ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300321 slice->v.Index.value->kind != Constant_kind)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900322 {
323 return 1;
324 }
325
326 idx = slice->v.Index.value;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300327 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900328 return make_const(node, newval, arena);
329}
330
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200331/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200332 tuple or frozenset respectively. Change literal list of
333 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200334 Used for right operand of "in" and "not in" tests and for iterable
335 in "for" loop and comprehensions.
336*/
337static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200338fold_iter(expr_ty arg, PyArena *arena, int optimize)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200339{
340 PyObject *newval;
341 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200342 /* First change a list into tuple. */
343 asdl_seq *elts = arg->v.List.elts;
344 Py_ssize_t n = asdl_seq_LEN(elts);
345 for (Py_ssize_t i = 0; i < n; i++) {
346 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
347 if (e->kind == Starred_kind) {
348 return 1;
349 }
350 }
351 expr_context_ty ctx = arg->v.List.ctx;
352 arg->kind = Tuple_kind;
353 arg->v.Tuple.elts = elts;
354 arg->v.Tuple.ctx = ctx;
355 /* Try to create a constant tuple. */
356 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200357 }
358 else if (arg->kind == Set_kind) {
359 newval = make_const_tuple(arg->v.Set.elts);
360 if (newval) {
361 Py_SETREF(newval, PyFrozenSet_New(newval));
362 }
363 }
364 else {
365 return 1;
366 }
367 return make_const(arg, newval, arena);
368}
369
INADA Naoki7ea143a2017-12-14 16:47:20 +0900370static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200371fold_compare(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900372{
373 asdl_int_seq *ops;
374 asdl_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100375 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900376
377 ops = node->v.Compare.ops;
378 args = node->v.Compare.comparators;
379 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200380 /* Change literal list or set in 'in' or 'not in' into
381 tuple or frozenset respectively. */
382 i = asdl_seq_LEN(ops) - 1;
383 int op = asdl_seq_GET(ops, i);
384 if (op == In || op == NotIn) {
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200385 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, optimize)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200386 return 0;
387 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900388 }
389 return 1;
390}
391
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200392static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_);
393static int astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_);
394static int astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_);
395static int astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_);
396static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_);
397static int astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_);
398static int astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_);
399static int astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_);
400static int astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_);
401static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900402#define CALL(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200403 if (!FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900404 return 0;
405
406#define CALL_OPT(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200407 if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900408 return 0;
409
410#define CALL_SEQ(FUNC, TYPE, ARG) { \
411 int i; \
412 asdl_seq *seq = (ARG); /* avoid variable capture */ \
413 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
414 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200415 if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900416 return 0; \
417 } \
418}
419
420#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
421 int i; \
422 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
423 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
424 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200425 if (!FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900426 return 0; \
427 } \
428}
429
430static int
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300431astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
432{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300433 int docstring = _PyAST_GetDocString(stmts) != NULL;
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300434 CALL_SEQ(astfold_stmt, stmt_ty, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300435 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
436 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300437 asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
438 if (!values) {
439 return 0;
440 }
441 asdl_seq_SET(values, 0, st->v.Expr.value);
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000442 expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
443 st->end_lineno, st->end_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;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900465 default:
466 break;
467 }
468 return 1;
469}
470
471static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200472astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900473{
474 switch (node_->kind) {
475 case BoolOp_kind:
476 CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
477 break;
478 case BinOp_kind:
479 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
480 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
481 CALL(fold_binop, expr_ty, node_);
482 break;
483 case UnaryOp_kind:
484 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
485 CALL(fold_unaryop, expr_ty, node_);
486 break;
487 case Lambda_kind:
488 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
489 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
490 break;
491 case IfExp_kind:
492 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
493 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
494 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
495 break;
496 case Dict_kind:
497 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
498 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
499 break;
500 case Set_kind:
501 CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
502 break;
503 case ListComp_kind:
504 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
505 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
506 break;
507 case SetComp_kind:
508 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
509 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
510 break;
511 case DictComp_kind:
512 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
513 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
514 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
515 break;
516 case GeneratorExp_kind:
517 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
518 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
519 break;
520 case Await_kind:
521 CALL(astfold_expr, expr_ty, node_->v.Await.value);
522 break;
523 case Yield_kind:
524 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
525 break;
526 case YieldFrom_kind:
527 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
528 break;
529 case Compare_kind:
530 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
531 CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
532 CALL(fold_compare, expr_ty, node_);
533 break;
534 case Call_kind:
535 CALL(astfold_expr, expr_ty, node_->v.Call.func);
536 CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
537 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
538 break;
539 case FormattedValue_kind:
540 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
541 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
542 break;
543 case JoinedStr_kind:
544 CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
545 break;
546 case Attribute_kind:
547 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
548 break;
549 case Subscript_kind:
550 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
551 CALL(astfold_slice, slice_ty, node_->v.Subscript.slice);
552 CALL(fold_subscr, expr_ty, node_);
553 break;
554 case Starred_kind:
555 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
556 break;
557 case List_kind:
558 CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
559 break;
560 case Tuple_kind:
561 CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
562 CALL(fold_tuple, expr_ty, node_);
563 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200564 case Name_kind:
565 if (_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
566 return make_const(node_, PyBool_FromLong(!optimize_), ctx_);
567 }
568 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900569 default:
570 break;
571 }
572 return 1;
573}
574
575static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200576astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900577{
578 switch (node_->kind) {
579 case Slice_kind:
580 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
581 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
582 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
583 break;
584 case ExtSlice_kind:
585 CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims);
586 break;
587 case Index_kind:
588 CALL(astfold_expr, expr_ty, node_->v.Index.value);
589 break;
590 default:
591 break;
592 }
593 return 1;
594}
595
596static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200597astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900598{
599 CALL(astfold_expr, expr_ty, node_->value);
600 return 1;
601}
602
603static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200604astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900605{
606 CALL(astfold_expr, expr_ty, node_->target);
607 CALL(astfold_expr, expr_ty, node_->iter);
608 CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200609
610 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900611 return 1;
612}
613
614static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200615astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900616{
Anthony Sottileb121a4a2020-01-05 12:03:56 -0500617 CALL_SEQ(astfold_arg, arg_ty, node_->posonlyargs);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900618 CALL_SEQ(astfold_arg, arg_ty, node_->args);
619 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
620 CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
621 CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
622 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
623 CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
624 return 1;
625}
626
627static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200628astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900629{
630 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
631 return 1;
632}
633
634static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200635astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900636{
637 switch (node_->kind) {
638 case FunctionDef_kind:
639 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300640 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900641 CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
642 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
643 break;
644 case AsyncFunctionDef_kind:
645 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300646 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900647 CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
648 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
649 break;
650 case ClassDef_kind:
651 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
652 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300653 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900654 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
655 break;
656 case Return_kind:
657 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
658 break;
659 case Delete_kind:
660 CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
661 break;
662 case Assign_kind:
663 CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
664 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
665 break;
666 case AugAssign_kind:
667 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
668 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
669 break;
670 case AnnAssign_kind:
671 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
672 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
673 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
674 break;
675 case For_kind:
676 CALL(astfold_expr, expr_ty, node_->v.For.target);
677 CALL(astfold_expr, expr_ty, node_->v.For.iter);
678 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
679 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200680
681 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900682 break;
683 case AsyncFor_kind:
684 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
685 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
686 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
687 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
688 break;
689 case While_kind:
690 CALL(astfold_expr, expr_ty, node_->v.While.test);
691 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
692 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
693 break;
694 case If_kind:
695 CALL(astfold_expr, expr_ty, node_->v.If.test);
696 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
697 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
698 break;
699 case With_kind:
700 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
701 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
702 break;
703 case AsyncWith_kind:
704 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
705 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
706 break;
707 case Raise_kind:
708 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
709 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
710 break;
711 case Try_kind:
712 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
713 CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
714 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
715 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
716 break;
717 case Assert_kind:
718 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
719 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
720 break;
721 case Expr_kind:
722 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
723 break;
724 default:
725 break;
726 }
727 return 1;
728}
729
730static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200731astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900732{
733 switch (node_->kind) {
734 case ExceptHandler_kind:
735 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
736 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
737 break;
738 default:
739 break;
740 }
741 return 1;
742}
743
744static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200745astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900746{
747 CALL(astfold_expr, expr_ty, node_->context_expr);
748 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
749 return 1;
750}
751
752#undef CALL
753#undef CALL_OPT
754#undef CALL_SEQ
755#undef CALL_INT_SEQ
756
757int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200758_PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900759{
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200760 int ret = astfold_mod(mod, arena, optimize);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900761 assert(ret || PyErr_Occurred());
762 return ret;
763}