blob: 2f659d085497e06da069be647068e87dceeba5d3 [file] [log] [blame]
INADA Naoki7ea143a2017-12-14 16:47:20 +09001/* AST Optimizer */
2#include "Python.h"
3#include "Python-ast.h"
4
5
6/* TODO: is_const and get_const_value are copied from Python/compile.c.
7 It should be deduped in the future. Maybe, we can include this file
8 from compile.c?
9*/
10static int
11is_const(expr_ty e)
12{
13 switch (e->kind) {
14 case Constant_kind:
15 case Num_kind:
16 case Str_kind:
17 case Bytes_kind:
18 case Ellipsis_kind:
19 case NameConstant_kind:
20 return 1;
21 default:
22 return 0;
23 }
24}
25
26static PyObject *
27get_const_value(expr_ty e)
28{
29 switch (e->kind) {
30 case Constant_kind:
31 return e->v.Constant.value;
32 case Num_kind:
33 return e->v.Num.n;
34 case Str_kind:
35 return e->v.Str.s;
36 case Bytes_kind:
37 return e->v.Bytes.s;
38 case Ellipsis_kind:
39 return Py_Ellipsis;
40 case NameConstant_kind:
41 return e->v.NameConstant.value;
42 default:
43 Py_UNREACHABLE();
44 }
45}
46
47static int
48make_const(expr_ty node, PyObject *val, PyArena *arena)
49{
50 if (val == NULL) {
51 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
52 return 0;
53 }
54 PyErr_Clear();
55 return 1;
56 }
57 if (PyArena_AddPyObject(arena, val) < 0) {
58 Py_DECREF(val);
59 return 0;
60 }
61 node->kind = Constant_kind;
62 node->v.Constant.value = val;
63 return 1;
64}
65
66#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
67
68static PyObject*
69unary_not(PyObject *v)
70{
71 int r = PyObject_IsTrue(v);
72 if (r < 0)
73 return NULL;
74 return PyBool_FromLong(!r);
75}
76
77static int
78fold_unaryop(expr_ty node, PyArena *arena)
79{
80 expr_ty arg = node->v.UnaryOp.operand;
81
82 if (!is_const(arg)) {
83 /* Fold not into comparison */
84 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
85 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
86 /* Eq and NotEq are often implemented in terms of one another, so
87 folding not (self == other) into self != other breaks implementation
88 of !=. Detecting such cases doesn't seem worthwhile.
89 Python uses </> for 'is subset'/'is superset' operations on sets.
90 They don't satisfy not folding laws. */
91 int op = asdl_seq_GET(arg->v.Compare.ops, 0);
92 switch (op) {
93 case Is:
94 op = IsNot;
95 break;
96 case IsNot:
97 op = Is;
98 break;
99 case In:
100 op = NotIn;
101 break;
102 case NotIn:
103 op = In;
104 break;
105 default:
106 op = 0;
107 }
108 if (op) {
109 asdl_seq_SET(arg->v.Compare.ops, 0, op);
110 COPY_NODE(node, arg);
111 return 1;
112 }
113 }
114 return 1;
115 }
116
117 typedef PyObject *(*unary_op)(PyObject*);
118 static const unary_op ops[] = {
119 [Invert] = PyNumber_Invert,
120 [Not] = unary_not,
121 [UAdd] = PyNumber_Positive,
122 [USub] = PyNumber_Negative,
123 };
124 PyObject *newval = ops[node->v.UnaryOp.op](get_const_value(arg));
125 return make_const(node, newval, arena);
126}
127
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200128/* Check whether a collection doesn't containing too much items (including
129 subcollections). This protects from creating a constant that needs
130 too much time for calculating a hash.
131 "limit" is the maximal number of items.
132 Returns the negative number if the total number of items exceeds the
133 limit. Otherwise returns the limit minus the total number of items.
134*/
135
136static Py_ssize_t
137check_complexity(PyObject *obj, Py_ssize_t limit)
138{
139 if (PyTuple_Check(obj)) {
140 Py_ssize_t i;
141 limit -= PyTuple_GET_SIZE(obj);
142 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
143 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
144 }
145 return limit;
146 }
147 else if (PyFrozenSet_Check(obj)) {
148 Py_ssize_t i = 0;
149 PyObject *item;
150 Py_hash_t hash;
151 limit -= PySet_GET_SIZE(obj);
152 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
153 limit = check_complexity(item, limit);
154 }
155 }
156 return limit;
157}
158
159#define MAX_INT_SIZE 128 /* bits */
160#define MAX_COLLECTION_SIZE 256 /* items */
161#define MAX_STR_SIZE 4096 /* characters */
162#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
163
164static PyObject *
165safe_multiply(PyObject *v, PyObject *w)
166{
167 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
168 size_t vbits = _PyLong_NumBits(v);
169 size_t wbits = _PyLong_NumBits(w);
170 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
171 return NULL;
172 }
173 if (vbits + wbits > MAX_INT_SIZE) {
174 return NULL;
175 }
176 }
177 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
178 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
179 PySet_GET_SIZE(w);
180 if (size) {
181 long n = PyLong_AsLong(v);
182 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
183 return NULL;
184 }
185 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
186 return NULL;
187 }
188 }
189 }
190 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
191 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
192 PyBytes_GET_SIZE(w);
193 if (size) {
194 long n = PyLong_AsLong(v);
195 if (n < 0 || n > MAX_STR_SIZE / size) {
196 return NULL;
197 }
198 }
199 }
200 else if (PyLong_Check(w) &&
201 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
202 PyUnicode_Check(v) || PyBytes_Check(v)))
203 {
204 return safe_multiply(w, v);
205 }
206
207 return PyNumber_Multiply(v, w);
208}
209
210static PyObject *
211safe_power(PyObject *v, PyObject *w)
212{
213 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
214 size_t vbits = _PyLong_NumBits(v);
215 size_t wbits = PyLong_AsSize_t(w);
216 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
217 return NULL;
218 }
219 if (vbits > MAX_INT_SIZE / wbits) {
220 return NULL;
221 }
222 }
223
224 return PyNumber_Power(v, w, Py_None);
225}
226
227static PyObject *
228safe_lshift(PyObject *v, PyObject *w)
229{
230 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
231 size_t vbits = _PyLong_NumBits(v);
232 size_t wbits = PyLong_AsSize_t(w);
233 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
234 return NULL;
235 }
236 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
237 return NULL;
238 }
239 }
240
241 return PyNumber_Lshift(v, w);
242}
243
244static PyObject *
245safe_mod(PyObject *v, PyObject *w)
246{
247 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
248 return NULL;
249 }
250
251 return PyNumber_Remainder(v, w);
252}
253
INADA Naoki7ea143a2017-12-14 16:47:20 +0900254static int
255fold_binop(expr_ty node, PyArena *arena)
256{
257 expr_ty lhs, rhs;
258 lhs = node->v.BinOp.left;
259 rhs = node->v.BinOp.right;
260 if (!is_const(lhs) || !is_const(rhs)) {
261 return 1;
262 }
263
264 PyObject *lv = get_const_value(lhs);
265 PyObject *rv = get_const_value(rhs);
266 PyObject *newval;
267
268 switch (node->v.BinOp.op) {
269 case Add:
270 newval = PyNumber_Add(lv, rv);
271 break;
272 case Sub:
273 newval = PyNumber_Subtract(lv, rv);
274 break;
275 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200276 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900277 break;
278 case Div:
279 newval = PyNumber_TrueDivide(lv, rv);
280 break;
281 case FloorDiv:
282 newval = PyNumber_FloorDivide(lv, rv);
283 break;
284 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200285 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900286 break;
287 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200288 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900289 break;
290 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200291 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900292 break;
293 case RShift:
294 newval = PyNumber_Rshift(lv, rv);
295 break;
296 case BitOr:
297 newval = PyNumber_Or(lv, rv);
298 break;
299 case BitXor:
300 newval = PyNumber_Xor(lv, rv);
301 break;
302 case BitAnd:
303 newval = PyNumber_And(lv, rv);
304 break;
305 default: // Unknown operator
306 return 1;
307 }
308
INADA Naoki7ea143a2017-12-14 16:47:20 +0900309 return make_const(node, newval, arena);
310}
311
312static PyObject*
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200313make_const_tuple(asdl_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900314{
315 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
316 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
317 if (!is_const(e)) {
318 return NULL;
319 }
320 }
321
322 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
323 if (newval == NULL) {
324 return NULL;
325 }
326
327 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
328 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
329 PyObject *v = get_const_value(e);
330 Py_INCREF(v);
331 PyTuple_SET_ITEM(newval, i, v);
332 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900333 return newval;
334}
335
336static int
337fold_tuple(expr_ty node, PyArena *arena)
338{
339 PyObject *newval;
340
341 if (node->v.Tuple.ctx != Load)
342 return 1;
343
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200344 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900345 return make_const(node, newval, arena);
346}
347
348static int
349fold_subscr(expr_ty node, PyArena *arena)
350{
351 PyObject *newval;
352 expr_ty arg, idx;
353 slice_ty slice;
354
355 arg = node->v.Subscript.value;
356 slice = node->v.Subscript.slice;
357 if (node->v.Subscript.ctx != Load ||
358 !is_const(arg) ||
359 /* TODO: handle other types of slices */
360 slice->kind != Index_kind ||
361 !is_const(slice->v.Index.value))
362 {
363 return 1;
364 }
365
366 idx = slice->v.Index.value;
367 newval = PyObject_GetItem(get_const_value(arg), get_const_value(idx));
368 return make_const(node, newval, arena);
369}
370
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200371/* Change literal list or set of constants into constant
372 tuple or frozenset respectively.
373 Used for right operand of "in" and "not in" tests and for iterable
374 in "for" loop and comprehensions.
375*/
376static int
377fold_iter(expr_ty arg, PyArena *arena)
378{
379 PyObject *newval;
380 if (arg->kind == List_kind) {
381 newval = make_const_tuple(arg->v.List.elts);
382 }
383 else if (arg->kind == Set_kind) {
384 newval = make_const_tuple(arg->v.Set.elts);
385 if (newval) {
386 Py_SETREF(newval, PyFrozenSet_New(newval));
387 }
388 }
389 else {
390 return 1;
391 }
392 return make_const(arg, newval, arena);
393}
394
INADA Naoki7ea143a2017-12-14 16:47:20 +0900395static int
396fold_compare(expr_ty node, PyArena *arena)
397{
398 asdl_int_seq *ops;
399 asdl_seq *args;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900400 int i;
401
402 ops = node->v.Compare.ops;
403 args = node->v.Compare.comparators;
404 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200405 /* Change literal list or set in 'in' or 'not in' into
406 tuple or frozenset respectively. */
407 i = asdl_seq_LEN(ops) - 1;
408 int op = asdl_seq_GET(ops, i);
409 if (op == In || op == NotIn) {
410 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena)) {
411 return 0;
412 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900413 }
414 return 1;
415}
416
417static int astfold_mod(mod_ty node_, PyArena* ctx_);
418static int astfold_stmt(stmt_ty node_, PyArena* ctx_);
419static int astfold_expr(expr_ty node_, PyArena* ctx_);
420static int astfold_arguments(arguments_ty node_, PyArena* ctx_);
421static int astfold_comprehension(comprehension_ty node_, PyArena* ctx_);
422static int astfold_keyword(keyword_ty node_, PyArena* ctx_);
423static int astfold_slice(slice_ty node_, PyArena* ctx_);
424static int astfold_arg(arg_ty node_, PyArena* ctx_);
425static int astfold_withitem(withitem_ty node_, PyArena* ctx_);
426static int astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_);
427#define CALL(FUNC, TYPE, ARG) \
428 if (!FUNC((ARG), ctx_)) \
429 return 0;
430
431#define CALL_OPT(FUNC, TYPE, ARG) \
432 if ((ARG) != NULL && !FUNC((ARG), ctx_)) \
433 return 0;
434
435#define CALL_SEQ(FUNC, TYPE, ARG) { \
436 int i; \
437 asdl_seq *seq = (ARG); /* avoid variable capture */ \
438 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
439 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
440 if (elt != NULL && !FUNC(elt, ctx_)) \
441 return 0; \
442 } \
443}
444
445#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
446 int i; \
447 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
448 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
449 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
450 if (!FUNC(elt, ctx_)) \
451 return 0; \
452 } \
453}
454
455static int
456astfold_mod(mod_ty node_, PyArena* ctx_)
457{
458 switch (node_->kind) {
459 case Module_kind:
460 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Module.body);
461 break;
462 case Interactive_kind:
463 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
464 break;
465 case Expression_kind:
466 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
467 break;
468 case Suite_kind:
469 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Suite.body);
470 break;
471 default:
472 break;
473 }
474 return 1;
475}
476
477static int
478astfold_expr(expr_ty node_, PyArena* ctx_)
479{
480 switch (node_->kind) {
481 case BoolOp_kind:
482 CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
483 break;
484 case BinOp_kind:
485 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
486 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
487 CALL(fold_binop, expr_ty, node_);
488 break;
489 case UnaryOp_kind:
490 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
491 CALL(fold_unaryop, expr_ty, node_);
492 break;
493 case Lambda_kind:
494 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
495 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
496 break;
497 case IfExp_kind:
498 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
499 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
500 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
501 break;
502 case Dict_kind:
503 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
504 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
505 break;
506 case Set_kind:
507 CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
508 break;
509 case ListComp_kind:
510 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
511 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
512 break;
513 case SetComp_kind:
514 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
515 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
516 break;
517 case DictComp_kind:
518 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
519 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
520 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
521 break;
522 case GeneratorExp_kind:
523 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
524 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
525 break;
526 case Await_kind:
527 CALL(astfold_expr, expr_ty, node_->v.Await.value);
528 break;
529 case Yield_kind:
530 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
531 break;
532 case YieldFrom_kind:
533 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
534 break;
535 case Compare_kind:
536 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
537 CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
538 CALL(fold_compare, expr_ty, node_);
539 break;
540 case Call_kind:
541 CALL(astfold_expr, expr_ty, node_->v.Call.func);
542 CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
543 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
544 break;
545 case FormattedValue_kind:
546 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
547 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
548 break;
549 case JoinedStr_kind:
550 CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
551 break;
552 case Attribute_kind:
553 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
554 break;
555 case Subscript_kind:
556 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
557 CALL(astfold_slice, slice_ty, node_->v.Subscript.slice);
558 CALL(fold_subscr, expr_ty, node_);
559 break;
560 case Starred_kind:
561 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
562 break;
563 case List_kind:
564 CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
565 break;
566 case Tuple_kind:
567 CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
568 CALL(fold_tuple, expr_ty, node_);
569 break;
570 default:
571 break;
572 }
573 return 1;
574}
575
576static int
577astfold_slice(slice_ty node_, PyArena* ctx_)
578{
579 switch (node_->kind) {
580 case Slice_kind:
581 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
582 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
583 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
584 break;
585 case ExtSlice_kind:
586 CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims);
587 break;
588 case Index_kind:
589 CALL(astfold_expr, expr_ty, node_->v.Index.value);
590 break;
591 default:
592 break;
593 }
594 return 1;
595}
596
597static int
598astfold_keyword(keyword_ty node_, PyArena* ctx_)
599{
600 CALL(astfold_expr, expr_ty, node_->value);
601 return 1;
602}
603
604static int
605astfold_comprehension(comprehension_ty node_, PyArena* ctx_)
606{
607 CALL(astfold_expr, expr_ty, node_->target);
608 CALL(astfold_expr, expr_ty, node_->iter);
609 CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200610
611 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900612 return 1;
613}
614
615static int
616astfold_arguments(arguments_ty node_, PyArena* ctx_)
617{
618 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
628astfold_arg(arg_ty node_, PyArena* ctx_)
629{
630 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
631 return 1;
632}
633
634static int
635astfold_stmt(stmt_ty node_, PyArena* ctx_)
636{
637 switch (node_->kind) {
638 case FunctionDef_kind:
639 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
640 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.FunctionDef.body);
641 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);
646 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFunctionDef.body);
647 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);
653 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ClassDef.body);
654 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
731astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_)
732{
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
745astfold_withitem(withitem_ty node_, PyArena* ctx_)
746{
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
758_PyAST_Optimize(mod_ty mod, PyArena *arena)
759{
760 int ret = astfold_mod(mod, arena);
761 assert(ret || PyErr_Occurred());
762 return ret;
763}