1 /* AST Optimizer */
2 #include "Python.h"
3 #include "Python-ast.h"
4 #include "ast.h"
5
6
7 static int
make_const(expr_ty node,PyObject * val,PyArena * arena)8 make_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.kind = NULL;
23 node->v.Constant.value = val;
24 return 1;
25 }
26
27 #define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
28
29 static PyObject*
unary_not(PyObject * v)30 unary_not(PyObject *v)
31 {
32 int r = PyObject_IsTrue(v);
33 if (r < 0)
34 return NULL;
35 return PyBool_FromLong(!r);
36 }
37
38 static int
fold_unaryop(expr_ty node,PyArena * arena,_PyASTOptimizeState * state)39 fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
40 {
41 expr_ty arg = node->v.UnaryOp.operand;
42
43 if (arg->kind != Constant_kind) {
44 /* Fold not into comparison */
45 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
46 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
47 /* Eq and NotEq are often implemented in terms of one another, so
48 folding not (self == other) into self != other breaks implementation
49 of !=. Detecting such cases doesn't seem worthwhile.
50 Python uses </> for 'is subset'/'is superset' operations on sets.
51 They don't satisfy not folding laws. */
52 int op = asdl_seq_GET(arg->v.Compare.ops, 0);
53 switch (op) {
54 case Is:
55 op = IsNot;
56 break;
57 case IsNot:
58 op = Is;
59 break;
60 case In:
61 op = NotIn;
62 break;
63 case NotIn:
64 op = In;
65 break;
66 default:
67 op = 0;
68 }
69 if (op) {
70 asdl_seq_SET(arg->v.Compare.ops, 0, op);
71 COPY_NODE(node, arg);
72 return 1;
73 }
74 }
75 return 1;
76 }
77
78 typedef PyObject *(*unary_op)(PyObject*);
79 static const unary_op ops[] = {
80 [Invert] = PyNumber_Invert,
81 [Not] = unary_not,
82 [UAdd] = PyNumber_Positive,
83 [USub] = PyNumber_Negative,
84 };
85 PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
86 return make_const(node, newval, arena);
87 }
88
89 /* Check whether a collection doesn't containing too much items (including
90 subcollections). This protects from creating a constant that needs
91 too much time for calculating a hash.
92 "limit" is the maximal number of items.
93 Returns the negative number if the total number of items exceeds the
94 limit. Otherwise returns the limit minus the total number of items.
95 */
96
97 static Py_ssize_t
check_complexity(PyObject * obj,Py_ssize_t limit)98 check_complexity(PyObject *obj, Py_ssize_t limit)
99 {
100 if (PyTuple_Check(obj)) {
101 Py_ssize_t i;
102 limit -= PyTuple_GET_SIZE(obj);
103 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
104 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
105 }
106 return limit;
107 }
108 else if (PyFrozenSet_Check(obj)) {
109 Py_ssize_t i = 0;
110 PyObject *item;
111 Py_hash_t hash;
112 limit -= PySet_GET_SIZE(obj);
113 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
114 limit = check_complexity(item, limit);
115 }
116 }
117 return limit;
118 }
119
120 #define MAX_INT_SIZE 128 /* bits */
121 #define MAX_COLLECTION_SIZE 256 /* items */
122 #define MAX_STR_SIZE 4096 /* characters */
123 #define MAX_TOTAL_ITEMS 1024 /* including nested collections */
124
125 static PyObject *
safe_multiply(PyObject * v,PyObject * w)126 safe_multiply(PyObject *v, PyObject *w)
127 {
128 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
129 size_t vbits = _PyLong_NumBits(v);
130 size_t wbits = _PyLong_NumBits(w);
131 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
132 return NULL;
133 }
134 if (vbits + wbits > MAX_INT_SIZE) {
135 return NULL;
136 }
137 }
138 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
139 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
140 PySet_GET_SIZE(w);
141 if (size) {
142 long n = PyLong_AsLong(v);
143 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
144 return NULL;
145 }
146 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
147 return NULL;
148 }
149 }
150 }
151 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
152 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
153 PyBytes_GET_SIZE(w);
154 if (size) {
155 long n = PyLong_AsLong(v);
156 if (n < 0 || n > MAX_STR_SIZE / size) {
157 return NULL;
158 }
159 }
160 }
161 else if (PyLong_Check(w) &&
162 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
163 PyUnicode_Check(v) || PyBytes_Check(v)))
164 {
165 return safe_multiply(w, v);
166 }
167
168 return PyNumber_Multiply(v, w);
169 }
170
171 static PyObject *
safe_power(PyObject * v,PyObject * w)172 safe_power(PyObject *v, PyObject *w)
173 {
174 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
175 size_t vbits = _PyLong_NumBits(v);
176 size_t wbits = PyLong_AsSize_t(w);
177 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
178 return NULL;
179 }
180 if (vbits > MAX_INT_SIZE / wbits) {
181 return NULL;
182 }
183 }
184
185 return PyNumber_Power(v, w, Py_None);
186 }
187
188 static PyObject *
safe_lshift(PyObject * v,PyObject * w)189 safe_lshift(PyObject *v, PyObject *w)
190 {
191 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
192 size_t vbits = _PyLong_NumBits(v);
193 size_t wbits = PyLong_AsSize_t(w);
194 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
195 return NULL;
196 }
197 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
198 return NULL;
199 }
200 }
201
202 return PyNumber_Lshift(v, w);
203 }
204
205 static PyObject *
safe_mod(PyObject * v,PyObject * w)206 safe_mod(PyObject *v, PyObject *w)
207 {
208 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
209 return NULL;
210 }
211
212 return PyNumber_Remainder(v, w);
213 }
214
215 static int
fold_binop(expr_ty node,PyArena * arena,_PyASTOptimizeState * state)216 fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
217 {
218 expr_ty lhs, rhs;
219 lhs = node->v.BinOp.left;
220 rhs = node->v.BinOp.right;
221 if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
222 return 1;
223 }
224
225 PyObject *lv = lhs->v.Constant.value;
226 PyObject *rv = rhs->v.Constant.value;
227 PyObject *newval;
228
229 switch (node->v.BinOp.op) {
230 case Add:
231 newval = PyNumber_Add(lv, rv);
232 break;
233 case Sub:
234 newval = PyNumber_Subtract(lv, rv);
235 break;
236 case Mult:
237 newval = safe_multiply(lv, rv);
238 break;
239 case Div:
240 newval = PyNumber_TrueDivide(lv, rv);
241 break;
242 case FloorDiv:
243 newval = PyNumber_FloorDivide(lv, rv);
244 break;
245 case Mod:
246 newval = safe_mod(lv, rv);
247 break;
248 case Pow:
249 newval = safe_power(lv, rv);
250 break;
251 case LShift:
252 newval = safe_lshift(lv, rv);
253 break;
254 case RShift:
255 newval = PyNumber_Rshift(lv, rv);
256 break;
257 case BitOr:
258 newval = PyNumber_Or(lv, rv);
259 break;
260 case BitXor:
261 newval = PyNumber_Xor(lv, rv);
262 break;
263 case BitAnd:
264 newval = PyNumber_And(lv, rv);
265 break;
266 default: // Unknown operator
267 return 1;
268 }
269
270 return make_const(node, newval, arena);
271 }
272
273 static PyObject*
make_const_tuple(asdl_seq * elts)274 make_const_tuple(asdl_seq *elts)
275 {
276 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
277 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
278 if (e->kind != Constant_kind) {
279 return NULL;
280 }
281 }
282
283 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
284 if (newval == NULL) {
285 return NULL;
286 }
287
288 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
289 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
290 PyObject *v = e->v.Constant.value;
291 Py_INCREF(v);
292 PyTuple_SET_ITEM(newval, i, v);
293 }
294 return newval;
295 }
296
297 static int
fold_tuple(expr_ty node,PyArena * arena,_PyASTOptimizeState * state)298 fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
299 {
300 PyObject *newval;
301
302 if (node->v.Tuple.ctx != Load)
303 return 1;
304
305 newval = make_const_tuple(node->v.Tuple.elts);
306 return make_const(node, newval, arena);
307 }
308
309 static int
fold_subscr(expr_ty node,PyArena * arena,_PyASTOptimizeState * state)310 fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
311 {
312 PyObject *newval;
313 expr_ty arg, idx;
314
315 arg = node->v.Subscript.value;
316 idx = node->v.Subscript.slice;
317 if (node->v.Subscript.ctx != Load ||
318 arg->kind != Constant_kind ||
319 idx->kind != Constant_kind)
320 {
321 return 1;
322 }
323
324 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
325 return make_const(node, newval, arena);
326 }
327
328 /* Change literal list or set of constants into constant
329 tuple or frozenset respectively. Change literal list of
330 non-constants into tuple.
331 Used for right operand of "in" and "not in" tests and for iterable
332 in "for" loop and comprehensions.
333 */
334 static int
fold_iter(expr_ty arg,PyArena * arena,_PyASTOptimizeState * state)335 fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
336 {
337 PyObject *newval;
338 if (arg->kind == List_kind) {
339 /* First change a list into tuple. */
340 asdl_seq *elts = arg->v.List.elts;
341 Py_ssize_t n = asdl_seq_LEN(elts);
342 for (Py_ssize_t i = 0; i < n; i++) {
343 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
344 if (e->kind == Starred_kind) {
345 return 1;
346 }
347 }
348 expr_context_ty ctx = arg->v.List.ctx;
349 arg->kind = Tuple_kind;
350 arg->v.Tuple.elts = elts;
351 arg->v.Tuple.ctx = ctx;
352 /* Try to create a constant tuple. */
353 newval = make_const_tuple(elts);
354 }
355 else if (arg->kind == Set_kind) {
356 newval = make_const_tuple(arg->v.Set.elts);
357 if (newval) {
358 Py_SETREF(newval, PyFrozenSet_New(newval));
359 }
360 }
361 else {
362 return 1;
363 }
364 return make_const(arg, newval, arena);
365 }
366
367 static int
fold_compare(expr_ty node,PyArena * arena,_PyASTOptimizeState * state)368 fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
369 {
370 asdl_int_seq *ops;
371 asdl_seq *args;
372 Py_ssize_t i;
373
374 ops = node->v.Compare.ops;
375 args = node->v.Compare.comparators;
376 /* TODO: optimize cases with literal arguments. */
377 /* Change literal list or set in 'in' or 'not in' into
378 tuple or frozenset respectively. */
379 i = asdl_seq_LEN(ops) - 1;
380 int op = asdl_seq_GET(ops, i);
381 if (op == In || op == NotIn) {
382 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
383 return 0;
384 }
385 }
386 return 1;
387 }
388
389 static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
390 static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
391 static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
392 static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
393 static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
394 static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
395 static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
396 static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
397 static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
398 #define CALL(FUNC, TYPE, ARG) \
399 if (!FUNC((ARG), ctx_, state)) \
400 return 0;
401
402 #define CALL_OPT(FUNC, TYPE, ARG) \
403 if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
404 return 0;
405
406 #define CALL_SEQ(FUNC, TYPE, ARG) { \
407 int i; \
408 asdl_seq *seq = (ARG); /* avoid variable capture */ \
409 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
410 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
411 if (elt != NULL && !FUNC(elt, ctx_, state)) \
412 return 0; \
413 } \
414 }
415
416 #define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
417 int i; \
418 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
419 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
420 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
421 if (!FUNC(elt, ctx_, state)) \
422 return 0; \
423 } \
424 }
425
426 static int
astfold_body(asdl_seq * stmts,PyArena * ctx_,_PyASTOptimizeState * state)427 astfold_body(asdl_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
428 {
429 int docstring = _PyAST_GetDocString(stmts) != NULL;
430 CALL_SEQ(astfold_stmt, stmt_ty, stmts);
431 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
432 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
433 asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
434 if (!values) {
435 return 0;
436 }
437 asdl_seq_SET(values, 0, st->v.Expr.value);
438 expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
439 st->end_lineno, st->end_col_offset, ctx_);
440 if (!expr) {
441 return 0;
442 }
443 st->v.Expr.value = expr;
444 }
445 return 1;
446 }
447
448 static int
astfold_mod(mod_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)449 astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
450 {
451 switch (node_->kind) {
452 case Module_kind:
453 CALL(astfold_body, asdl_seq, node_->v.Module.body);
454 break;
455 case Interactive_kind:
456 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
457 break;
458 case Expression_kind:
459 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
460 break;
461 default:
462 break;
463 }
464 return 1;
465 }
466
467 static int
astfold_expr(expr_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)468 astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
469 {
470 switch (node_->kind) {
471 case BoolOp_kind:
472 CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
473 break;
474 case BinOp_kind:
475 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
476 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
477 CALL(fold_binop, expr_ty, node_);
478 break;
479 case UnaryOp_kind:
480 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
481 CALL(fold_unaryop, expr_ty, node_);
482 break;
483 case Lambda_kind:
484 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
485 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
486 break;
487 case IfExp_kind:
488 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
489 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
490 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
491 break;
492 case Dict_kind:
493 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
494 CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
495 break;
496 case Set_kind:
497 CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
498 break;
499 case ListComp_kind:
500 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
501 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
502 break;
503 case SetComp_kind:
504 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
505 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
506 break;
507 case DictComp_kind:
508 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
509 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
510 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
511 break;
512 case GeneratorExp_kind:
513 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
514 CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
515 break;
516 case Await_kind:
517 CALL(astfold_expr, expr_ty, node_->v.Await.value);
518 break;
519 case Yield_kind:
520 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
521 break;
522 case YieldFrom_kind:
523 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
524 break;
525 case Compare_kind:
526 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
527 CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
528 CALL(fold_compare, expr_ty, node_);
529 break;
530 case Call_kind:
531 CALL(astfold_expr, expr_ty, node_->v.Call.func);
532 CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
533 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
534 break;
535 case FormattedValue_kind:
536 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
537 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
538 break;
539 case JoinedStr_kind:
540 CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
541 break;
542 case Attribute_kind:
543 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
544 break;
545 case Subscript_kind:
546 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
547 CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
548 CALL(fold_subscr, expr_ty, node_);
549 break;
550 case Starred_kind:
551 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
552 break;
553 case Slice_kind:
554 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
555 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
556 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
557 break;
558 case List_kind:
559 CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
560 break;
561 case Tuple_kind:
562 CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
563 CALL(fold_tuple, expr_ty, node_);
564 break;
565 case Name_kind:
566 if (node_->v.Name.ctx == Load &&
567 _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
568 return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
569 }
570 break;
571 default:
572 break;
573 }
574 return 1;
575 }
576
577 static int
astfold_keyword(keyword_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)578 astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
579 {
580 CALL(astfold_expr, expr_ty, node_->value);
581 return 1;
582 }
583
584 static int
astfold_comprehension(comprehension_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)585 astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
586 {
587 CALL(astfold_expr, expr_ty, node_->target);
588 CALL(astfold_expr, expr_ty, node_->iter);
589 CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
590
591 CALL(fold_iter, expr_ty, node_->iter);
592 return 1;
593 }
594
595 static int
astfold_arguments(arguments_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)596 astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
597 {
598 CALL_SEQ(astfold_arg, arg_ty, node_->posonlyargs);
599 CALL_SEQ(astfold_arg, arg_ty, node_->args);
600 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
601 CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
602 CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
603 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
604 CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
605 return 1;
606 }
607
608 static int
astfold_arg(arg_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)609 astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
610 {
611 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
612 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
613 }
614 return 1;
615 }
616
617 static int
astfold_stmt(stmt_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)618 astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
619 {
620 switch (node_->kind) {
621 case FunctionDef_kind:
622 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
623 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
624 CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
625 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
626 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
627 }
628 break;
629 case AsyncFunctionDef_kind:
630 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
631 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
632 CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
633 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
634 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
635 }
636 break;
637 case ClassDef_kind:
638 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
639 CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
640 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
641 CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
642 break;
643 case Return_kind:
644 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
645 break;
646 case Delete_kind:
647 CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
648 break;
649 case Assign_kind:
650 CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
651 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
652 break;
653 case AugAssign_kind:
654 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
655 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
656 break;
657 case AnnAssign_kind:
658 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
659 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
660 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
661 }
662 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
663 break;
664 case For_kind:
665 CALL(astfold_expr, expr_ty, node_->v.For.target);
666 CALL(astfold_expr, expr_ty, node_->v.For.iter);
667 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
668 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
669
670 CALL(fold_iter, expr_ty, node_->v.For.iter);
671 break;
672 case AsyncFor_kind:
673 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
674 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
675 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
676 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
677 break;
678 case While_kind:
679 CALL(astfold_expr, expr_ty, node_->v.While.test);
680 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
681 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
682 break;
683 case If_kind:
684 CALL(astfold_expr, expr_ty, node_->v.If.test);
685 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
686 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
687 break;
688 case With_kind:
689 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
690 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
691 break;
692 case AsyncWith_kind:
693 CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
694 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
695 break;
696 case Raise_kind:
697 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
698 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
699 break;
700 case Try_kind:
701 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
702 CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
703 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
704 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
705 break;
706 case Assert_kind:
707 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
708 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
709 break;
710 case Expr_kind:
711 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
712 break;
713 default:
714 break;
715 }
716 return 1;
717 }
718
719 static int
astfold_excepthandler(excepthandler_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)720 astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
721 {
722 switch (node_->kind) {
723 case ExceptHandler_kind:
724 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
725 CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
726 break;
727 default:
728 break;
729 }
730 return 1;
731 }
732
733 static int
astfold_withitem(withitem_ty node_,PyArena * ctx_,_PyASTOptimizeState * state)734 astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
735 {
736 CALL(astfold_expr, expr_ty, node_->context_expr);
737 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
738 return 1;
739 }
740
741 #undef CALL
742 #undef CALL_OPT
743 #undef CALL_SEQ
744 #undef CALL_INT_SEQ
745
746 int
_PyAST_Optimize(mod_ty mod,PyArena * arena,_PyASTOptimizeState * state)747 _PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
748 {
749 int ret = astfold_mod(mod, arena, state);
750 assert(ret || PyErr_Occurred());
751 return ret;
752 }
753