blob: e92d6471f91dcde5316fca1c8dbd5808d3a1c9b2 [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
128static int
129fold_binop(expr_ty node, PyArena *arena)
130{
131 expr_ty lhs, rhs;
132 lhs = node->v.BinOp.left;
133 rhs = node->v.BinOp.right;
134 if (!is_const(lhs) || !is_const(rhs)) {
135 return 1;
136 }
137
138 PyObject *lv = get_const_value(lhs);
139 PyObject *rv = get_const_value(rhs);
140 PyObject *newval;
141
142 switch (node->v.BinOp.op) {
143 case Add:
144 newval = PyNumber_Add(lv, rv);
145 break;
146 case Sub:
147 newval = PyNumber_Subtract(lv, rv);
148 break;
149 case Mult:
150 newval = PyNumber_Multiply(lv, rv);
151 break;
152 case Div:
153 newval = PyNumber_TrueDivide(lv, rv);
154 break;
155 case FloorDiv:
156 newval = PyNumber_FloorDivide(lv, rv);
157 break;
158 case Mod:
159 newval = PyNumber_Remainder(lv, rv);
160 break;
161 case Pow:
162 newval = PyNumber_Power(lv, rv, Py_None);
163 break;
164 case LShift:
165 newval = PyNumber_Lshift(lv, rv);
166 break;
167 case RShift:
168 newval = PyNumber_Rshift(lv, rv);
169 break;
170 case BitOr:
171 newval = PyNumber_Or(lv, rv);
172 break;
173 case BitXor:
174 newval = PyNumber_Xor(lv, rv);
175 break;
176 case BitAnd:
177 newval = PyNumber_And(lv, rv);
178 break;
179 default: // Unknown operator
180 return 1;
181 }
182
183 if (newval == NULL) {
184 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
185 return 0;
186 }
187 PyErr_Clear();
188 return 1;
189 }
190
191 /* Avoid creating large constants. */
192 Py_ssize_t size = PyObject_Size(newval);
193 if (size == -1) {
194 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
195 Py_DECREF(newval);
196 return 0;
197 }
198 PyErr_Clear();
199 }
200 else if (size > 20) {
201 Py_DECREF(newval);
202 return 1;
203 }
204 return make_const(node, newval, arena);
205}
206
207static PyObject*
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200208make_const_tuple(asdl_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900209{
210 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
211 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
212 if (!is_const(e)) {
213 return NULL;
214 }
215 }
216
217 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
218 if (newval == NULL) {
219 return NULL;
220 }
221
222 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
223 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
224 PyObject *v = get_const_value(e);
225 Py_INCREF(v);
226 PyTuple_SET_ITEM(newval, i, v);
227 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900228 return newval;
229}
230
231static int
232fold_tuple(expr_ty node, PyArena *arena)
233{
234 PyObject *newval;
235
236 if (node->v.Tuple.ctx != Load)
237 return 1;
238
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200239 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900240 return make_const(node, newval, arena);
241}
242
243static int
244fold_subscr(expr_ty node, PyArena *arena)
245{
246 PyObject *newval;
247 expr_ty arg, idx;
248 slice_ty slice;
249
250 arg = node->v.Subscript.value;
251 slice = node->v.Subscript.slice;
252 if (node->v.Subscript.ctx != Load ||
253 !is_const(arg) ||
254 /* TODO: handle other types of slices */
255 slice->kind != Index_kind ||
256 !is_const(slice->v.Index.value))
257 {
258 return 1;
259 }
260
261 idx = slice->v.Index.value;
262 newval = PyObject_GetItem(get_const_value(arg), get_const_value(idx));
263 return make_const(node, newval, arena);
264}
265
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200266/* Change literal list or set of constants into constant
267 tuple or frozenset respectively.
268 Used for right operand of "in" and "not in" tests and for iterable
269 in "for" loop and comprehensions.
270*/
271static int
272fold_iter(expr_ty arg, PyArena *arena)
273{
274 PyObject *newval;
275 if (arg->kind == List_kind) {
276 newval = make_const_tuple(arg->v.List.elts);
277 }
278 else if (arg->kind == Set_kind) {
279 newval = make_const_tuple(arg->v.Set.elts);
280 if (newval) {
281 Py_SETREF(newval, PyFrozenSet_New(newval));
282 }
283 }
284 else {
285 return 1;
286 }
287 return make_const(arg, newval, arena);
288}
289
INADA Naoki7ea143a2017-12-14 16:47:20 +0900290static int
291fold_compare(expr_ty node, PyArena *arena)
292{
293 asdl_int_seq *ops;
294 asdl_seq *args;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900295 int i;
296
297 ops = node->v.Compare.ops;
298 args = node->v.Compare.comparators;
299 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200300 /* Change literal list or set in 'in' or 'not in' into
301 tuple or frozenset respectively. */
302 i = asdl_seq_LEN(ops) - 1;
303 int op = asdl_seq_GET(ops, i);
304 if (op == In || op == NotIn) {
305 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena)) {
306 return 0;
307 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900308 }
309 return 1;
310}
311
312static int astfold_mod(mod_ty node_, PyArena* ctx_);
313static int astfold_stmt(stmt_ty node_, PyArena* ctx_);
314static int astfold_expr(expr_ty node_, PyArena* ctx_);
315static int astfold_arguments(arguments_ty node_, PyArena* ctx_);
316static int astfold_comprehension(comprehension_ty node_, PyArena* ctx_);
317static int astfold_keyword(keyword_ty node_, PyArena* ctx_);
318static int astfold_slice(slice_ty node_, PyArena* ctx_);
319static int astfold_arg(arg_ty node_, PyArena* ctx_);
320static int astfold_withitem(withitem_ty node_, PyArena* ctx_);
321static int astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_);
322#define CALL(FUNC, TYPE, ARG) \
323 if (!FUNC((ARG), ctx_)) \
324 return 0;
325
326#define CALL_OPT(FUNC, TYPE, ARG) \
327 if ((ARG) != NULL && !FUNC((ARG), ctx_)) \
328 return 0;
329
330#define CALL_SEQ(FUNC, TYPE, ARG) { \
331 int i; \
332 asdl_seq *seq = (ARG); /* avoid variable capture */ \
333 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
334 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
335 if (elt != NULL && !FUNC(elt, ctx_)) \
336 return 0; \
337 } \
338}
339
340#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
341 int i; \
342 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
343 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
344 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
345 if (!FUNC(elt, ctx_)) \
346 return 0; \
347 } \
348}
349
350static int
351astfold_mod(mod_ty node_, PyArena* ctx_)
352{
353 switch (node_->kind) {
354 case Module_kind:
355 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Module.body);
356 break;
357 case Interactive_kind:
358 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
359 break;
360 case Expression_kind:
361 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
362 break;
363 case Suite_kind:
364 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Suite.body);
365 break;
366 default:
367 break;
368 }
369 return 1;
370}
371
372static int
373astfold_expr(expr_ty node_, PyArena* ctx_)
374{
375 switch (node_->kind) {
376 case BoolOp_kind:
377 CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
378 break;
379 case BinOp_kind:
380 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
381 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
382 CALL(fold_binop, expr_ty, node_);
383 break;
384 case UnaryOp_kind:
385 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
386 CALL(fold_unaryop, expr_ty, node_);
387 break;
388 case Lambda_kind:
389 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
390 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
391 break;
392 case IfExp_kind:
393 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
394 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
395 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
396 break;
397 case Dict_kind:
398 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
399 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
400 break;
401 case Set_kind:
402 CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
403 break;
404 case ListComp_kind:
405 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
406 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
407 break;
408 case SetComp_kind:
409 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
410 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
411 break;
412 case DictComp_kind:
413 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
414 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
415 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
416 break;
417 case GeneratorExp_kind:
418 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
419 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
420 break;
421 case Await_kind:
422 CALL(astfold_expr, expr_ty, node_->v.Await.value);
423 break;
424 case Yield_kind:
425 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
426 break;
427 case YieldFrom_kind:
428 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
429 break;
430 case Compare_kind:
431 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
432 CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
433 CALL(fold_compare, expr_ty, node_);
434 break;
435 case Call_kind:
436 CALL(astfold_expr, expr_ty, node_->v.Call.func);
437 CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
438 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
439 break;
440 case FormattedValue_kind:
441 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
442 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
443 break;
444 case JoinedStr_kind:
445 CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
446 break;
447 case Attribute_kind:
448 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
449 break;
450 case Subscript_kind:
451 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
452 CALL(astfold_slice, slice_ty, node_->v.Subscript.slice);
453 CALL(fold_subscr, expr_ty, node_);
454 break;
455 case Starred_kind:
456 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
457 break;
458 case List_kind:
459 CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
460 break;
461 case Tuple_kind:
462 CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
463 CALL(fold_tuple, expr_ty, node_);
464 break;
465 default:
466 break;
467 }
468 return 1;
469}
470
471static int
472astfold_slice(slice_ty node_, PyArena* ctx_)
473{
474 switch (node_->kind) {
475 case Slice_kind:
476 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
477 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
478 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
479 break;
480 case ExtSlice_kind:
481 CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims);
482 break;
483 case Index_kind:
484 CALL(astfold_expr, expr_ty, node_->v.Index.value);
485 break;
486 default:
487 break;
488 }
489 return 1;
490}
491
492static int
493astfold_keyword(keyword_ty node_, PyArena* ctx_)
494{
495 CALL(astfold_expr, expr_ty, node_->value);
496 return 1;
497}
498
499static int
500astfold_comprehension(comprehension_ty node_, PyArena* ctx_)
501{
502 CALL(astfold_expr, expr_ty, node_->target);
503 CALL(astfold_expr, expr_ty, node_->iter);
504 CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200505
506 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900507 return 1;
508}
509
510static int
511astfold_arguments(arguments_ty node_, PyArena* ctx_)
512{
513 CALL_SEQ(astfold_arg, arg_ty, node_->args);
514 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
515 CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
516 CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
517 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
518 CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
519 return 1;
520}
521
522static int
523astfold_arg(arg_ty node_, PyArena* ctx_)
524{
525 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
526 return 1;
527}
528
529static int
530astfold_stmt(stmt_ty node_, PyArena* ctx_)
531{
532 switch (node_->kind) {
533 case FunctionDef_kind:
534 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
535 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.FunctionDef.body);
536 CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
537 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
538 break;
539 case AsyncFunctionDef_kind:
540 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
541 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFunctionDef.body);
542 CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
543 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
544 break;
545 case ClassDef_kind:
546 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
547 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
548 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ClassDef.body);
549 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
550 break;
551 case Return_kind:
552 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
553 break;
554 case Delete_kind:
555 CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
556 break;
557 case Assign_kind:
558 CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
559 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
560 break;
561 case AugAssign_kind:
562 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
563 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
564 break;
565 case AnnAssign_kind:
566 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
567 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
568 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
569 break;
570 case For_kind:
571 CALL(astfold_expr, expr_ty, node_->v.For.target);
572 CALL(astfold_expr, expr_ty, node_->v.For.iter);
573 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
574 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200575
576 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900577 break;
578 case AsyncFor_kind:
579 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
580 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
581 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
582 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
583 break;
584 case While_kind:
585 CALL(astfold_expr, expr_ty, node_->v.While.test);
586 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
587 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
588 break;
589 case If_kind:
590 CALL(astfold_expr, expr_ty, node_->v.If.test);
591 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
592 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
593 break;
594 case With_kind:
595 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
596 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
597 break;
598 case AsyncWith_kind:
599 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
600 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
601 break;
602 case Raise_kind:
603 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
604 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
605 break;
606 case Try_kind:
607 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
608 CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
609 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
610 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
611 break;
612 case Assert_kind:
613 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
614 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
615 break;
616 case Expr_kind:
617 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
618 break;
619 default:
620 break;
621 }
622 return 1;
623}
624
625static int
626astfold_excepthandler(excepthandler_ty node_, PyArena* ctx_)
627{
628 switch (node_->kind) {
629 case ExceptHandler_kind:
630 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
631 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
632 break;
633 default:
634 break;
635 }
636 return 1;
637}
638
639static int
640astfold_withitem(withitem_ty node_, PyArena* ctx_)
641{
642 CALL(astfold_expr, expr_ty, node_->context_expr);
643 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
644 return 1;
645}
646
647#undef CALL
648#undef CALL_OPT
649#undef CALL_SEQ
650#undef CALL_INT_SEQ
651
652int
653_PyAST_Optimize(mod_ty mod, PyArena *arena)
654{
655 int ret = astfold_mod(mod, arena);
656 assert(ret || PyErr_Occurred());
657 return ret;
658}