blob: 5e57638e3d017241b08b3851a99161c42a263e7c [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
8/* TODO: is_const and get_const_value are copied from Python/compile.c.
9 It should be deduped in the future. Maybe, we can include this file
10 from compile.c?
11*/
12static int
13is_const(expr_ty e)
14{
15 switch (e->kind) {
16 case Constant_kind:
17 case Num_kind:
18 case Str_kind:
19 case Bytes_kind:
20 case Ellipsis_kind:
21 case NameConstant_kind:
22 return 1;
23 default:
24 return 0;
25 }
26}
27
28static PyObject *
29get_const_value(expr_ty e)
30{
31 switch (e->kind) {
32 case Constant_kind:
33 return e->v.Constant.value;
34 case Num_kind:
35 return e->v.Num.n;
36 case Str_kind:
37 return e->v.Str.s;
38 case Bytes_kind:
39 return e->v.Bytes.s;
40 case Ellipsis_kind:
41 return Py_Ellipsis;
42 case NameConstant_kind:
43 return e->v.NameConstant.value;
44 default:
45 Py_UNREACHABLE();
46 }
47}
48
49static int
50make_const(expr_ty node, PyObject *val, PyArena *arena)
51{
52 if (val == NULL) {
53 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
54 return 0;
55 }
56 PyErr_Clear();
57 return 1;
58 }
59 if (PyArena_AddPyObject(arena, val) < 0) {
60 Py_DECREF(val);
61 return 0;
62 }
63 node->kind = Constant_kind;
64 node->v.Constant.value = val;
65 return 1;
66}
67
68#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
69
70static PyObject*
71unary_not(PyObject *v)
72{
73 int r = PyObject_IsTrue(v);
74 if (r < 0)
75 return NULL;
76 return PyBool_FromLong(!r);
77}
78
79static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +020080fold_unaryop(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +090081{
82 expr_ty arg = node->v.UnaryOp.operand;
83
84 if (!is_const(arg)) {
85 /* Fold not into comparison */
86 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
87 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
88 /* Eq and NotEq are often implemented in terms of one another, so
89 folding not (self == other) into self != other breaks implementation
90 of !=. Detecting such cases doesn't seem worthwhile.
91 Python uses </> for 'is subset'/'is superset' operations on sets.
92 They don't satisfy not folding laws. */
93 int op = asdl_seq_GET(arg->v.Compare.ops, 0);
94 switch (op) {
95 case Is:
96 op = IsNot;
97 break;
98 case IsNot:
99 op = Is;
100 break;
101 case In:
102 op = NotIn;
103 break;
104 case NotIn:
105 op = In;
106 break;
107 default:
108 op = 0;
109 }
110 if (op) {
111 asdl_seq_SET(arg->v.Compare.ops, 0, op);
112 COPY_NODE(node, arg);
113 return 1;
114 }
115 }
116 return 1;
117 }
118
119 typedef PyObject *(*unary_op)(PyObject*);
120 static const unary_op ops[] = {
121 [Invert] = PyNumber_Invert,
122 [Not] = unary_not,
123 [UAdd] = PyNumber_Positive,
124 [USub] = PyNumber_Negative,
125 };
126 PyObject *newval = ops[node->v.UnaryOp.op](get_const_value(arg));
127 return make_const(node, newval, arena);
128}
129
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200130/* Check whether a collection doesn't containing too much items (including
131 subcollections). This protects from creating a constant that needs
132 too much time for calculating a hash.
133 "limit" is the maximal number of items.
134 Returns the negative number if the total number of items exceeds the
135 limit. Otherwise returns the limit minus the total number of items.
136*/
137
138static Py_ssize_t
139check_complexity(PyObject *obj, Py_ssize_t limit)
140{
141 if (PyTuple_Check(obj)) {
142 Py_ssize_t i;
143 limit -= PyTuple_GET_SIZE(obj);
144 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
145 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
146 }
147 return limit;
148 }
149 else if (PyFrozenSet_Check(obj)) {
150 Py_ssize_t i = 0;
151 PyObject *item;
152 Py_hash_t hash;
153 limit -= PySet_GET_SIZE(obj);
154 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
155 limit = check_complexity(item, limit);
156 }
157 }
158 return limit;
159}
160
161#define MAX_INT_SIZE 128 /* bits */
162#define MAX_COLLECTION_SIZE 256 /* items */
163#define MAX_STR_SIZE 4096 /* characters */
164#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
165
166static PyObject *
167safe_multiply(PyObject *v, PyObject *w)
168{
169 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
170 size_t vbits = _PyLong_NumBits(v);
171 size_t wbits = _PyLong_NumBits(w);
172 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
173 return NULL;
174 }
175 if (vbits + wbits > MAX_INT_SIZE) {
176 return NULL;
177 }
178 }
179 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
180 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
181 PySet_GET_SIZE(w);
182 if (size) {
183 long n = PyLong_AsLong(v);
184 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
185 return NULL;
186 }
187 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
188 return NULL;
189 }
190 }
191 }
192 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
193 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
194 PyBytes_GET_SIZE(w);
195 if (size) {
196 long n = PyLong_AsLong(v);
197 if (n < 0 || n > MAX_STR_SIZE / size) {
198 return NULL;
199 }
200 }
201 }
202 else if (PyLong_Check(w) &&
203 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
204 PyUnicode_Check(v) || PyBytes_Check(v)))
205 {
206 return safe_multiply(w, v);
207 }
208
209 return PyNumber_Multiply(v, w);
210}
211
212static PyObject *
213safe_power(PyObject *v, PyObject *w)
214{
215 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
216 size_t vbits = _PyLong_NumBits(v);
217 size_t wbits = PyLong_AsSize_t(w);
218 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
219 return NULL;
220 }
221 if (vbits > MAX_INT_SIZE / wbits) {
222 return NULL;
223 }
224 }
225
226 return PyNumber_Power(v, w, Py_None);
227}
228
229static PyObject *
230safe_lshift(PyObject *v, PyObject *w)
231{
232 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
233 size_t vbits = _PyLong_NumBits(v);
234 size_t wbits = PyLong_AsSize_t(w);
235 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
236 return NULL;
237 }
238 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
239 return NULL;
240 }
241 }
242
243 return PyNumber_Lshift(v, w);
244}
245
246static PyObject *
247safe_mod(PyObject *v, PyObject *w)
248{
249 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
250 return NULL;
251 }
252
253 return PyNumber_Remainder(v, w);
254}
255
INADA Naoki7ea143a2017-12-14 16:47:20 +0900256static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200257fold_binop(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900258{
259 expr_ty lhs, rhs;
260 lhs = node->v.BinOp.left;
261 rhs = node->v.BinOp.right;
262 if (!is_const(lhs) || !is_const(rhs)) {
263 return 1;
264 }
265
266 PyObject *lv = get_const_value(lhs);
267 PyObject *rv = get_const_value(rhs);
268 PyObject *newval;
269
270 switch (node->v.BinOp.op) {
271 case Add:
272 newval = PyNumber_Add(lv, rv);
273 break;
274 case Sub:
275 newval = PyNumber_Subtract(lv, rv);
276 break;
277 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200278 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900279 break;
280 case Div:
281 newval = PyNumber_TrueDivide(lv, rv);
282 break;
283 case FloorDiv:
284 newval = PyNumber_FloorDivide(lv, rv);
285 break;
286 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200287 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900288 break;
289 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200290 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900291 break;
292 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200293 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900294 break;
295 case RShift:
296 newval = PyNumber_Rshift(lv, rv);
297 break;
298 case BitOr:
299 newval = PyNumber_Or(lv, rv);
300 break;
301 case BitXor:
302 newval = PyNumber_Xor(lv, rv);
303 break;
304 case BitAnd:
305 newval = PyNumber_And(lv, rv);
306 break;
307 default: // Unknown operator
308 return 1;
309 }
310
INADA Naoki7ea143a2017-12-14 16:47:20 +0900311 return make_const(node, newval, arena);
312}
313
314static PyObject*
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200315make_const_tuple(asdl_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900316{
317 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
318 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
319 if (!is_const(e)) {
320 return NULL;
321 }
322 }
323
324 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
325 if (newval == NULL) {
326 return NULL;
327 }
328
329 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
330 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
331 PyObject *v = get_const_value(e);
332 Py_INCREF(v);
333 PyTuple_SET_ITEM(newval, i, v);
334 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900335 return newval;
336}
337
338static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200339fold_tuple(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900340{
341 PyObject *newval;
342
343 if (node->v.Tuple.ctx != Load)
344 return 1;
345
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200346 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900347 return make_const(node, newval, arena);
348}
349
350static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200351fold_subscr(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900352{
353 PyObject *newval;
354 expr_ty arg, idx;
355 slice_ty slice;
356
357 arg = node->v.Subscript.value;
358 slice = node->v.Subscript.slice;
359 if (node->v.Subscript.ctx != Load ||
360 !is_const(arg) ||
361 /* TODO: handle other types of slices */
362 slice->kind != Index_kind ||
363 !is_const(slice->v.Index.value))
364 {
365 return 1;
366 }
367
368 idx = slice->v.Index.value;
369 newval = PyObject_GetItem(get_const_value(arg), get_const_value(idx));
370 return make_const(node, newval, arena);
371}
372
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200373/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200374 tuple or frozenset respectively. Change literal list of
375 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200376 Used for right operand of "in" and "not in" tests and for iterable
377 in "for" loop and comprehensions.
378*/
379static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200380fold_iter(expr_ty arg, PyArena *arena, int optimize)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200381{
382 PyObject *newval;
383 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200384 /* First change a list into tuple. */
385 asdl_seq *elts = arg->v.List.elts;
386 Py_ssize_t n = asdl_seq_LEN(elts);
387 for (Py_ssize_t i = 0; i < n; i++) {
388 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
389 if (e->kind == Starred_kind) {
390 return 1;
391 }
392 }
393 expr_context_ty ctx = arg->v.List.ctx;
394 arg->kind = Tuple_kind;
395 arg->v.Tuple.elts = elts;
396 arg->v.Tuple.ctx = ctx;
397 /* Try to create a constant tuple. */
398 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200399 }
400 else if (arg->kind == Set_kind) {
401 newval = make_const_tuple(arg->v.Set.elts);
402 if (newval) {
403 Py_SETREF(newval, PyFrozenSet_New(newval));
404 }
405 }
406 else {
407 return 1;
408 }
409 return make_const(arg, newval, arena);
410}
411
INADA Naoki7ea143a2017-12-14 16:47:20 +0900412static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200413fold_compare(expr_ty node, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900414{
415 asdl_int_seq *ops;
416 asdl_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100417 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900418
419 ops = node->v.Compare.ops;
420 args = node->v.Compare.comparators;
421 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200422 /* Change literal list or set in 'in' or 'not in' into
423 tuple or frozenset respectively. */
424 i = asdl_seq_LEN(ops) - 1;
425 int op = asdl_seq_GET(ops, i);
426 if (op == In || op == NotIn) {
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200427 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, optimize)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200428 return 0;
429 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900430 }
431 return 1;
432}
433
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200434static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_);
435static int astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_);
436static int astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_);
437static int astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_);
438static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_);
439static int astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_);
440static int astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_);
441static int astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_);
442static int astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_);
443static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900444#define CALL(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200445 if (!FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900446 return 0;
447
448#define CALL_OPT(FUNC, TYPE, ARG) \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200449 if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900450 return 0;
451
452#define CALL_SEQ(FUNC, TYPE, ARG) { \
453 int i; \
454 asdl_seq *seq = (ARG); /* avoid variable capture */ \
455 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
456 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200457 if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900458 return 0; \
459 } \
460}
461
462#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
463 int i; \
464 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
465 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
466 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200467 if (!FUNC(elt, ctx_, optimize_)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900468 return 0; \
469 } \
470}
471
472static int
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300473astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
474{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300475 int docstring = _PyAST_GetDocString(stmts) != NULL;
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300476 CALL_SEQ(astfold_stmt, stmt_ty, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300477 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
478 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300479 asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
480 if (!values) {
481 return 0;
482 }
483 asdl_seq_SET(values, 0, st->v.Expr.value);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300484 expr_ty expr = JoinedStr(values, st->lineno, st->col_offset, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300485 if (!expr) {
486 return 0;
487 }
488 st->v.Expr.value = expr;
489 }
490 return 1;
491}
492
493static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200494astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900495{
496 switch (node_->kind) {
497 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300498 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900499 break;
500 case Interactive_kind:
501 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
502 break;
503 case Expression_kind:
504 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
505 break;
506 case Suite_kind:
507 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Suite.body);
508 break;
509 default:
510 break;
511 }
512 return 1;
513}
514
515static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200516astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900517{
518 switch (node_->kind) {
519 case BoolOp_kind:
520 CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
521 break;
522 case BinOp_kind:
523 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
524 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
525 CALL(fold_binop, expr_ty, node_);
526 break;
527 case UnaryOp_kind:
528 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
529 CALL(fold_unaryop, expr_ty, node_);
530 break;
531 case Lambda_kind:
532 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
533 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
534 break;
535 case IfExp_kind:
536 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
537 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
538 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
539 break;
540 case Dict_kind:
541 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
542 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
543 break;
544 case Set_kind:
545 CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
546 break;
547 case ListComp_kind:
548 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
549 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
550 break;
551 case SetComp_kind:
552 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
553 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
554 break;
555 case DictComp_kind:
556 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
557 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
558 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
559 break;
560 case GeneratorExp_kind:
561 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
562 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
563 break;
564 case Await_kind:
565 CALL(astfold_expr, expr_ty, node_->v.Await.value);
566 break;
567 case Yield_kind:
568 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
569 break;
570 case YieldFrom_kind:
571 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
572 break;
573 case Compare_kind:
574 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
575 CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
576 CALL(fold_compare, expr_ty, node_);
577 break;
578 case Call_kind:
579 CALL(astfold_expr, expr_ty, node_->v.Call.func);
580 CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
581 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
582 break;
583 case FormattedValue_kind:
584 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
585 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
586 break;
587 case JoinedStr_kind:
588 CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
589 break;
590 case Attribute_kind:
591 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
592 break;
593 case Subscript_kind:
594 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
595 CALL(astfold_slice, slice_ty, node_->v.Subscript.slice);
596 CALL(fold_subscr, expr_ty, node_);
597 break;
598 case Starred_kind:
599 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
600 break;
601 case List_kind:
602 CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
603 break;
604 case Tuple_kind:
605 CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
606 CALL(fold_tuple, expr_ty, node_);
607 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200608 case Name_kind:
609 if (_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
610 return make_const(node_, PyBool_FromLong(!optimize_), ctx_);
611 }
612 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900613 default:
614 break;
615 }
616 return 1;
617}
618
619static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200620astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900621{
622 switch (node_->kind) {
623 case Slice_kind:
624 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
625 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
626 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
627 break;
628 case ExtSlice_kind:
629 CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims);
630 break;
631 case Index_kind:
632 CALL(astfold_expr, expr_ty, node_->v.Index.value);
633 break;
634 default:
635 break;
636 }
637 return 1;
638}
639
640static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200641astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900642{
643 CALL(astfold_expr, expr_ty, node_->value);
644 return 1;
645}
646
647static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200648astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900649{
650 CALL(astfold_expr, expr_ty, node_->target);
651 CALL(astfold_expr, expr_ty, node_->iter);
652 CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200653
654 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900655 return 1;
656}
657
658static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200659astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900660{
661 CALL_SEQ(astfold_arg, arg_ty, node_->args);
662 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
663 CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
664 CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
665 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
666 CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
667 return 1;
668}
669
670static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200671astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900672{
673 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
674 return 1;
675}
676
677static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200678astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900679{
680 switch (node_->kind) {
681 case FunctionDef_kind:
682 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300683 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900684 CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
685 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
686 break;
687 case AsyncFunctionDef_kind:
688 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300689 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900690 CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
691 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
692 break;
693 case ClassDef_kind:
694 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
695 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300696 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900697 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
698 break;
699 case Return_kind:
700 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
701 break;
702 case Delete_kind:
703 CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
704 break;
705 case Assign_kind:
706 CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
707 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
708 break;
709 case AugAssign_kind:
710 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
711 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
712 break;
713 case AnnAssign_kind:
714 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
715 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
716 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
717 break;
718 case For_kind:
719 CALL(astfold_expr, expr_ty, node_->v.For.target);
720 CALL(astfold_expr, expr_ty, node_->v.For.iter);
721 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
722 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200723
724 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900725 break;
726 case AsyncFor_kind:
727 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
728 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
729 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
730 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
731 break;
732 case While_kind:
733 CALL(astfold_expr, expr_ty, node_->v.While.test);
734 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
735 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
736 break;
737 case If_kind:
738 CALL(astfold_expr, expr_ty, node_->v.If.test);
739 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
740 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
741 break;
742 case With_kind:
743 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
744 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
745 break;
746 case AsyncWith_kind:
747 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
748 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
749 break;
750 case Raise_kind:
751 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
752 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
753 break;
754 case Try_kind:
755 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
756 CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
757 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
758 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
759 break;
760 case Assert_kind:
761 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
762 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
763 break;
764 case Expr_kind:
765 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
766 break;
767 default:
768 break;
769 }
770 return 1;
771}
772
773static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200774astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900775{
776 switch (node_->kind) {
777 case ExceptHandler_kind:
778 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
779 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
780 break;
781 default:
782 break;
783 }
784 return 1;
785}
786
787static int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200788astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900789{
790 CALL(astfold_expr, expr_ty, node_->context_expr);
791 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
792 return 1;
793}
794
795#undef CALL
796#undef CALL_OPT
797#undef CALL_SEQ
798#undef CALL_INT_SEQ
799
800int
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200801_PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900802{
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200803 int ret = astfold_mod(mod, arena, optimize);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900804 assert(ret || PyErr_Occurred());
805 return ret;
806}