blob: c76b428f97298d8403858b66aa72c74d97c5d5c4 [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()
INADA Naoki7ea143a2017-12-14 16:47:20 +09004
5
INADA Naoki7ea143a2017-12-14 16:47:20 +09006static int
7make_const(expr_ty node, PyObject *val, PyArena *arena)
8{
Nick Coghlan8805a4d2020-11-07 22:35:17 +10009 // Even if no new value was calculated, make_const may still
10 // need to clear an error (e.g. for division by zero)
INADA Naoki7ea143a2017-12-14 16:47:20 +090011 if (val == NULL) {
12 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
13 return 0;
14 }
15 PyErr_Clear();
16 return 1;
17 }
18 if (PyArena_AddPyObject(arena, val) < 0) {
19 Py_DECREF(val);
20 return 0;
21 }
22 node->kind = Constant_kind;
Pablo Galindo33986462020-04-14 21:40:41 +010023 node->v.Constant.kind = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +090024 node->v.Constant.value = val;
25 return 1;
26}
27
28#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
29
30static PyObject*
31unary_not(PyObject *v)
32{
33 int r = PyObject_IsTrue(v);
34 if (r < 0)
35 return NULL;
36 return PyBool_FromLong(!r);
37}
38
39static int
Pablo Galindod112c602020-03-18 23:02:09 +000040fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +090041{
42 expr_ty arg = node->v.UnaryOp.operand;
43
Serhiy Storchaka3f228112018-09-27 17:42:37 +030044 if (arg->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090045 /* Fold not into comparison */
46 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
47 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
48 /* Eq and NotEq are often implemented in terms of one another, so
49 folding not (self == other) into self != other breaks implementation
50 of !=. Detecting such cases doesn't seem worthwhile.
51 Python uses </> for 'is subset'/'is superset' operations on sets.
52 They don't satisfy not folding laws. */
Nick Coghlan8805a4d2020-11-07 22:35:17 +100053 cmpop_ty op = asdl_seq_GET(arg->v.Compare.ops, 0);
INADA Naoki7ea143a2017-12-14 16:47:20 +090054 switch (op) {
55 case Is:
56 op = IsNot;
57 break;
58 case IsNot:
59 op = Is;
60 break;
61 case In:
62 op = NotIn;
63 break;
64 case NotIn:
65 op = In;
66 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +100067 // The remaining comparison operators can't be safely inverted
68 case Eq:
69 case NotEq:
70 case Lt:
71 case LtE:
72 case Gt:
73 case GtE:
74 op = 0; // The AST enums leave "0" free as an "unused" marker
75 break;
76 // No default case, so the compiler will emit a warning if new
77 // comparison operators are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +090078 }
79 if (op) {
80 asdl_seq_SET(arg->v.Compare.ops, 0, op);
81 COPY_NODE(node, arg);
82 return 1;
83 }
84 }
85 return 1;
86 }
87
88 typedef PyObject *(*unary_op)(PyObject*);
89 static const unary_op ops[] = {
90 [Invert] = PyNumber_Invert,
91 [Not] = unary_not,
92 [UAdd] = PyNumber_Positive,
93 [USub] = PyNumber_Negative,
94 };
Serhiy Storchaka3f228112018-09-27 17:42:37 +030095 PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +090096 return make_const(node, newval, arena);
97}
98
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +020099/* Check whether a collection doesn't containing too much items (including
100 subcollections). This protects from creating a constant that needs
101 too much time for calculating a hash.
102 "limit" is the maximal number of items.
103 Returns the negative number if the total number of items exceeds the
104 limit. Otherwise returns the limit minus the total number of items.
105*/
106
107static Py_ssize_t
108check_complexity(PyObject *obj, Py_ssize_t limit)
109{
110 if (PyTuple_Check(obj)) {
111 Py_ssize_t i;
112 limit -= PyTuple_GET_SIZE(obj);
113 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
114 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
115 }
116 return limit;
117 }
118 else if (PyFrozenSet_Check(obj)) {
119 Py_ssize_t i = 0;
120 PyObject *item;
121 Py_hash_t hash;
122 limit -= PySet_GET_SIZE(obj);
123 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
124 limit = check_complexity(item, limit);
125 }
126 }
127 return limit;
128}
129
130#define MAX_INT_SIZE 128 /* bits */
131#define MAX_COLLECTION_SIZE 256 /* items */
132#define MAX_STR_SIZE 4096 /* characters */
133#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
134
135static PyObject *
136safe_multiply(PyObject *v, PyObject *w)
137{
138 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
139 size_t vbits = _PyLong_NumBits(v);
140 size_t wbits = _PyLong_NumBits(w);
141 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
142 return NULL;
143 }
144 if (vbits + wbits > MAX_INT_SIZE) {
145 return NULL;
146 }
147 }
148 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
149 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
150 PySet_GET_SIZE(w);
151 if (size) {
152 long n = PyLong_AsLong(v);
153 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
154 return NULL;
155 }
156 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
157 return NULL;
158 }
159 }
160 }
161 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
162 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
163 PyBytes_GET_SIZE(w);
164 if (size) {
165 long n = PyLong_AsLong(v);
166 if (n < 0 || n > MAX_STR_SIZE / size) {
167 return NULL;
168 }
169 }
170 }
171 else if (PyLong_Check(w) &&
172 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
173 PyUnicode_Check(v) || PyBytes_Check(v)))
174 {
175 return safe_multiply(w, v);
176 }
177
178 return PyNumber_Multiply(v, w);
179}
180
181static PyObject *
182safe_power(PyObject *v, PyObject *w)
183{
184 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
185 size_t vbits = _PyLong_NumBits(v);
186 size_t wbits = PyLong_AsSize_t(w);
187 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
188 return NULL;
189 }
190 if (vbits > MAX_INT_SIZE / wbits) {
191 return NULL;
192 }
193 }
194
195 return PyNumber_Power(v, w, Py_None);
196}
197
198static PyObject *
199safe_lshift(PyObject *v, PyObject *w)
200{
201 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
202 size_t vbits = _PyLong_NumBits(v);
203 size_t wbits = PyLong_AsSize_t(w);
204 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
205 return NULL;
206 }
207 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
208 return NULL;
209 }
210 }
211
212 return PyNumber_Lshift(v, w);
213}
214
215static PyObject *
216safe_mod(PyObject *v, PyObject *w)
217{
218 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
219 return NULL;
220 }
221
222 return PyNumber_Remainder(v, w);
223}
224
INADA Naoki7ea143a2017-12-14 16:47:20 +0900225static int
Pablo Galindod112c602020-03-18 23:02:09 +0000226fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900227{
228 expr_ty lhs, rhs;
229 lhs = node->v.BinOp.left;
230 rhs = node->v.BinOp.right;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300231 if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900232 return 1;
233 }
234
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300235 PyObject *lv = lhs->v.Constant.value;
236 PyObject *rv = rhs->v.Constant.value;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000237 PyObject *newval = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900238
239 switch (node->v.BinOp.op) {
240 case Add:
241 newval = PyNumber_Add(lv, rv);
242 break;
243 case Sub:
244 newval = PyNumber_Subtract(lv, rv);
245 break;
246 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200247 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900248 break;
249 case Div:
250 newval = PyNumber_TrueDivide(lv, rv);
251 break;
252 case FloorDiv:
253 newval = PyNumber_FloorDivide(lv, rv);
254 break;
255 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200256 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900257 break;
258 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200259 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900260 break;
261 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200262 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900263 break;
264 case RShift:
265 newval = PyNumber_Rshift(lv, rv);
266 break;
267 case BitOr:
268 newval = PyNumber_Or(lv, rv);
269 break;
270 case BitXor:
271 newval = PyNumber_Xor(lv, rv);
272 break;
273 case BitAnd:
274 newval = PyNumber_And(lv, rv);
275 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000276 // No builtin constants implement the following operators
277 case MatMult:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900278 return 1;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000279 // No default case, so the compiler will emit a warning if new binary
280 // operators are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900281 }
282
INADA Naoki7ea143a2017-12-14 16:47:20 +0900283 return make_const(node, newval, arena);
284}
285
286static PyObject*
Pablo Galindoa5634c42020-09-16 19:42:00 +0100287make_const_tuple(asdl_expr_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900288{
289 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
290 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300291 if (e->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900292 return NULL;
293 }
294 }
295
296 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
297 if (newval == NULL) {
298 return NULL;
299 }
300
301 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
302 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300303 PyObject *v = e->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900304 Py_INCREF(v);
305 PyTuple_SET_ITEM(newval, i, v);
306 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900307 return newval;
308}
309
310static int
Pablo Galindod112c602020-03-18 23:02:09 +0000311fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900312{
313 PyObject *newval;
314
315 if (node->v.Tuple.ctx != Load)
316 return 1;
317
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200318 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900319 return make_const(node, newval, arena);
320}
321
322static int
Pablo Galindod112c602020-03-18 23:02:09 +0000323fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900324{
325 PyObject *newval;
326 expr_ty arg, idx;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900327
328 arg = node->v.Subscript.value;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200329 idx = node->v.Subscript.slice;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900330 if (node->v.Subscript.ctx != Load ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300331 arg->kind != Constant_kind ||
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200332 idx->kind != Constant_kind)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900333 {
334 return 1;
335 }
336
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300337 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900338 return make_const(node, newval, arena);
339}
340
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200341/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200342 tuple or frozenset respectively. Change literal list of
343 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200344 Used for right operand of "in" and "not in" tests and for iterable
345 in "for" loop and comprehensions.
346*/
347static int
Pablo Galindod112c602020-03-18 23:02:09 +0000348fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200349{
350 PyObject *newval;
351 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200352 /* First change a list into tuple. */
Pablo Galindoa5634c42020-09-16 19:42:00 +0100353 asdl_expr_seq *elts = arg->v.List.elts;
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200354 Py_ssize_t n = asdl_seq_LEN(elts);
355 for (Py_ssize_t i = 0; i < n; i++) {
356 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
357 if (e->kind == Starred_kind) {
358 return 1;
359 }
360 }
361 expr_context_ty ctx = arg->v.List.ctx;
362 arg->kind = Tuple_kind;
363 arg->v.Tuple.elts = elts;
364 arg->v.Tuple.ctx = ctx;
365 /* Try to create a constant tuple. */
366 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200367 }
368 else if (arg->kind == Set_kind) {
369 newval = make_const_tuple(arg->v.Set.elts);
370 if (newval) {
371 Py_SETREF(newval, PyFrozenSet_New(newval));
372 }
373 }
374 else {
375 return 1;
376 }
377 return make_const(arg, newval, arena);
378}
379
INADA Naoki7ea143a2017-12-14 16:47:20 +0900380static int
Pablo Galindod112c602020-03-18 23:02:09 +0000381fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900382{
383 asdl_int_seq *ops;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100384 asdl_expr_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100385 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900386
387 ops = node->v.Compare.ops;
388 args = node->v.Compare.comparators;
389 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200390 /* Change literal list or set in 'in' or 'not in' into
391 tuple or frozenset respectively. */
392 i = asdl_seq_LEN(ops) - 1;
393 int op = asdl_seq_GET(ops, i);
394 if (op == In || op == NotIn) {
Pablo Galindod112c602020-03-18 23:02:09 +0000395 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200396 return 0;
397 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900398 }
399 return 1;
400}
401
Pablo Galindod112c602020-03-18 23:02:09 +0000402static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
403static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
404static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
405static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
406static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
407static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Pablo Galindod112c602020-03-18 23:02:09 +0000408static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
409static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Brandt Bucher145bf262021-02-26 14:51:55 -0800410static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
411static int astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
412
INADA Naoki7ea143a2017-12-14 16:47:20 +0900413#define CALL(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000414 if (!FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900415 return 0;
416
417#define CALL_OPT(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000418 if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900419 return 0;
420
421#define CALL_SEQ(FUNC, TYPE, ARG) { \
422 int i; \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100423 asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900424 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100425 TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000426 if (elt != NULL && !FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900427 return 0; \
428 } \
429}
430
431#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
432 int i; \
433 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
434 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
435 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000436 if (!FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900437 return 0; \
438 } \
439}
440
441static int
Pablo Galindoa5634c42020-09-16 19:42:00 +0100442astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300443{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300444 int docstring = _PyAST_GetDocString(stmts) != NULL;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100445 CALL_SEQ(astfold_stmt, stmt, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300446 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
447 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100448 asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300449 if (!values) {
450 return 0;
451 }
452 asdl_seq_SET(values, 0, st->v.Expr.value);
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000453 expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
454 st->end_lineno, st->end_col_offset, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300455 if (!expr) {
456 return 0;
457 }
458 st->v.Expr.value = expr;
459 }
460 return 1;
461}
462
463static int
Pablo Galindod112c602020-03-18 23:02:09 +0000464astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900465{
466 switch (node_->kind) {
467 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300468 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900469 break;
470 case Interactive_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100471 CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900472 break;
473 case Expression_kind:
474 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
475 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000476 // The following top level nodes don't participate in constant folding
477 case FunctionType_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900478 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000479 // No default case, so the compiler will emit a warning if new top level
480 // compilation nodes are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900481 }
482 return 1;
483}
484
485static int
Pablo Galindod112c602020-03-18 23:02:09 +0000486astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900487{
488 switch (node_->kind) {
489 case BoolOp_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100490 CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900491 break;
492 case BinOp_kind:
493 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
494 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
495 CALL(fold_binop, expr_ty, node_);
496 break;
497 case UnaryOp_kind:
498 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
499 CALL(fold_unaryop, expr_ty, node_);
500 break;
501 case Lambda_kind:
502 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
503 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
504 break;
505 case IfExp_kind:
506 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
507 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
508 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
509 break;
510 case Dict_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100511 CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);
512 CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900513 break;
514 case Set_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100515 CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900516 break;
517 case ListComp_kind:
518 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100519 CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900520 break;
521 case SetComp_kind:
522 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100523 CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900524 break;
525 case DictComp_kind:
526 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
527 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100528 CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900529 break;
530 case GeneratorExp_kind:
531 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100532 CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900533 break;
534 case Await_kind:
535 CALL(astfold_expr, expr_ty, node_->v.Await.value);
536 break;
537 case Yield_kind:
538 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
539 break;
540 case YieldFrom_kind:
541 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
542 break;
543 case Compare_kind:
544 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100545 CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900546 CALL(fold_compare, expr_ty, node_);
547 break;
548 case Call_kind:
549 CALL(astfold_expr, expr_ty, node_->v.Call.func);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100550 CALL_SEQ(astfold_expr, expr, node_->v.Call.args);
551 CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900552 break;
553 case FormattedValue_kind:
554 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
555 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
556 break;
557 case JoinedStr_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100558 CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900559 break;
560 case Attribute_kind:
561 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
562 break;
563 case Subscript_kind:
564 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200565 CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900566 CALL(fold_subscr, expr_ty, node_);
567 break;
568 case Starred_kind:
569 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
570 break;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200571 case Slice_kind:
572 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
573 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
574 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
575 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900576 case List_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100577 CALL_SEQ(astfold_expr, expr, node_->v.List.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900578 break;
579 case Tuple_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100580 CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900581 CALL(fold_tuple, expr_ty, node_);
582 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200583 case Name_kind:
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100584 if (node_->v.Name.ctx == Load &&
585 _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
Pablo Galindod112c602020-03-18 23:02:09 +0000586 return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200587 }
588 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000589 case NamedExpr_kind:
590 CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900591 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000592 case Constant_kind:
593 // Already a constant, nothing further to do
594 break;
Brandt Bucher145bf262021-02-26 14:51:55 -0800595 case MatchAs_kind:
596 case MatchOr_kind:
597 // These can't occur outside of patterns.
598 Py_UNREACHABLE();
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000599 // No default case, so the compiler will emit a warning if new expression
600 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900601 }
602 return 1;
603}
604
605static int
Pablo Galindod112c602020-03-18 23:02:09 +0000606astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900607{
608 CALL(astfold_expr, expr_ty, node_->value);
609 return 1;
610}
611
612static int
Pablo Galindod112c602020-03-18 23:02:09 +0000613astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900614{
615 CALL(astfold_expr, expr_ty, node_->target);
616 CALL(astfold_expr, expr_ty, node_->iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100617 CALL_SEQ(astfold_expr, expr, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200618
619 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900620 return 1;
621}
622
623static int
Pablo Galindod112c602020-03-18 23:02:09 +0000624astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900625{
Pablo Galindoa5634c42020-09-16 19:42:00 +0100626 CALL_SEQ(astfold_expr, expr, node_->kw_defaults);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100627 CALL_SEQ(astfold_expr, expr, node_->defaults);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900628 return 1;
629}
630
631static int
Pablo Galindod112c602020-03-18 23:02:09 +0000632astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900633{
634 switch (node_->kind) {
635 case FunctionDef_kind:
636 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300637 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100638 CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900639 break;
640 case AsyncFunctionDef_kind:
641 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300642 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100643 CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900644 break;
645 case ClassDef_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100646 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
647 CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300648 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100649 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900650 break;
651 case Return_kind:
652 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
653 break;
654 case Delete_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100655 CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900656 break;
657 case Assign_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100658 CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900659 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
660 break;
661 case AugAssign_kind:
662 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
663 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
664 break;
665 case AnnAssign_kind:
666 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900667 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
668 break;
669 case For_kind:
670 CALL(astfold_expr, expr_ty, node_->v.For.target);
671 CALL(astfold_expr, expr_ty, node_->v.For.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100672 CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
673 CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200674
675 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900676 break;
677 case AsyncFor_kind:
678 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
679 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100680 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
681 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900682 break;
683 case While_kind:
684 CALL(astfold_expr, expr_ty, node_->v.While.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100685 CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
686 CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900687 break;
688 case If_kind:
689 CALL(astfold_expr, expr_ty, node_->v.If.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100690 CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);
691 CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900692 break;
693 case With_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100694 CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);
695 CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900696 break;
697 case AsyncWith_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100698 CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);
699 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900700 break;
701 case Raise_kind:
702 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
703 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
704 break;
705 case Try_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100706 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
707 CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
708 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
709 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900710 break;
711 case Assert_kind:
712 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
713 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
714 break;
715 case Expr_kind:
716 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
717 break;
Brandt Bucher145bf262021-02-26 14:51:55 -0800718 case Match_kind:
719 CALL(astfold_expr, expr_ty, node_->v.Match.subject);
720 CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases);
721 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000722 // The following statements don't contain any subexpressions to be folded
723 case Import_kind:
724 case ImportFrom_kind:
725 case Global_kind:
726 case Nonlocal_kind:
727 case Pass_kind:
728 case Break_kind:
729 case Continue_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900730 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000731 // No default case, so the compiler will emit a warning if new statement
732 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900733 }
734 return 1;
735}
736
737static int
Pablo Galindod112c602020-03-18 23:02:09 +0000738astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900739{
740 switch (node_->kind) {
741 case ExceptHandler_kind:
742 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100743 CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900744 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000745 // No default case, so the compiler will emit a warning if new handler
746 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900747 }
748 return 1;
749}
750
751static int
Pablo Galindod112c602020-03-18 23:02:09 +0000752astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900753{
754 CALL(astfold_expr, expr_ty, node_->context_expr);
755 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
756 return 1;
757}
758
Brandt Bucher145bf262021-02-26 14:51:55 -0800759static int
760astfold_pattern_negative(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
761{
762 assert(node_->kind == UnaryOp_kind);
763 assert(node_->v.UnaryOp.op == USub);
764 assert(node_->v.UnaryOp.operand->kind == Constant_kind);
765 PyObject *value = node_->v.UnaryOp.operand->v.Constant.value;
766 assert(PyComplex_CheckExact(value) ||
767 PyFloat_CheckExact(value) ||
768 PyLong_CheckExact(value));
769 PyObject *negated = PyNumber_Negative(value);
770 if (negated == NULL) {
771 return 0;
772 }
773 assert(PyComplex_CheckExact(negated) ||
774 PyFloat_CheckExact(negated) ||
775 PyLong_CheckExact(negated));
776 return make_const(node_, negated, ctx_);
777}
778
779static int
780astfold_pattern_complex(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
781{
782 expr_ty left = node_->v.BinOp.left;
783 expr_ty right = node_->v.BinOp.right;
784 if (left->kind == UnaryOp_kind) {
785 CALL(astfold_pattern_negative, expr_ty, left);
786 }
787 assert(left->kind = Constant_kind);
788 assert(right->kind = Constant_kind);
789 // LHS must be real, RHS must be imaginary:
790 if (!(PyFloat_CheckExact(left->v.Constant.value) ||
791 PyLong_CheckExact(left->v.Constant.value)) ||
792 !PyComplex_CheckExact(right->v.Constant.value))
793 {
794 // Not actually valid, but it's the compiler's job to complain:
795 return 1;
796 }
797 PyObject *new;
798 if (node_->v.BinOp.op == Add) {
799 new = PyNumber_Add(left->v.Constant.value, right->v.Constant.value);
800 }
801 else {
802 assert(node_->v.BinOp.op == Sub);
803 new = PyNumber_Subtract(left->v.Constant.value, right->v.Constant.value);
804 }
805 if (new == NULL) {
806 return 0;
807 }
808 assert(PyComplex_CheckExact(new));
809 return make_const(node_, new, ctx_);
810}
811
812static int
813astfold_pattern_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
814{
815 CALL(astfold_pattern, expr_ty, node_->value);
816 return 1;
817}
818
819static int
820astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
821{
822 // Don't blindly optimize the pattern as an expr; it plays by its own rules!
823 // Currently, this is only used to form complex/negative numeric constants.
824 switch (node_->kind) {
825 case Attribute_kind:
826 break;
827 case BinOp_kind:
828 CALL(astfold_pattern_complex, expr_ty, node_);
829 break;
830 case Call_kind:
831 CALL_SEQ(astfold_pattern, expr, node_->v.Call.args);
832 CALL_SEQ(astfold_pattern_keyword, keyword, node_->v.Call.keywords);
833 break;
834 case Constant_kind:
835 break;
836 case Dict_kind:
837 CALL_SEQ(astfold_pattern, expr, node_->v.Dict.keys);
838 CALL_SEQ(astfold_pattern, expr, node_->v.Dict.values);
839 break;
840 // Not actually valid, but it's the compiler's job to complain:
841 case JoinedStr_kind:
842 break;
843 case List_kind:
844 CALL_SEQ(astfold_pattern, expr, node_->v.List.elts);
845 break;
846 case MatchAs_kind:
847 CALL(astfold_pattern, expr_ty, node_->v.MatchAs.pattern);
848 break;
849 case MatchOr_kind:
850 CALL_SEQ(astfold_pattern, expr, node_->v.MatchOr.patterns);
851 break;
852 case Name_kind:
853 break;
854 case Starred_kind:
855 CALL(astfold_pattern, expr_ty, node_->v.Starred.value);
856 break;
857 case Tuple_kind:
858 CALL_SEQ(astfold_pattern, expr, node_->v.Tuple.elts);
859 break;
860 case UnaryOp_kind:
861 CALL(astfold_pattern_negative, expr_ty, node_);
862 break;
863 default:
864 Py_UNREACHABLE();
865 }
866 return 1;
867}
868
869static int
870astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
871{
872 CALL(astfold_pattern, expr_ty, node_->pattern);
873 CALL_OPT(astfold_expr, expr_ty, node_->guard);
874 CALL_SEQ(astfold_stmt, stmt, node_->body);
875 return 1;
876}
877
INADA Naoki7ea143a2017-12-14 16:47:20 +0900878#undef CALL
879#undef CALL_OPT
880#undef CALL_SEQ
881#undef CALL_INT_SEQ
882
883int
Pablo Galindod112c602020-03-18 23:02:09 +0000884_PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900885{
Pablo Galindod112c602020-03-18 23:02:09 +0000886 int ret = astfold_mod(mod, arena, state);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900887 assert(ret || PyErr_Occurred());
888 return ret;
889}