blob: 8c958ca7f137630eb6bd662882d92d19dfa0bcc5 [file] [log] [blame]
INADA Naoki7ea143a2017-12-14 16:47:20 +09001/* AST Optimizer */
2#include "Python.h"
3#include "Python-ast.h"
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +03004#include "ast.h"
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 }
19 if (PyArena_AddPyObject(arena, val) < 0) {
20 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);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900411#define CALL(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000412 if (!FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900413 return 0;
414
415#define CALL_OPT(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000416 if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900417 return 0;
418
419#define CALL_SEQ(FUNC, TYPE, ARG) { \
420 int i; \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100421 asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900422 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100423 TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000424 if (elt != NULL && !FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900425 return 0; \
426 } \
427}
428
429#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
430 int i; \
431 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
432 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
433 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000434 if (!FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900435 return 0; \
436 } \
437}
438
439static int
Pablo Galindoa5634c42020-09-16 19:42:00 +0100440astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300441{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300442 int docstring = _PyAST_GetDocString(stmts) != NULL;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100443 CALL_SEQ(astfold_stmt, stmt, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300444 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
445 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100446 asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300447 if (!values) {
448 return 0;
449 }
450 asdl_seq_SET(values, 0, st->v.Expr.value);
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000451 expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
452 st->end_lineno, st->end_col_offset, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300453 if (!expr) {
454 return 0;
455 }
456 st->v.Expr.value = expr;
457 }
458 return 1;
459}
460
461static int
Pablo Galindod112c602020-03-18 23:02:09 +0000462astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900463{
464 switch (node_->kind) {
465 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300466 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900467 break;
468 case Interactive_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100469 CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900470 break;
471 case Expression_kind:
472 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
473 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000474 // The following top level nodes don't participate in constant folding
475 case FunctionType_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900476 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000477 // No default case, so the compiler will emit a warning if new top level
478 // compilation nodes are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900479 }
480 return 1;
481}
482
483static int
Pablo Galindod112c602020-03-18 23:02:09 +0000484astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900485{
486 switch (node_->kind) {
487 case BoolOp_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100488 CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900489 break;
490 case BinOp_kind:
491 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
492 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
493 CALL(fold_binop, expr_ty, node_);
494 break;
495 case UnaryOp_kind:
496 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
497 CALL(fold_unaryop, expr_ty, node_);
498 break;
499 case Lambda_kind:
500 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
501 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
502 break;
503 case IfExp_kind:
504 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
505 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
506 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
507 break;
508 case Dict_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100509 CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);
510 CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900511 break;
512 case Set_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100513 CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900514 break;
515 case ListComp_kind:
516 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100517 CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900518 break;
519 case SetComp_kind:
520 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100521 CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900522 break;
523 case DictComp_kind:
524 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
525 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100526 CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900527 break;
528 case GeneratorExp_kind:
529 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100530 CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900531 break;
532 case Await_kind:
533 CALL(astfold_expr, expr_ty, node_->v.Await.value);
534 break;
535 case Yield_kind:
536 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
537 break;
538 case YieldFrom_kind:
539 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
540 break;
541 case Compare_kind:
542 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100543 CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900544 CALL(fold_compare, expr_ty, node_);
545 break;
546 case Call_kind:
547 CALL(astfold_expr, expr_ty, node_->v.Call.func);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100548 CALL_SEQ(astfold_expr, expr, node_->v.Call.args);
549 CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900550 break;
551 case FormattedValue_kind:
552 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
553 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
554 break;
555 case JoinedStr_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100556 CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900557 break;
558 case Attribute_kind:
559 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
560 break;
561 case Subscript_kind:
562 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200563 CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900564 CALL(fold_subscr, expr_ty, node_);
565 break;
566 case Starred_kind:
567 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
568 break;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200569 case Slice_kind:
570 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
571 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
572 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
573 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900574 case List_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100575 CALL_SEQ(astfold_expr, expr, node_->v.List.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900576 break;
577 case Tuple_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100578 CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900579 CALL(fold_tuple, expr_ty, node_);
580 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200581 case Name_kind:
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100582 if (node_->v.Name.ctx == Load &&
583 _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
Pablo Galindod112c602020-03-18 23:02:09 +0000584 return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200585 }
586 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000587 case NamedExpr_kind:
588 CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900589 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000590 case Constant_kind:
591 // Already a constant, nothing further to do
592 break;
593 // No default case, so the compiler will emit a warning if new expression
594 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900595 }
596 return 1;
597}
598
599static int
Pablo Galindod112c602020-03-18 23:02:09 +0000600astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900601{
602 CALL(astfold_expr, expr_ty, node_->value);
603 return 1;
604}
605
606static int
Pablo Galindod112c602020-03-18 23:02:09 +0000607astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900608{
609 CALL(astfold_expr, expr_ty, node_->target);
610 CALL(astfold_expr, expr_ty, node_->iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100611 CALL_SEQ(astfold_expr, expr, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200612
613 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900614 return 1;
615}
616
617static int
Pablo Galindod112c602020-03-18 23:02:09 +0000618astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900619{
Pablo Galindoa5634c42020-09-16 19:42:00 +0100620 CALL_SEQ(astfold_expr, expr, node_->kw_defaults);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100621 CALL_SEQ(astfold_expr, expr, node_->defaults);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900622 return 1;
623}
624
625static int
Pablo Galindod112c602020-03-18 23:02:09 +0000626astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900627{
628 switch (node_->kind) {
629 case FunctionDef_kind:
630 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300631 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100632 CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900633 break;
634 case AsyncFunctionDef_kind:
635 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300636 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100637 CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900638 break;
639 case ClassDef_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100640 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
641 CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300642 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100643 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900644 break;
645 case Return_kind:
646 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
647 break;
648 case Delete_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100649 CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900650 break;
651 case Assign_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100652 CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900653 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
654 break;
655 case AugAssign_kind:
656 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
657 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
658 break;
659 case AnnAssign_kind:
660 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900661 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
662 break;
663 case For_kind:
664 CALL(astfold_expr, expr_ty, node_->v.For.target);
665 CALL(astfold_expr, expr_ty, node_->v.For.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100666 CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
667 CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200668
669 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900670 break;
671 case AsyncFor_kind:
672 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
673 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100674 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
675 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900676 break;
677 case While_kind:
678 CALL(astfold_expr, expr_ty, node_->v.While.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100679 CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
680 CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900681 break;
682 case If_kind:
683 CALL(astfold_expr, expr_ty, node_->v.If.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100684 CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);
685 CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900686 break;
687 case With_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100688 CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);
689 CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900690 break;
691 case AsyncWith_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100692 CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);
693 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900694 break;
695 case Raise_kind:
696 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
697 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
698 break;
699 case Try_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100700 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
701 CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
702 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
703 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900704 break;
705 case Assert_kind:
706 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
707 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
708 break;
709 case Expr_kind:
710 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
711 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000712 // The following statements don't contain any subexpressions to be folded
713 case Import_kind:
714 case ImportFrom_kind:
715 case Global_kind:
716 case Nonlocal_kind:
717 case Pass_kind:
718 case Break_kind:
719 case Continue_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900720 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000721 // No default case, so the compiler will emit a warning if new statement
722 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900723 }
724 return 1;
725}
726
727static int
Pablo Galindod112c602020-03-18 23:02:09 +0000728astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900729{
730 switch (node_->kind) {
731 case ExceptHandler_kind:
732 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100733 CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900734 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000735 // No default case, so the compiler will emit a warning if new handler
736 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900737 }
738 return 1;
739}
740
741static int
Pablo Galindod112c602020-03-18 23:02:09 +0000742astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900743{
744 CALL(astfold_expr, expr_ty, node_->context_expr);
745 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
746 return 1;
747}
748
749#undef CALL
750#undef CALL_OPT
751#undef CALL_SEQ
752#undef CALL_INT_SEQ
753
754int
Pablo Galindod112c602020-03-18 23:02:09 +0000755_PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900756{
Pablo Galindod112c602020-03-18 23:02:09 +0000757 int ret = astfold_mod(mod, arena, state);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900758 assert(ret || PyErr_Occurred());
759 return ret;
760}