blob: 7a2b6e6aab11a7f85df5e40062fc0b9bf9a48dea [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;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900313
314 arg = node->v.Subscript.value;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200315 idx = node->v.Subscript.slice;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900316 if (node->v.Subscript.ctx != Load ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300317 arg->kind != Constant_kind ||
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200318 idx->kind != Constant_kind)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900319 {
320 return 1;
321 }
322
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300323 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900324 return make_const(node, newval, arena);
325}
326
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200327/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200328 tuple or frozenset respectively. Change literal list of
329 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200330 Used for right operand of "in" and "not in" tests and for iterable
331 in "for" loop and comprehensions.
332*/
333static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200334fold_iter(expr_ty arg, PyArena *arena, int optimize)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200335{
336 PyObject *newval;
337 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200338 /* First change a list into tuple. */
339 asdl_seq *elts = arg->v.List.elts;
340 Py_ssize_t n = asdl_seq_LEN(elts);
341 for (Py_ssize_t i = 0; i < n; i++) {
342 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
343 if (e->kind == Starred_kind) {
344 return 1;
345 }
346 }
347 expr_context_ty ctx = arg->v.List.ctx;
348 arg->kind = Tuple_kind;
349 arg->v.Tuple.elts = elts;
350 arg->v.Tuple.ctx = ctx;
351 /* Try to create a constant tuple. */
352 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200353 }
354 else if (arg->kind == Set_kind) {
355 newval = make_const_tuple(arg->v.Set.elts);
356 if (newval) {
357 Py_SETREF(newval, PyFrozenSet_New(newval));
358 }
359 }
360 else {
361 return 1;
362 }
363 return make_const(arg, newval, arena);
364}
365
INADA Naoki7ea143a2017-12-14 16:47:20 +0900366static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200367fold_compare(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900368{
369 asdl_int_seq *ops;
370 asdl_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100371 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900372
373 ops = node->v.Compare.ops;
374 args = node->v.Compare.comparators;
375 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200376 /* Change literal list or set in 'in' or 'not in' into
377 tuple or frozenset respectively. */
378 i = asdl_seq_LEN(ops) - 1;
379 int op = asdl_seq_GET(ops, i);
380 if (op == In || op == NotIn) {
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200381 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, optimize)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200382 return 0;
383 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900384 }
385 return 1;
386}
387
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200388static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_);
389static int astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_);
390static int astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_);
391static int astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_);
392static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_);
393static int astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_);
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200394static int astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_);
395static int astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_);
396static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900397#define CALL(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200398 if (!FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900399 return 0;
400
401#define CALL_OPT(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200402 if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900403 return 0;
404
405#define CALL_SEQ(FUNC, TYPE, ARG) { \
406 int i; \
407 asdl_seq *seq = (ARG); /* avoid variable capture */ \
408 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
409 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200410 if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900411 return 0; \
412 } \
413}
414
415#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
416 int i; \
417 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
418 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
419 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200420 if (!FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900421 return 0; \
422 } \
423}
424
425static int
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300426astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
427{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300428 int docstring = _PyAST_GetDocString(stmts) != NULL;
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300429 CALL_SEQ(astfold_stmt, stmt_ty, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300430 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
431 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300432 asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
433 if (!values) {
434 return 0;
435 }
436 asdl_seq_SET(values, 0, st->v.Expr.value);
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000437 expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
438 st->end_lineno, st->end_col_offset, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300439 if (!expr) {
440 return 0;
441 }
442 st->v.Expr.value = expr;
443 }
444 return 1;
445}
446
447static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200448astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900449{
450 switch (node_->kind) {
451 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300452 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900453 break;
454 case Interactive_kind:
455 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
456 break;
457 case Expression_kind:
458 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
459 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900460 default:
461 break;
462 }
463 return 1;
464}
465
466static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200467astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900468{
469 switch (node_->kind) {
470 case BoolOp_kind:
471 CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
472 break;
473 case BinOp_kind:
474 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
475 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
476 CALL(fold_binop, expr_ty, node_);
477 break;
478 case UnaryOp_kind:
479 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
480 CALL(fold_unaryop, expr_ty, node_);
481 break;
482 case Lambda_kind:
483 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
484 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
485 break;
486 case IfExp_kind:
487 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
488 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
489 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
490 break;
491 case Dict_kind:
492 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
493 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
494 break;
495 case Set_kind:
496 CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
497 break;
498 case ListComp_kind:
499 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
500 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
501 break;
502 case SetComp_kind:
503 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
504 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
505 break;
506 case DictComp_kind:
507 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
508 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
509 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
510 break;
511 case GeneratorExp_kind:
512 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
513 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
514 break;
515 case Await_kind:
516 CALL(astfold_expr, expr_ty, node_->v.Await.value);
517 break;
518 case Yield_kind:
519 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
520 break;
521 case YieldFrom_kind:
522 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
523 break;
524 case Compare_kind:
525 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
526 CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
527 CALL(fold_compare, expr_ty, node_);
528 break;
529 case Call_kind:
530 CALL(astfold_expr, expr_ty, node_->v.Call.func);
531 CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
532 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
533 break;
534 case FormattedValue_kind:
535 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
536 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
537 break;
538 case JoinedStr_kind:
539 CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
540 break;
541 case Attribute_kind:
542 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
543 break;
544 case Subscript_kind:
545 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200546 CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900547 CALL(fold_subscr, expr_ty, node_);
548 break;
549 case Starred_kind:
550 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
551 break;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200552 case Slice_kind:
553 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
554 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
555 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
556 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900557 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_keyword(keyword_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900577{
578 CALL(astfold_expr, expr_ty, node_->value);
579 return 1;
580}
581
582static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200583astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900584{
585 CALL(astfold_expr, expr_ty, node_->target);
586 CALL(astfold_expr, expr_ty, node_->iter);
587 CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200588
589 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900590 return 1;
591}
592
593static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200594astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900595{
Anthony Sottileb121a4a2020-01-05 12:03:56 -0500596 CALL_SEQ(astfold_arg, arg_ty, node_->posonlyargs);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900597 CALL_SEQ(astfold_arg, arg_ty, node_->args);
598 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
599 CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
600 CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
601 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
602 CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
603 return 1;
604}
605
606static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200607astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900608{
609 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
610 return 1;
611}
612
613static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200614astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900615{
616 switch (node_->kind) {
617 case FunctionDef_kind:
618 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300619 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900620 CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
621 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
622 break;
623 case AsyncFunctionDef_kind:
624 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300625 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900626 CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
627 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
628 break;
629 case ClassDef_kind:
630 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
631 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300632 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900633 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
634 break;
635 case Return_kind:
636 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
637 break;
638 case Delete_kind:
639 CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
640 break;
641 case Assign_kind:
642 CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
643 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
644 break;
645 case AugAssign_kind:
646 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
647 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
648 break;
649 case AnnAssign_kind:
650 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
651 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
652 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
653 break;
654 case For_kind:
655 CALL(astfold_expr, expr_ty, node_->v.For.target);
656 CALL(astfold_expr, expr_ty, node_->v.For.iter);
657 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
658 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200659
660 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900661 break;
662 case AsyncFor_kind:
663 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
664 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
665 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
666 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
667 break;
668 case While_kind:
669 CALL(astfold_expr, expr_ty, node_->v.While.test);
670 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
671 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
672 break;
673 case If_kind:
674 CALL(astfold_expr, expr_ty, node_->v.If.test);
675 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
676 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
677 break;
678 case With_kind:
679 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
680 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
681 break;
682 case AsyncWith_kind:
683 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
684 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
685 break;
686 case Raise_kind:
687 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
688 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
689 break;
690 case Try_kind:
691 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
692 CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
693 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
694 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
695 break;
696 case Assert_kind:
697 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
698 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
699 break;
700 case Expr_kind:
701 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
702 break;
703 default:
704 break;
705 }
706 return 1;
707}
708
709static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200710astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900711{
712 switch (node_->kind) {
713 case ExceptHandler_kind:
714 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
715 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
716 break;
717 default:
718 break;
719 }
720 return 1;
721}
722
723static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200724astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900725{
726 CALL(astfold_expr, expr_ty, node_->context_expr);
727 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
728 return 1;
729}
730
731#undef CALL
732#undef CALL_OPT
733#undef CALL_SEQ
734#undef CALL_INT_SEQ
735
736int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200737_PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900738{
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200739 int ret = astfold_mod(mod, arena, optimize);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900740 assert(ret || PyErr_Occurred());
741 return ret;
742}