blob: 6eb514e24f9d7e94396034b5e51d3ede334d434d [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
Serhiy Storchakaface87c2021-04-25 13:38:00 +03005#include "pycore_pystate.h" // _PyThreadState_GET()
INADA Naoki7ea143a2017-12-14 16:47:20 +09006
7
INADA Naoki7ea143a2017-12-14 16:47:20 +09008static int
9make_const(expr_ty node, PyObject *val, PyArena *arena)
10{
Nick Coghlan8805a4d2020-11-07 22:35:17 +100011 // Even if no new value was calculated, make_const may still
12 // need to clear an error (e.g. for division by zero)
INADA Naoki7ea143a2017-12-14 16:47:20 +090013 if (val == NULL) {
14 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
15 return 0;
16 }
17 PyErr_Clear();
18 return 1;
19 }
Victor Stinner8370e072021-03-24 02:23:01 +010020 if (_PyArena_AddPyObject(arena, val) < 0) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090021 Py_DECREF(val);
22 return 0;
23 }
24 node->kind = Constant_kind;
Pablo Galindo33986462020-04-14 21:40:41 +010025 node->v.Constant.kind = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +090026 node->v.Constant.value = val;
27 return 1;
28}
29
30#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
31
32static PyObject*
33unary_not(PyObject *v)
34{
35 int r = PyObject_IsTrue(v);
36 if (r < 0)
37 return NULL;
38 return PyBool_FromLong(!r);
39}
40
41static int
Pablo Galindod112c602020-03-18 23:02:09 +000042fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +090043{
44 expr_ty arg = node->v.UnaryOp.operand;
45
Serhiy Storchaka3f228112018-09-27 17:42:37 +030046 if (arg->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090047 /* Fold not into comparison */
48 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
49 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
50 /* Eq and NotEq are often implemented in terms of one another, so
51 folding not (self == other) into self != other breaks implementation
52 of !=. Detecting such cases doesn't seem worthwhile.
53 Python uses </> for 'is subset'/'is superset' operations on sets.
54 They don't satisfy not folding laws. */
Nick Coghlan8805a4d2020-11-07 22:35:17 +100055 cmpop_ty op = asdl_seq_GET(arg->v.Compare.ops, 0);
INADA Naoki7ea143a2017-12-14 16:47:20 +090056 switch (op) {
57 case Is:
58 op = IsNot;
59 break;
60 case IsNot:
61 op = Is;
62 break;
63 case In:
64 op = NotIn;
65 break;
66 case NotIn:
67 op = In;
68 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +100069 // The remaining comparison operators can't be safely inverted
70 case Eq:
71 case NotEq:
72 case Lt:
73 case LtE:
74 case Gt:
75 case GtE:
76 op = 0; // The AST enums leave "0" free as an "unused" marker
77 break;
78 // No default case, so the compiler will emit a warning if new
79 // comparison operators are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +090080 }
81 if (op) {
82 asdl_seq_SET(arg->v.Compare.ops, 0, op);
83 COPY_NODE(node, arg);
84 return 1;
85 }
86 }
87 return 1;
88 }
89
90 typedef PyObject *(*unary_op)(PyObject*);
91 static const unary_op ops[] = {
92 [Invert] = PyNumber_Invert,
93 [Not] = unary_not,
94 [UAdd] = PyNumber_Positive,
95 [USub] = PyNumber_Negative,
96 };
Serhiy Storchaka3f228112018-09-27 17:42:37 +030097 PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +090098 return make_const(node, newval, arena);
99}
100
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200101/* Check whether a collection doesn't containing too much items (including
102 subcollections). This protects from creating a constant that needs
103 too much time for calculating a hash.
104 "limit" is the maximal number of items.
105 Returns the negative number if the total number of items exceeds the
106 limit. Otherwise returns the limit minus the total number of items.
107*/
108
109static Py_ssize_t
110check_complexity(PyObject *obj, Py_ssize_t limit)
111{
112 if (PyTuple_Check(obj)) {
113 Py_ssize_t i;
114 limit -= PyTuple_GET_SIZE(obj);
115 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
116 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
117 }
118 return limit;
119 }
120 else if (PyFrozenSet_Check(obj)) {
121 Py_ssize_t i = 0;
122 PyObject *item;
123 Py_hash_t hash;
124 limit -= PySet_GET_SIZE(obj);
125 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
126 limit = check_complexity(item, limit);
127 }
128 }
129 return limit;
130}
131
132#define MAX_INT_SIZE 128 /* bits */
133#define MAX_COLLECTION_SIZE 256 /* items */
134#define MAX_STR_SIZE 4096 /* characters */
135#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
136
137static PyObject *
138safe_multiply(PyObject *v, PyObject *w)
139{
140 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
141 size_t vbits = _PyLong_NumBits(v);
142 size_t wbits = _PyLong_NumBits(w);
143 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
144 return NULL;
145 }
146 if (vbits + wbits > MAX_INT_SIZE) {
147 return NULL;
148 }
149 }
150 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
151 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
152 PySet_GET_SIZE(w);
153 if (size) {
154 long n = PyLong_AsLong(v);
155 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
156 return NULL;
157 }
158 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
159 return NULL;
160 }
161 }
162 }
163 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
164 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
165 PyBytes_GET_SIZE(w);
166 if (size) {
167 long n = PyLong_AsLong(v);
168 if (n < 0 || n > MAX_STR_SIZE / size) {
169 return NULL;
170 }
171 }
172 }
173 else if (PyLong_Check(w) &&
174 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
175 PyUnicode_Check(v) || PyBytes_Check(v)))
176 {
177 return safe_multiply(w, v);
178 }
179
180 return PyNumber_Multiply(v, w);
181}
182
183static PyObject *
184safe_power(PyObject *v, PyObject *w)
185{
186 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
187 size_t vbits = _PyLong_NumBits(v);
188 size_t wbits = PyLong_AsSize_t(w);
189 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
190 return NULL;
191 }
192 if (vbits > MAX_INT_SIZE / wbits) {
193 return NULL;
194 }
195 }
196
197 return PyNumber_Power(v, w, Py_None);
198}
199
200static PyObject *
201safe_lshift(PyObject *v, PyObject *w)
202{
203 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
204 size_t vbits = _PyLong_NumBits(v);
205 size_t wbits = PyLong_AsSize_t(w);
206 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
207 return NULL;
208 }
209 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
210 return NULL;
211 }
212 }
213
214 return PyNumber_Lshift(v, w);
215}
216
217static PyObject *
218safe_mod(PyObject *v, PyObject *w)
219{
220 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
221 return NULL;
222 }
223
224 return PyNumber_Remainder(v, w);
225}
226
INADA Naoki7ea143a2017-12-14 16:47:20 +0900227static int
Pablo Galindod112c602020-03-18 23:02:09 +0000228fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900229{
230 expr_ty lhs, rhs;
231 lhs = node->v.BinOp.left;
232 rhs = node->v.BinOp.right;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300233 if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900234 return 1;
235 }
236
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300237 PyObject *lv = lhs->v.Constant.value;
238 PyObject *rv = rhs->v.Constant.value;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000239 PyObject *newval = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900240
241 switch (node->v.BinOp.op) {
242 case Add:
243 newval = PyNumber_Add(lv, rv);
244 break;
245 case Sub:
246 newval = PyNumber_Subtract(lv, rv);
247 break;
248 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200249 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900250 break;
251 case Div:
252 newval = PyNumber_TrueDivide(lv, rv);
253 break;
254 case FloorDiv:
255 newval = PyNumber_FloorDivide(lv, rv);
256 break;
257 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200258 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900259 break;
260 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200261 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900262 break;
263 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200264 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900265 break;
266 case RShift:
267 newval = PyNumber_Rshift(lv, rv);
268 break;
269 case BitOr:
270 newval = PyNumber_Or(lv, rv);
271 break;
272 case BitXor:
273 newval = PyNumber_Xor(lv, rv);
274 break;
275 case BitAnd:
276 newval = PyNumber_And(lv, rv);
277 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000278 // No builtin constants implement the following operators
279 case MatMult:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900280 return 1;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000281 // No default case, so the compiler will emit a warning if new binary
282 // operators are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900283 }
284
INADA Naoki7ea143a2017-12-14 16:47:20 +0900285 return make_const(node, newval, arena);
286}
287
288static PyObject*
Pablo Galindoa5634c42020-09-16 19:42:00 +0100289make_const_tuple(asdl_expr_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900290{
291 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
292 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300293 if (e->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900294 return NULL;
295 }
296 }
297
298 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
299 if (newval == NULL) {
300 return NULL;
301 }
302
303 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
304 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300305 PyObject *v = e->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900306 Py_INCREF(v);
307 PyTuple_SET_ITEM(newval, i, v);
308 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900309 return newval;
310}
311
312static int
Pablo Galindod112c602020-03-18 23:02:09 +0000313fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900314{
315 PyObject *newval;
316
317 if (node->v.Tuple.ctx != Load)
318 return 1;
319
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200320 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900321 return make_const(node, newval, arena);
322}
323
324static int
Pablo Galindod112c602020-03-18 23:02:09 +0000325fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900326{
327 PyObject *newval;
328 expr_ty arg, idx;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900329
330 arg = node->v.Subscript.value;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200331 idx = node->v.Subscript.slice;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900332 if (node->v.Subscript.ctx != Load ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300333 arg->kind != Constant_kind ||
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200334 idx->kind != Constant_kind)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900335 {
336 return 1;
337 }
338
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300339 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900340 return make_const(node, newval, arena);
341}
342
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200343/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200344 tuple or frozenset respectively. Change literal list of
345 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200346 Used for right operand of "in" and "not in" tests and for iterable
347 in "for" loop and comprehensions.
348*/
349static int
Pablo Galindod112c602020-03-18 23:02:09 +0000350fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200351{
352 PyObject *newval;
353 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200354 /* First change a list into tuple. */
Pablo Galindoa5634c42020-09-16 19:42:00 +0100355 asdl_expr_seq *elts = arg->v.List.elts;
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200356 Py_ssize_t n = asdl_seq_LEN(elts);
357 for (Py_ssize_t i = 0; i < n; i++) {
358 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
359 if (e->kind == Starred_kind) {
360 return 1;
361 }
362 }
363 expr_context_ty ctx = arg->v.List.ctx;
364 arg->kind = Tuple_kind;
365 arg->v.Tuple.elts = elts;
366 arg->v.Tuple.ctx = ctx;
367 /* Try to create a constant tuple. */
368 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200369 }
370 else if (arg->kind == Set_kind) {
371 newval = make_const_tuple(arg->v.Set.elts);
372 if (newval) {
373 Py_SETREF(newval, PyFrozenSet_New(newval));
374 }
375 }
376 else {
377 return 1;
378 }
379 return make_const(arg, newval, arena);
380}
381
INADA Naoki7ea143a2017-12-14 16:47:20 +0900382static int
Pablo Galindod112c602020-03-18 23:02:09 +0000383fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900384{
385 asdl_int_seq *ops;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100386 asdl_expr_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100387 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900388
389 ops = node->v.Compare.ops;
390 args = node->v.Compare.comparators;
391 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200392 /* Change literal list or set in 'in' or 'not in' into
393 tuple or frozenset respectively. */
394 i = asdl_seq_LEN(ops) - 1;
395 int op = asdl_seq_GET(ops, i);
396 if (op == In || op == NotIn) {
Pablo Galindod112c602020-03-18 23:02:09 +0000397 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200398 return 0;
399 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900400 }
401 return 1;
402}
403
Pablo Galindod112c602020-03-18 23:02:09 +0000404static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
405static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
406static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
407static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
408static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
409static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100410static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Pablo Galindod112c602020-03-18 23:02:09 +0000411static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
412static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Brandt Bucher145bf262021-02-26 14:51:55 -0800413static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
414static int astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
415
INADA Naoki7ea143a2017-12-14 16:47:20 +0900416#define CALL(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000417 if (!FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900418 return 0;
419
420#define CALL_OPT(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000421 if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900422 return 0;
423
424#define CALL_SEQ(FUNC, TYPE, ARG) { \
425 int i; \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100426 asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900427 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100428 TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000429 if (elt != NULL && !FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900430 return 0; \
431 } \
432}
433
434#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
435 int i; \
436 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
437 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
438 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000439 if (!FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900440 return 0; \
441 } \
442}
443
444static int
Pablo Galindoa5634c42020-09-16 19:42:00 +0100445astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300446{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300447 int docstring = _PyAST_GetDocString(stmts) != NULL;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100448 CALL_SEQ(astfold_stmt, stmt, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300449 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
450 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100451 asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300452 if (!values) {
453 return 0;
454 }
455 asdl_seq_SET(values, 0, st->v.Expr.value);
Victor Stinnerd27f8d22021-04-07 21:34:22 +0200456 expr_ty expr = _PyAST_JoinedStr(values, st->lineno, st->col_offset,
457 st->end_lineno, st->end_col_offset,
458 ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300459 if (!expr) {
460 return 0;
461 }
462 st->v.Expr.value = expr;
463 }
464 return 1;
465}
466
467static int
Pablo Galindod112c602020-03-18 23:02:09 +0000468astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900469{
470 switch (node_->kind) {
471 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300472 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900473 break;
474 case Interactive_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100475 CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900476 break;
477 case Expression_kind:
478 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
479 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000480 // The following top level nodes don't participate in constant folding
481 case FunctionType_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900482 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000483 // No default case, so the compiler will emit a warning if new top level
484 // compilation nodes are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900485 }
486 return 1;
487}
488
489static int
Pablo Galindod112c602020-03-18 23:02:09 +0000490astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900491{
Serhiy Storchakaface87c2021-04-25 13:38:00 +0300492 if (++state->recursion_depth > state->recursion_limit) {
493 PyErr_SetString(PyExc_RecursionError,
494 "maximum recursion depth exceeded during compilation");
495 return 0;
496 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900497 switch (node_->kind) {
498 case BoolOp_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100499 CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900500 break;
501 case BinOp_kind:
502 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
503 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
504 CALL(fold_binop, expr_ty, node_);
505 break;
506 case UnaryOp_kind:
507 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
508 CALL(fold_unaryop, expr_ty, node_);
509 break;
510 case Lambda_kind:
511 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
512 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
513 break;
514 case IfExp_kind:
515 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
516 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
517 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
518 break;
519 case Dict_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100520 CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);
521 CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900522 break;
523 case Set_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100524 CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900525 break;
526 case ListComp_kind:
527 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100528 CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900529 break;
530 case SetComp_kind:
531 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100532 CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900533 break;
534 case DictComp_kind:
535 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
536 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100537 CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900538 break;
539 case GeneratorExp_kind:
540 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100541 CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900542 break;
543 case Await_kind:
544 CALL(astfold_expr, expr_ty, node_->v.Await.value);
545 break;
546 case Yield_kind:
547 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
548 break;
549 case YieldFrom_kind:
550 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
551 break;
552 case Compare_kind:
553 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100554 CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900555 CALL(fold_compare, expr_ty, node_);
556 break;
557 case Call_kind:
558 CALL(astfold_expr, expr_ty, node_->v.Call.func);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100559 CALL_SEQ(astfold_expr, expr, node_->v.Call.args);
560 CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900561 break;
562 case FormattedValue_kind:
563 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
564 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
565 break;
566 case JoinedStr_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100567 CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900568 break;
569 case Attribute_kind:
570 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
571 break;
572 case Subscript_kind:
573 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200574 CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900575 CALL(fold_subscr, expr_ty, node_);
576 break;
577 case Starred_kind:
578 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
579 break;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200580 case Slice_kind:
581 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
582 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
583 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
584 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900585 case List_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100586 CALL_SEQ(astfold_expr, expr, node_->v.List.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900587 break;
588 case Tuple_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100589 CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900590 CALL(fold_tuple, expr_ty, node_);
591 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200592 case Name_kind:
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100593 if (node_->v.Name.ctx == Load &&
594 _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
Serhiy Storchakaface87c2021-04-25 13:38:00 +0300595 state->recursion_depth--;
Pablo Galindod112c602020-03-18 23:02:09 +0000596 return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200597 }
598 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000599 case NamedExpr_kind:
600 CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900601 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000602 case Constant_kind:
603 // Already a constant, nothing further to do
604 break;
Brandt Bucher145bf262021-02-26 14:51:55 -0800605 case MatchAs_kind:
606 case MatchOr_kind:
607 // These can't occur outside of patterns.
608 Py_UNREACHABLE();
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000609 // No default case, so the compiler will emit a warning if new expression
610 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900611 }
Serhiy Storchakaface87c2021-04-25 13:38:00 +0300612 state->recursion_depth--;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900613 return 1;
614}
615
616static int
Pablo Galindod112c602020-03-18 23:02:09 +0000617astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900618{
619 CALL(astfold_expr, expr_ty, node_->value);
620 return 1;
621}
622
623static int
Pablo Galindod112c602020-03-18 23:02:09 +0000624astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900625{
626 CALL(astfold_expr, expr_ty, node_->target);
627 CALL(astfold_expr, expr_ty, node_->iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100628 CALL_SEQ(astfold_expr, expr, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200629
630 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900631 return 1;
632}
633
634static int
Pablo Galindod112c602020-03-18 23:02:09 +0000635astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900636{
Pablo Galindob0544ba2021-04-21 12:41:19 +0100637 CALL_SEQ(astfold_arg, arg, node_->posonlyargs);
638 CALL_SEQ(astfold_arg, arg, node_->args);
639 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
640 CALL_SEQ(astfold_arg, arg, node_->kwonlyargs);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100641 CALL_SEQ(astfold_expr, expr, node_->kw_defaults);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100642 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100643 CALL_SEQ(astfold_expr, expr, node_->defaults);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900644 return 1;
645}
646
647static int
Pablo Galindob0544ba2021-04-21 12:41:19 +0100648astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
649{
650 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
651 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
652 }
653 return 1;
654}
655
656static int
Pablo Galindod112c602020-03-18 23:02:09 +0000657astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900658{
Serhiy Storchakaface87c2021-04-25 13:38:00 +0300659 if (++state->recursion_depth > state->recursion_limit) {
660 PyErr_SetString(PyExc_RecursionError,
661 "maximum recursion depth exceeded during compilation");
662 return 0;
663 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900664 switch (node_->kind) {
665 case FunctionDef_kind:
666 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300667 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100668 CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100669 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
670 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
671 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900672 break;
673 case AsyncFunctionDef_kind:
674 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300675 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100676 CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100677 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
678 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
679 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900680 break;
681 case ClassDef_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100682 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
683 CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300684 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100685 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900686 break;
687 case Return_kind:
688 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
689 break;
690 case Delete_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100691 CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900692 break;
693 case Assign_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100694 CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900695 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
696 break;
697 case AugAssign_kind:
698 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
699 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
700 break;
701 case AnnAssign_kind:
702 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100703 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
704 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
705 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900706 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
707 break;
708 case For_kind:
709 CALL(astfold_expr, expr_ty, node_->v.For.target);
710 CALL(astfold_expr, expr_ty, node_->v.For.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100711 CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
712 CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200713
714 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900715 break;
716 case AsyncFor_kind:
717 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
718 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100719 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
720 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900721 break;
722 case While_kind:
723 CALL(astfold_expr, expr_ty, node_->v.While.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100724 CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
725 CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900726 break;
727 case If_kind:
728 CALL(astfold_expr, expr_ty, node_->v.If.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100729 CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);
730 CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900731 break;
732 case With_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100733 CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);
734 CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900735 break;
736 case AsyncWith_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100737 CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);
738 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900739 break;
740 case Raise_kind:
741 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
742 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
743 break;
744 case Try_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100745 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
746 CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
747 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
748 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900749 break;
750 case Assert_kind:
751 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
752 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
753 break;
754 case Expr_kind:
755 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
756 break;
Brandt Bucher145bf262021-02-26 14:51:55 -0800757 case Match_kind:
758 CALL(astfold_expr, expr_ty, node_->v.Match.subject);
759 CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases);
760 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000761 // The following statements don't contain any subexpressions to be folded
762 case Import_kind:
763 case ImportFrom_kind:
764 case Global_kind:
765 case Nonlocal_kind:
766 case Pass_kind:
767 case Break_kind:
768 case Continue_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900769 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000770 // No default case, so the compiler will emit a warning if new statement
771 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900772 }
Serhiy Storchakaface87c2021-04-25 13:38:00 +0300773 state->recursion_depth--;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900774 return 1;
775}
776
777static int
Pablo Galindod112c602020-03-18 23:02:09 +0000778astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900779{
780 switch (node_->kind) {
781 case ExceptHandler_kind:
782 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100783 CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900784 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000785 // No default case, so the compiler will emit a warning if new handler
786 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900787 }
788 return 1;
789}
790
791static int
Pablo Galindod112c602020-03-18 23:02:09 +0000792astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900793{
794 CALL(astfold_expr, expr_ty, node_->context_expr);
795 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
796 return 1;
797}
798
Brandt Bucher145bf262021-02-26 14:51:55 -0800799static int
800astfold_pattern_negative(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
801{
802 assert(node_->kind == UnaryOp_kind);
803 assert(node_->v.UnaryOp.op == USub);
804 assert(node_->v.UnaryOp.operand->kind == Constant_kind);
805 PyObject *value = node_->v.UnaryOp.operand->v.Constant.value;
806 assert(PyComplex_CheckExact(value) ||
807 PyFloat_CheckExact(value) ||
808 PyLong_CheckExact(value));
809 PyObject *negated = PyNumber_Negative(value);
810 if (negated == NULL) {
811 return 0;
812 }
813 assert(PyComplex_CheckExact(negated) ||
814 PyFloat_CheckExact(negated) ||
815 PyLong_CheckExact(negated));
816 return make_const(node_, negated, ctx_);
817}
818
819static int
820astfold_pattern_complex(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
821{
822 expr_ty left = node_->v.BinOp.left;
823 expr_ty right = node_->v.BinOp.right;
824 if (left->kind == UnaryOp_kind) {
825 CALL(astfold_pattern_negative, expr_ty, left);
826 }
827 assert(left->kind = Constant_kind);
828 assert(right->kind = Constant_kind);
829 // LHS must be real, RHS must be imaginary:
830 if (!(PyFloat_CheckExact(left->v.Constant.value) ||
831 PyLong_CheckExact(left->v.Constant.value)) ||
832 !PyComplex_CheckExact(right->v.Constant.value))
833 {
834 // Not actually valid, but it's the compiler's job to complain:
835 return 1;
836 }
837 PyObject *new;
838 if (node_->v.BinOp.op == Add) {
839 new = PyNumber_Add(left->v.Constant.value, right->v.Constant.value);
840 }
841 else {
842 assert(node_->v.BinOp.op == Sub);
843 new = PyNumber_Subtract(left->v.Constant.value, right->v.Constant.value);
844 }
845 if (new == NULL) {
846 return 0;
847 }
848 assert(PyComplex_CheckExact(new));
849 return make_const(node_, new, ctx_);
850}
851
852static int
853astfold_pattern_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
854{
855 CALL(astfold_pattern, expr_ty, node_->value);
856 return 1;
857}
858
859static int
860astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
861{
862 // Don't blindly optimize the pattern as an expr; it plays by its own rules!
863 // Currently, this is only used to form complex/negative numeric constants.
864 switch (node_->kind) {
865 case Attribute_kind:
866 break;
867 case BinOp_kind:
868 CALL(astfold_pattern_complex, expr_ty, node_);
869 break;
870 case Call_kind:
871 CALL_SEQ(astfold_pattern, expr, node_->v.Call.args);
872 CALL_SEQ(astfold_pattern_keyword, keyword, node_->v.Call.keywords);
873 break;
874 case Constant_kind:
875 break;
876 case Dict_kind:
877 CALL_SEQ(astfold_pattern, expr, node_->v.Dict.keys);
878 CALL_SEQ(astfold_pattern, expr, node_->v.Dict.values);
879 break;
880 // Not actually valid, but it's the compiler's job to complain:
881 case JoinedStr_kind:
882 break;
883 case List_kind:
884 CALL_SEQ(astfold_pattern, expr, node_->v.List.elts);
885 break;
886 case MatchAs_kind:
887 CALL(astfold_pattern, expr_ty, node_->v.MatchAs.pattern);
888 break;
889 case MatchOr_kind:
890 CALL_SEQ(astfold_pattern, expr, node_->v.MatchOr.patterns);
891 break;
892 case Name_kind:
893 break;
894 case Starred_kind:
895 CALL(astfold_pattern, expr_ty, node_->v.Starred.value);
896 break;
897 case Tuple_kind:
898 CALL_SEQ(astfold_pattern, expr, node_->v.Tuple.elts);
899 break;
900 case UnaryOp_kind:
901 CALL(astfold_pattern_negative, expr_ty, node_);
902 break;
903 default:
904 Py_UNREACHABLE();
905 }
906 return 1;
907}
908
909static int
910astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
911{
912 CALL(astfold_pattern, expr_ty, node_->pattern);
913 CALL_OPT(astfold_expr, expr_ty, node_->guard);
914 CALL_SEQ(astfold_stmt, stmt, node_->body);
915 return 1;
916}
917
INADA Naoki7ea143a2017-12-14 16:47:20 +0900918#undef CALL
919#undef CALL_OPT
920#undef CALL_SEQ
921#undef CALL_INT_SEQ
922
Serhiy Storchakaface87c2021-04-25 13:38:00 +0300923/* See comments in symtable.c. */
924#define COMPILER_STACK_FRAME_SCALE 3
925
INADA Naoki7ea143a2017-12-14 16:47:20 +0900926int
Pablo Galindod112c602020-03-18 23:02:09 +0000927_PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900928{
Serhiy Storchakaface87c2021-04-25 13:38:00 +0300929 PyThreadState *tstate;
930 int recursion_limit = Py_GetRecursionLimit();
931 int starting_recursion_depth;
932
933 /* Setup recursion depth check counters */
934 tstate = _PyThreadState_GET();
935 if (!tstate) {
936 return 0;
937 }
938 /* Be careful here to prevent overflow. */
939 starting_recursion_depth = (tstate->recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
940 tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE : tstate->recursion_depth;
941 state->recursion_depth = starting_recursion_depth;
942 state->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ?
943 recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit;
944
Pablo Galindod112c602020-03-18 23:02:09 +0000945 int ret = astfold_mod(mod, arena, state);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900946 assert(ret || PyErr_Occurred());
Serhiy Storchakaface87c2021-04-25 13:38:00 +0300947
948 /* Check that the recursion depth counting balanced correctly */
949 if (ret && state->recursion_depth != starting_recursion_depth) {
950 PyErr_Format(PyExc_SystemError,
951 "AST optimizer recursion depth mismatch (before=%d, after=%d)",
952 starting_recursion_depth, state->recursion_depth);
953 return 0;
954 }
955
INADA Naoki7ea143a2017-12-14 16:47:20 +0900956 return ret;
957}