blob: 46dba7646e0cd7accd2d989cfb22c19c6d7e3fe3 [file] [log] [blame]
INADA Naoki7ea143a2017-12-14 16:47:20 +09001/* AST Optimizer */
2#include "Python.h"
Victor Stinner526fdeb2021-03-17 23:50:50 +01003#include "pycore_ast.h" // _PyAST_GetDocString()
Victor Stinnera81fca62021-03-24 00:51:50 +01004#include "pycore_compile.h" // _PyASTOptimizeState
INADA Naoki7ea143a2017-12-14 16:47:20 +09005
6
INADA Naoki7ea143a2017-12-14 16:47:20 +09007static int
8make_const(expr_ty node, PyObject *val, PyArena *arena)
9{
Nick Coghlan8805a4d2020-11-07 22:35:17 +100010 // Even if no new value was calculated, make_const may still
11 // need to clear an error (e.g. for division by zero)
INADA Naoki7ea143a2017-12-14 16:47:20 +090012 if (val == NULL) {
13 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
14 return 0;
15 }
16 PyErr_Clear();
17 return 1;
18 }
Victor Stinner8370e072021-03-24 02:23:01 +010019 if (_PyArena_AddPyObject(arena, val) < 0) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090020 Py_DECREF(val);
21 return 0;
22 }
23 node->kind = Constant_kind;
Pablo Galindo33986462020-04-14 21:40:41 +010024 node->v.Constant.kind = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +090025 node->v.Constant.value = val;
26 return 1;
27}
28
29#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
30
31static PyObject*
32unary_not(PyObject *v)
33{
34 int r = PyObject_IsTrue(v);
35 if (r < 0)
36 return NULL;
37 return PyBool_FromLong(!r);
38}
39
40static int
Pablo Galindod112c602020-03-18 23:02:09 +000041fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +090042{
43 expr_ty arg = node->v.UnaryOp.operand;
44
Serhiy Storchaka3f228112018-09-27 17:42:37 +030045 if (arg->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090046 /* Fold not into comparison */
47 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
48 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
49 /* Eq and NotEq are often implemented in terms of one another, so
50 folding not (self == other) into self != other breaks implementation
51 of !=. Detecting such cases doesn't seem worthwhile.
52 Python uses </> for 'is subset'/'is superset' operations on sets.
53 They don't satisfy not folding laws. */
Nick Coghlan8805a4d2020-11-07 22:35:17 +100054 cmpop_ty op = asdl_seq_GET(arg->v.Compare.ops, 0);
INADA Naoki7ea143a2017-12-14 16:47:20 +090055 switch (op) {
56 case Is:
57 op = IsNot;
58 break;
59 case IsNot:
60 op = Is;
61 break;
62 case In:
63 op = NotIn;
64 break;
65 case NotIn:
66 op = In;
67 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +100068 // The remaining comparison operators can't be safely inverted
69 case Eq:
70 case NotEq:
71 case Lt:
72 case LtE:
73 case Gt:
74 case GtE:
75 op = 0; // The AST enums leave "0" free as an "unused" marker
76 break;
77 // No default case, so the compiler will emit a warning if new
78 // comparison operators are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +090079 }
80 if (op) {
81 asdl_seq_SET(arg->v.Compare.ops, 0, op);
82 COPY_NODE(node, arg);
83 return 1;
84 }
85 }
86 return 1;
87 }
88
89 typedef PyObject *(*unary_op)(PyObject*);
90 static const unary_op ops[] = {
91 [Invert] = PyNumber_Invert,
92 [Not] = unary_not,
93 [UAdd] = PyNumber_Positive,
94 [USub] = PyNumber_Negative,
95 };
Serhiy Storchaka3f228112018-09-27 17:42:37 +030096 PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +090097 return make_const(node, newval, arena);
98}
99
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200100/* Check whether a collection doesn't containing too much items (including
101 subcollections). This protects from creating a constant that needs
102 too much time for calculating a hash.
103 "limit" is the maximal number of items.
104 Returns the negative number if the total number of items exceeds the
105 limit. Otherwise returns the limit minus the total number of items.
106*/
107
108static Py_ssize_t
109check_complexity(PyObject *obj, Py_ssize_t limit)
110{
111 if (PyTuple_Check(obj)) {
112 Py_ssize_t i;
113 limit -= PyTuple_GET_SIZE(obj);
114 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
115 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
116 }
117 return limit;
118 }
119 else if (PyFrozenSet_Check(obj)) {
120 Py_ssize_t i = 0;
121 PyObject *item;
122 Py_hash_t hash;
123 limit -= PySet_GET_SIZE(obj);
124 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
125 limit = check_complexity(item, limit);
126 }
127 }
128 return limit;
129}
130
131#define MAX_INT_SIZE 128 /* bits */
132#define MAX_COLLECTION_SIZE 256 /* items */
133#define MAX_STR_SIZE 4096 /* characters */
134#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
135
136static PyObject *
137safe_multiply(PyObject *v, PyObject *w)
138{
139 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
140 size_t vbits = _PyLong_NumBits(v);
141 size_t wbits = _PyLong_NumBits(w);
142 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
143 return NULL;
144 }
145 if (vbits + wbits > MAX_INT_SIZE) {
146 return NULL;
147 }
148 }
149 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
150 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
151 PySet_GET_SIZE(w);
152 if (size) {
153 long n = PyLong_AsLong(v);
154 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
155 return NULL;
156 }
157 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
158 return NULL;
159 }
160 }
161 }
162 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
163 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
164 PyBytes_GET_SIZE(w);
165 if (size) {
166 long n = PyLong_AsLong(v);
167 if (n < 0 || n > MAX_STR_SIZE / size) {
168 return NULL;
169 }
170 }
171 }
172 else if (PyLong_Check(w) &&
173 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
174 PyUnicode_Check(v) || PyBytes_Check(v)))
175 {
176 return safe_multiply(w, v);
177 }
178
179 return PyNumber_Multiply(v, w);
180}
181
182static PyObject *
183safe_power(PyObject *v, PyObject *w)
184{
185 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
186 size_t vbits = _PyLong_NumBits(v);
187 size_t wbits = PyLong_AsSize_t(w);
188 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
189 return NULL;
190 }
191 if (vbits > MAX_INT_SIZE / wbits) {
192 return NULL;
193 }
194 }
195
196 return PyNumber_Power(v, w, Py_None);
197}
198
199static PyObject *
200safe_lshift(PyObject *v, PyObject *w)
201{
202 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
203 size_t vbits = _PyLong_NumBits(v);
204 size_t wbits = PyLong_AsSize_t(w);
205 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
206 return NULL;
207 }
208 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
209 return NULL;
210 }
211 }
212
213 return PyNumber_Lshift(v, w);
214}
215
216static PyObject *
217safe_mod(PyObject *v, PyObject *w)
218{
219 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
220 return NULL;
221 }
222
223 return PyNumber_Remainder(v, w);
224}
225
INADA Naoki7ea143a2017-12-14 16:47:20 +0900226static int
Pablo Galindod112c602020-03-18 23:02:09 +0000227fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900228{
229 expr_ty lhs, rhs;
230 lhs = node->v.BinOp.left;
231 rhs = node->v.BinOp.right;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300232 if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900233 return 1;
234 }
235
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300236 PyObject *lv = lhs->v.Constant.value;
237 PyObject *rv = rhs->v.Constant.value;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000238 PyObject *newval = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900239
240 switch (node->v.BinOp.op) {
241 case Add:
242 newval = PyNumber_Add(lv, rv);
243 break;
244 case Sub:
245 newval = PyNumber_Subtract(lv, rv);
246 break;
247 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200248 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900249 break;
250 case Div:
251 newval = PyNumber_TrueDivide(lv, rv);
252 break;
253 case FloorDiv:
254 newval = PyNumber_FloorDivide(lv, rv);
255 break;
256 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200257 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900258 break;
259 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200260 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900261 break;
262 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200263 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900264 break;
265 case RShift:
266 newval = PyNumber_Rshift(lv, rv);
267 break;
268 case BitOr:
269 newval = PyNumber_Or(lv, rv);
270 break;
271 case BitXor:
272 newval = PyNumber_Xor(lv, rv);
273 break;
274 case BitAnd:
275 newval = PyNumber_And(lv, rv);
276 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000277 // No builtin constants implement the following operators
278 case MatMult:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900279 return 1;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000280 // No default case, so the compiler will emit a warning if new binary
281 // operators are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900282 }
283
INADA Naoki7ea143a2017-12-14 16:47:20 +0900284 return make_const(node, newval, arena);
285}
286
287static PyObject*
Pablo Galindoa5634c42020-09-16 19:42:00 +0100288make_const_tuple(asdl_expr_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900289{
290 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
291 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300292 if (e->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900293 return NULL;
294 }
295 }
296
297 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
298 if (newval == NULL) {
299 return NULL;
300 }
301
302 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
303 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300304 PyObject *v = e->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900305 Py_INCREF(v);
306 PyTuple_SET_ITEM(newval, i, v);
307 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900308 return newval;
309}
310
311static int
Pablo Galindod112c602020-03-18 23:02:09 +0000312fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900313{
314 PyObject *newval;
315
316 if (node->v.Tuple.ctx != Load)
317 return 1;
318
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200319 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900320 return make_const(node, newval, arena);
321}
322
323static int
Pablo Galindod112c602020-03-18 23:02:09 +0000324fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900325{
326 PyObject *newval;
327 expr_ty arg, idx;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900328
329 arg = node->v.Subscript.value;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200330 idx = node->v.Subscript.slice;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900331 if (node->v.Subscript.ctx != Load ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300332 arg->kind != Constant_kind ||
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200333 idx->kind != Constant_kind)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900334 {
335 return 1;
336 }
337
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300338 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900339 return make_const(node, newval, arena);
340}
341
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200342/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200343 tuple or frozenset respectively. Change literal list of
344 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200345 Used for right operand of "in" and "not in" tests and for iterable
346 in "for" loop and comprehensions.
347*/
348static int
Pablo Galindod112c602020-03-18 23:02:09 +0000349fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200350{
351 PyObject *newval;
352 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200353 /* First change a list into tuple. */
Pablo Galindoa5634c42020-09-16 19:42:00 +0100354 asdl_expr_seq *elts = arg->v.List.elts;
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200355 Py_ssize_t n = asdl_seq_LEN(elts);
356 for (Py_ssize_t i = 0; i < n; i++) {
357 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
358 if (e->kind == Starred_kind) {
359 return 1;
360 }
361 }
362 expr_context_ty ctx = arg->v.List.ctx;
363 arg->kind = Tuple_kind;
364 arg->v.Tuple.elts = elts;
365 arg->v.Tuple.ctx = ctx;
366 /* Try to create a constant tuple. */
367 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200368 }
369 else if (arg->kind == Set_kind) {
370 newval = make_const_tuple(arg->v.Set.elts);
371 if (newval) {
372 Py_SETREF(newval, PyFrozenSet_New(newval));
373 }
374 }
375 else {
376 return 1;
377 }
378 return make_const(arg, newval, arena);
379}
380
INADA Naoki7ea143a2017-12-14 16:47:20 +0900381static int
Pablo Galindod112c602020-03-18 23:02:09 +0000382fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900383{
384 asdl_int_seq *ops;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100385 asdl_expr_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100386 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900387
388 ops = node->v.Compare.ops;
389 args = node->v.Compare.comparators;
390 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200391 /* Change literal list or set in 'in' or 'not in' into
392 tuple or frozenset respectively. */
393 i = asdl_seq_LEN(ops) - 1;
394 int op = asdl_seq_GET(ops, i);
395 if (op == In || op == NotIn) {
Pablo Galindod112c602020-03-18 23:02:09 +0000396 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200397 return 0;
398 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900399 }
400 return 1;
401}
402
Pablo Galindod112c602020-03-18 23:02:09 +0000403static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
404static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
405static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
406static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
407static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
408static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Pablo Galindod112c602020-03-18 23:02:09 +0000409static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
410static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Brandt Bucher145bf262021-02-26 14:51:55 -0800411static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
412static int astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
413
INADA Naoki7ea143a2017-12-14 16:47:20 +0900414#define CALL(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000415 if (!FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900416 return 0;
417
418#define CALL_OPT(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000419 if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900420 return 0;
421
422#define CALL_SEQ(FUNC, TYPE, ARG) { \
423 int i; \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100424 asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900425 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100426 TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000427 if (elt != NULL && !FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900428 return 0; \
429 } \
430}
431
432#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
433 int i; \
434 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
435 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
436 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000437 if (!FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900438 return 0; \
439 } \
440}
441
442static int
Pablo Galindoa5634c42020-09-16 19:42:00 +0100443astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300444{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300445 int docstring = _PyAST_GetDocString(stmts) != NULL;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100446 CALL_SEQ(astfold_stmt, stmt, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300447 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
448 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100449 asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300450 if (!values) {
451 return 0;
452 }
453 asdl_seq_SET(values, 0, st->v.Expr.value);
Victor Stinnerd36d6a92021-04-07 13:01:09 +0200454 expr_ty expr = _Py_JoinedStr(values, st->lineno, st->col_offset,
455 st->end_lineno, st->end_col_offset, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300456 if (!expr) {
457 return 0;
458 }
459 st->v.Expr.value = expr;
460 }
461 return 1;
462}
463
464static int
Pablo Galindod112c602020-03-18 23:02:09 +0000465astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900466{
467 switch (node_->kind) {
468 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300469 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900470 break;
471 case Interactive_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100472 CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900473 break;
474 case Expression_kind:
475 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
476 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000477 // The following top level nodes don't participate in constant folding
478 case FunctionType_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900479 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000480 // No default case, so the compiler will emit a warning if new top level
481 // compilation nodes are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900482 }
483 return 1;
484}
485
486static int
Pablo Galindod112c602020-03-18 23:02:09 +0000487astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900488{
489 switch (node_->kind) {
490 case BoolOp_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100491 CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900492 break;
493 case BinOp_kind:
494 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
495 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
496 CALL(fold_binop, expr_ty, node_);
497 break;
498 case UnaryOp_kind:
499 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
500 CALL(fold_unaryop, expr_ty, node_);
501 break;
502 case Lambda_kind:
503 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
504 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
505 break;
506 case IfExp_kind:
507 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
508 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
509 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
510 break;
511 case Dict_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100512 CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);
513 CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900514 break;
515 case Set_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100516 CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900517 break;
518 case ListComp_kind:
519 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100520 CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900521 break;
522 case SetComp_kind:
523 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100524 CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900525 break;
526 case DictComp_kind:
527 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
528 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100529 CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900530 break;
531 case GeneratorExp_kind:
532 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100533 CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900534 break;
535 case Await_kind:
536 CALL(astfold_expr, expr_ty, node_->v.Await.value);
537 break;
538 case Yield_kind:
539 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
540 break;
541 case YieldFrom_kind:
542 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
543 break;
544 case Compare_kind:
545 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100546 CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900547 CALL(fold_compare, expr_ty, node_);
548 break;
549 case Call_kind:
550 CALL(astfold_expr, expr_ty, node_->v.Call.func);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100551 CALL_SEQ(astfold_expr, expr, node_->v.Call.args);
552 CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900553 break;
554 case FormattedValue_kind:
555 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
556 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
557 break;
558 case JoinedStr_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100559 CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900560 break;
561 case Attribute_kind:
562 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
563 break;
564 case Subscript_kind:
565 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200566 CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900567 CALL(fold_subscr, expr_ty, node_);
568 break;
569 case Starred_kind:
570 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
571 break;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200572 case Slice_kind:
573 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
574 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
575 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
576 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900577 case List_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100578 CALL_SEQ(astfold_expr, expr, node_->v.List.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900579 break;
580 case Tuple_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100581 CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900582 CALL(fold_tuple, expr_ty, node_);
583 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200584 case Name_kind:
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100585 if (node_->v.Name.ctx == Load &&
586 _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
Pablo Galindod112c602020-03-18 23:02:09 +0000587 return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200588 }
589 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000590 case NamedExpr_kind:
591 CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900592 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000593 case Constant_kind:
594 // Already a constant, nothing further to do
595 break;
Brandt Bucher145bf262021-02-26 14:51:55 -0800596 case MatchAs_kind:
597 case MatchOr_kind:
598 // These can't occur outside of patterns.
599 Py_UNREACHABLE();
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000600 // No default case, so the compiler will emit a warning if new expression
601 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900602 }
603 return 1;
604}
605
606static int
Pablo Galindod112c602020-03-18 23:02:09 +0000607astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900608{
609 CALL(astfold_expr, expr_ty, node_->value);
610 return 1;
611}
612
613static int
Pablo Galindod112c602020-03-18 23:02:09 +0000614astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900615{
616 CALL(astfold_expr, expr_ty, node_->target);
617 CALL(astfold_expr, expr_ty, node_->iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100618 CALL_SEQ(astfold_expr, expr, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200619
620 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900621 return 1;
622}
623
624static int
Pablo Galindod112c602020-03-18 23:02:09 +0000625astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900626{
Pablo Galindoa5634c42020-09-16 19:42:00 +0100627 CALL_SEQ(astfold_expr, expr, node_->kw_defaults);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100628 CALL_SEQ(astfold_expr, expr, node_->defaults);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900629 return 1;
630}
631
632static int
Pablo Galindod112c602020-03-18 23:02:09 +0000633astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900634{
635 switch (node_->kind) {
636 case FunctionDef_kind:
637 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300638 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100639 CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900640 break;
641 case AsyncFunctionDef_kind:
642 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300643 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100644 CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900645 break;
646 case ClassDef_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100647 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
648 CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300649 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100650 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900651 break;
652 case Return_kind:
653 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
654 break;
655 case Delete_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100656 CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900657 break;
658 case Assign_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100659 CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900660 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
661 break;
662 case AugAssign_kind:
663 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
664 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
665 break;
666 case AnnAssign_kind:
667 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900668 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
669 break;
670 case For_kind:
671 CALL(astfold_expr, expr_ty, node_->v.For.target);
672 CALL(astfold_expr, expr_ty, node_->v.For.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100673 CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
674 CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200675
676 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900677 break;
678 case AsyncFor_kind:
679 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
680 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100681 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
682 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900683 break;
684 case While_kind:
685 CALL(astfold_expr, expr_ty, node_->v.While.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100686 CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
687 CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900688 break;
689 case If_kind:
690 CALL(astfold_expr, expr_ty, node_->v.If.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100691 CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);
692 CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900693 break;
694 case With_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100695 CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);
696 CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900697 break;
698 case AsyncWith_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100699 CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);
700 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900701 break;
702 case Raise_kind:
703 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
704 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
705 break;
706 case Try_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100707 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
708 CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
709 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
710 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900711 break;
712 case Assert_kind:
713 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
714 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
715 break;
716 case Expr_kind:
717 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
718 break;
Brandt Bucher145bf262021-02-26 14:51:55 -0800719 case Match_kind:
720 CALL(astfold_expr, expr_ty, node_->v.Match.subject);
721 CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases);
722 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000723 // The following statements don't contain any subexpressions to be folded
724 case Import_kind:
725 case ImportFrom_kind:
726 case Global_kind:
727 case Nonlocal_kind:
728 case Pass_kind:
729 case Break_kind:
730 case Continue_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900731 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000732 // No default case, so the compiler will emit a warning if new statement
733 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900734 }
735 return 1;
736}
737
738static int
Pablo Galindod112c602020-03-18 23:02:09 +0000739astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900740{
741 switch (node_->kind) {
742 case ExceptHandler_kind:
743 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100744 CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900745 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000746 // No default case, so the compiler will emit a warning if new handler
747 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900748 }
749 return 1;
750}
751
752static int
Pablo Galindod112c602020-03-18 23:02:09 +0000753astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900754{
755 CALL(astfold_expr, expr_ty, node_->context_expr);
756 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
757 return 1;
758}
759
Brandt Bucher145bf262021-02-26 14:51:55 -0800760static int
761astfold_pattern_negative(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
762{
763 assert(node_->kind == UnaryOp_kind);
764 assert(node_->v.UnaryOp.op == USub);
765 assert(node_->v.UnaryOp.operand->kind == Constant_kind);
766 PyObject *value = node_->v.UnaryOp.operand->v.Constant.value;
767 assert(PyComplex_CheckExact(value) ||
768 PyFloat_CheckExact(value) ||
769 PyLong_CheckExact(value));
770 PyObject *negated = PyNumber_Negative(value);
771 if (negated == NULL) {
772 return 0;
773 }
774 assert(PyComplex_CheckExact(negated) ||
775 PyFloat_CheckExact(negated) ||
776 PyLong_CheckExact(negated));
777 return make_const(node_, negated, ctx_);
778}
779
780static int
781astfold_pattern_complex(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
782{
783 expr_ty left = node_->v.BinOp.left;
784 expr_ty right = node_->v.BinOp.right;
785 if (left->kind == UnaryOp_kind) {
786 CALL(astfold_pattern_negative, expr_ty, left);
787 }
788 assert(left->kind = Constant_kind);
789 assert(right->kind = Constant_kind);
790 // LHS must be real, RHS must be imaginary:
791 if (!(PyFloat_CheckExact(left->v.Constant.value) ||
792 PyLong_CheckExact(left->v.Constant.value)) ||
793 !PyComplex_CheckExact(right->v.Constant.value))
794 {
795 // Not actually valid, but it's the compiler's job to complain:
796 return 1;
797 }
798 PyObject *new;
799 if (node_->v.BinOp.op == Add) {
800 new = PyNumber_Add(left->v.Constant.value, right->v.Constant.value);
801 }
802 else {
803 assert(node_->v.BinOp.op == Sub);
804 new = PyNumber_Subtract(left->v.Constant.value, right->v.Constant.value);
805 }
806 if (new == NULL) {
807 return 0;
808 }
809 assert(PyComplex_CheckExact(new));
810 return make_const(node_, new, ctx_);
811}
812
813static int
814astfold_pattern_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
815{
816 CALL(astfold_pattern, expr_ty, node_->value);
817 return 1;
818}
819
820static int
821astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
822{
823 // Don't blindly optimize the pattern as an expr; it plays by its own rules!
824 // Currently, this is only used to form complex/negative numeric constants.
825 switch (node_->kind) {
826 case Attribute_kind:
827 break;
828 case BinOp_kind:
829 CALL(astfold_pattern_complex, expr_ty, node_);
830 break;
831 case Call_kind:
832 CALL_SEQ(astfold_pattern, expr, node_->v.Call.args);
833 CALL_SEQ(astfold_pattern_keyword, keyword, node_->v.Call.keywords);
834 break;
835 case Constant_kind:
836 break;
837 case Dict_kind:
838 CALL_SEQ(astfold_pattern, expr, node_->v.Dict.keys);
839 CALL_SEQ(astfold_pattern, expr, node_->v.Dict.values);
840 break;
841 // Not actually valid, but it's the compiler's job to complain:
842 case JoinedStr_kind:
843 break;
844 case List_kind:
845 CALL_SEQ(astfold_pattern, expr, node_->v.List.elts);
846 break;
847 case MatchAs_kind:
848 CALL(astfold_pattern, expr_ty, node_->v.MatchAs.pattern);
849 break;
850 case MatchOr_kind:
851 CALL_SEQ(astfold_pattern, expr, node_->v.MatchOr.patterns);
852 break;
853 case Name_kind:
854 break;
855 case Starred_kind:
856 CALL(astfold_pattern, expr_ty, node_->v.Starred.value);
857 break;
858 case Tuple_kind:
859 CALL_SEQ(astfold_pattern, expr, node_->v.Tuple.elts);
860 break;
861 case UnaryOp_kind:
862 CALL(astfold_pattern_negative, expr_ty, node_);
863 break;
864 default:
865 Py_UNREACHABLE();
866 }
867 return 1;
868}
869
870static int
871astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
872{
873 CALL(astfold_pattern, expr_ty, node_->pattern);
874 CALL_OPT(astfold_expr, expr_ty, node_->guard);
875 CALL_SEQ(astfold_stmt, stmt, node_->body);
876 return 1;
877}
878
INADA Naoki7ea143a2017-12-14 16:47:20 +0900879#undef CALL
880#undef CALL_OPT
881#undef CALL_SEQ
882#undef CALL_INT_SEQ
883
884int
Pablo Galindod112c602020-03-18 23:02:09 +0000885_PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900886{
Pablo Galindod112c602020-03-18 23:02:09 +0000887 int ret = astfold_mod(mod, arena, state);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900888 assert(ret || PyErr_Occurred());
889 return ret;
890}