blob: 22ca6f23aefa30a04dcae6dee8e351cffc405e6b [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{
10 if (val == NULL) {
11 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
12 return 0;
13 }
14 PyErr_Clear();
15 return 1;
16 }
17 if (PyArena_AddPyObject(arena, val) < 0) {
18 Py_DECREF(val);
19 return 0;
20 }
21 node->kind = Constant_kind;
Pablo Galindo33986462020-04-14 21:40:41 +010022 node->v.Constant.kind = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +090023 node->v.Constant.value = val;
24 return 1;
25}
26
27#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
28
29static PyObject*
30unary_not(PyObject *v)
31{
32 int r = PyObject_IsTrue(v);
33 if (r < 0)
34 return NULL;
35 return PyBool_FromLong(!r);
36}
37
38static int
Pablo Galindod112c602020-03-18 23:02:09 +000039fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +090040{
41 expr_ty arg = node->v.UnaryOp.operand;
42
Serhiy Storchaka3f228112018-09-27 17:42:37 +030043 if (arg->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090044 /* Fold not into comparison */
45 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
46 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
47 /* Eq and NotEq are often implemented in terms of one another, so
48 folding not (self == other) into self != other breaks implementation
49 of !=. Detecting such cases doesn't seem worthwhile.
50 Python uses </> for 'is subset'/'is superset' operations on sets.
51 They don't satisfy not folding laws. */
52 int op = asdl_seq_GET(arg->v.Compare.ops, 0);
53 switch (op) {
54 case Is:
55 op = IsNot;
56 break;
57 case IsNot:
58 op = Is;
59 break;
60 case In:
61 op = NotIn;
62 break;
63 case NotIn:
64 op = In;
65 break;
66 default:
67 op = 0;
68 }
69 if (op) {
70 asdl_seq_SET(arg->v.Compare.ops, 0, op);
71 COPY_NODE(node, arg);
72 return 1;
73 }
74 }
75 return 1;
76 }
77
78 typedef PyObject *(*unary_op)(PyObject*);
79 static const unary_op ops[] = {
80 [Invert] = PyNumber_Invert,
81 [Not] = unary_not,
82 [UAdd] = PyNumber_Positive,
83 [USub] = PyNumber_Negative,
84 };
Serhiy Storchaka3f228112018-09-27 17:42:37 +030085 PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +090086 return make_const(node, newval, arena);
87}
88
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +020089/* Check whether a collection doesn't containing too much items (including
90 subcollections). This protects from creating a constant that needs
91 too much time for calculating a hash.
92 "limit" is the maximal number of items.
93 Returns the negative number if the total number of items exceeds the
94 limit. Otherwise returns the limit minus the total number of items.
95*/
96
97static Py_ssize_t
98check_complexity(PyObject *obj, Py_ssize_t limit)
99{
100 if (PyTuple_Check(obj)) {
101 Py_ssize_t i;
102 limit -= PyTuple_GET_SIZE(obj);
103 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
104 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
105 }
106 return limit;
107 }
108 else if (PyFrozenSet_Check(obj)) {
109 Py_ssize_t i = 0;
110 PyObject *item;
111 Py_hash_t hash;
112 limit -= PySet_GET_SIZE(obj);
113 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
114 limit = check_complexity(item, limit);
115 }
116 }
117 return limit;
118}
119
120#define MAX_INT_SIZE 128 /* bits */
121#define MAX_COLLECTION_SIZE 256 /* items */
122#define MAX_STR_SIZE 4096 /* characters */
123#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
124
125static PyObject *
126safe_multiply(PyObject *v, PyObject *w)
127{
128 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
129 size_t vbits = _PyLong_NumBits(v);
130 size_t wbits = _PyLong_NumBits(w);
131 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
132 return NULL;
133 }
134 if (vbits + wbits > MAX_INT_SIZE) {
135 return NULL;
136 }
137 }
138 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
139 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
140 PySet_GET_SIZE(w);
141 if (size) {
142 long n = PyLong_AsLong(v);
143 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
144 return NULL;
145 }
146 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
147 return NULL;
148 }
149 }
150 }
151 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
152 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
153 PyBytes_GET_SIZE(w);
154 if (size) {
155 long n = PyLong_AsLong(v);
156 if (n < 0 || n > MAX_STR_SIZE / size) {
157 return NULL;
158 }
159 }
160 }
161 else if (PyLong_Check(w) &&
162 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
163 PyUnicode_Check(v) || PyBytes_Check(v)))
164 {
165 return safe_multiply(w, v);
166 }
167
168 return PyNumber_Multiply(v, w);
169}
170
171static PyObject *
172safe_power(PyObject *v, PyObject *w)
173{
174 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
175 size_t vbits = _PyLong_NumBits(v);
176 size_t wbits = PyLong_AsSize_t(w);
177 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
178 return NULL;
179 }
180 if (vbits > MAX_INT_SIZE / wbits) {
181 return NULL;
182 }
183 }
184
185 return PyNumber_Power(v, w, Py_None);
186}
187
188static PyObject *
189safe_lshift(PyObject *v, PyObject *w)
190{
191 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
192 size_t vbits = _PyLong_NumBits(v);
193 size_t wbits = PyLong_AsSize_t(w);
194 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
195 return NULL;
196 }
197 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
198 return NULL;
199 }
200 }
201
202 return PyNumber_Lshift(v, w);
203}
204
205static PyObject *
206safe_mod(PyObject *v, PyObject *w)
207{
208 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
209 return NULL;
210 }
211
212 return PyNumber_Remainder(v, w);
213}
214
INADA Naoki7ea143a2017-12-14 16:47:20 +0900215static int
Pablo Galindod112c602020-03-18 23:02:09 +0000216fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900217{
218 expr_ty lhs, rhs;
219 lhs = node->v.BinOp.left;
220 rhs = node->v.BinOp.right;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300221 if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900222 return 1;
223 }
224
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300225 PyObject *lv = lhs->v.Constant.value;
226 PyObject *rv = rhs->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900227 PyObject *newval;
228
229 switch (node->v.BinOp.op) {
230 case Add:
231 newval = PyNumber_Add(lv, rv);
232 break;
233 case Sub:
234 newval = PyNumber_Subtract(lv, rv);
235 break;
236 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200237 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900238 break;
239 case Div:
240 newval = PyNumber_TrueDivide(lv, rv);
241 break;
242 case FloorDiv:
243 newval = PyNumber_FloorDivide(lv, rv);
244 break;
245 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200246 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900247 break;
248 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200249 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900250 break;
251 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200252 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900253 break;
254 case RShift:
255 newval = PyNumber_Rshift(lv, rv);
256 break;
257 case BitOr:
258 newval = PyNumber_Or(lv, rv);
259 break;
260 case BitXor:
261 newval = PyNumber_Xor(lv, rv);
262 break;
263 case BitAnd:
264 newval = PyNumber_And(lv, rv);
265 break;
266 default: // Unknown operator
267 return 1;
268 }
269
INADA Naoki7ea143a2017-12-14 16:47:20 +0900270 return make_const(node, newval, arena);
271}
272
273static PyObject*
Pablo Galindoa5634c42020-09-16 19:42:00 +0100274make_const_tuple(asdl_expr_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900275{
276 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
277 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300278 if (e->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900279 return NULL;
280 }
281 }
282
283 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
284 if (newval == NULL) {
285 return NULL;
286 }
287
288 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
289 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300290 PyObject *v = e->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900291 Py_INCREF(v);
292 PyTuple_SET_ITEM(newval, i, v);
293 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900294 return newval;
295}
296
297static int
Pablo Galindod112c602020-03-18 23:02:09 +0000298fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900299{
300 PyObject *newval;
301
302 if (node->v.Tuple.ctx != Load)
303 return 1;
304
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200305 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900306 return make_const(node, newval, arena);
307}
308
309static int
Pablo Galindod112c602020-03-18 23:02:09 +0000310fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900311{
312 PyObject *newval;
313 expr_ty arg, idx;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900314
315 arg = node->v.Subscript.value;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200316 idx = node->v.Subscript.slice;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900317 if (node->v.Subscript.ctx != Load ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300318 arg->kind != Constant_kind ||
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200319 idx->kind != Constant_kind)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900320 {
321 return 1;
322 }
323
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300324 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900325 return make_const(node, newval, arena);
326}
327
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200328/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200329 tuple or frozenset respectively. Change literal list of
330 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200331 Used for right operand of "in" and "not in" tests and for iterable
332 in "for" loop and comprehensions.
333*/
334static int
Pablo Galindod112c602020-03-18 23:02:09 +0000335fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200336{
337 PyObject *newval;
338 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200339 /* First change a list into tuple. */
Pablo Galindoa5634c42020-09-16 19:42:00 +0100340 asdl_expr_seq *elts = arg->v.List.elts;
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200341 Py_ssize_t n = asdl_seq_LEN(elts);
342 for (Py_ssize_t i = 0; i < n; i++) {
343 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
344 if (e->kind == Starred_kind) {
345 return 1;
346 }
347 }
348 expr_context_ty ctx = arg->v.List.ctx;
349 arg->kind = Tuple_kind;
350 arg->v.Tuple.elts = elts;
351 arg->v.Tuple.ctx = ctx;
352 /* Try to create a constant tuple. */
353 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200354 }
355 else if (arg->kind == Set_kind) {
356 newval = make_const_tuple(arg->v.Set.elts);
357 if (newval) {
358 Py_SETREF(newval, PyFrozenSet_New(newval));
359 }
360 }
361 else {
362 return 1;
363 }
364 return make_const(arg, newval, arena);
365}
366
INADA Naoki7ea143a2017-12-14 16:47:20 +0900367static int
Pablo Galindod112c602020-03-18 23:02:09 +0000368fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900369{
370 asdl_int_seq *ops;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100371 asdl_expr_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100372 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900373
374 ops = node->v.Compare.ops;
375 args = node->v.Compare.comparators;
376 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200377 /* Change literal list or set in 'in' or 'not in' into
378 tuple or frozenset respectively. */
379 i = asdl_seq_LEN(ops) - 1;
380 int op = asdl_seq_GET(ops, i);
381 if (op == In || op == NotIn) {
Pablo Galindod112c602020-03-18 23:02:09 +0000382 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200383 return 0;
384 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900385 }
386 return 1;
387}
388
Pablo Galindod112c602020-03-18 23:02:09 +0000389static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
390static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
391static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
392static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
393static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
394static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Pablo Galindod112c602020-03-18 23:02:09 +0000395static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
396static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900397#define CALL(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000398 if (!FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900399 return 0;
400
401#define CALL_OPT(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000402 if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900403 return 0;
404
405#define CALL_SEQ(FUNC, TYPE, ARG) { \
406 int i; \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100407 asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900408 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100409 TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000410 if (elt != NULL && !FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900411 return 0; \
412 } \
413}
414
415#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
416 int i; \
417 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
418 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
419 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000420 if (!FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900421 return 0; \
422 } \
423}
424
425static int
Pablo Galindoa5634c42020-09-16 19:42:00 +0100426astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300427{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300428 int docstring = _PyAST_GetDocString(stmts) != NULL;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100429 CALL_SEQ(astfold_stmt, stmt, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300430 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
431 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100432 asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300433 if (!values) {
434 return 0;
435 }
436 asdl_seq_SET(values, 0, st->v.Expr.value);
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000437 expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
438 st->end_lineno, st->end_col_offset, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300439 if (!expr) {
440 return 0;
441 }
442 st->v.Expr.value = expr;
443 }
444 return 1;
445}
446
447static int
Pablo Galindod112c602020-03-18 23:02:09 +0000448astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900449{
450 switch (node_->kind) {
451 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300452 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900453 break;
454 case Interactive_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100455 CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900456 break;
457 case Expression_kind:
458 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
459 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900460 default:
461 break;
462 }
463 return 1;
464}
465
466static int
Pablo Galindod112c602020-03-18 23:02:09 +0000467astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900468{
469 switch (node_->kind) {
470 case BoolOp_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100471 CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900472 break;
473 case BinOp_kind:
474 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
475 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
476 CALL(fold_binop, expr_ty, node_);
477 break;
478 case UnaryOp_kind:
479 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
480 CALL(fold_unaryop, expr_ty, node_);
481 break;
482 case Lambda_kind:
483 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
484 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
485 break;
486 case IfExp_kind:
487 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
488 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
489 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
490 break;
491 case Dict_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100492 CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);
493 CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900494 break;
495 case Set_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100496 CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900497 break;
498 case ListComp_kind:
499 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100500 CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900501 break;
502 case SetComp_kind:
503 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100504 CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900505 break;
506 case DictComp_kind:
507 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
508 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100509 CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900510 break;
511 case GeneratorExp_kind:
512 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100513 CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900514 break;
515 case Await_kind:
516 CALL(astfold_expr, expr_ty, node_->v.Await.value);
517 break;
518 case Yield_kind:
519 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
520 break;
521 case YieldFrom_kind:
522 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
523 break;
524 case Compare_kind:
525 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100526 CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900527 CALL(fold_compare, expr_ty, node_);
528 break;
529 case Call_kind:
530 CALL(astfold_expr, expr_ty, node_->v.Call.func);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100531 CALL_SEQ(astfold_expr, expr, node_->v.Call.args);
532 CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900533 break;
534 case FormattedValue_kind:
535 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
536 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
537 break;
538 case JoinedStr_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100539 CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900540 break;
541 case Attribute_kind:
542 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
543 break;
544 case Subscript_kind:
545 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200546 CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900547 CALL(fold_subscr, expr_ty, node_);
548 break;
549 case Starred_kind:
550 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
551 break;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200552 case Slice_kind:
553 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
554 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
555 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
556 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900557 case List_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100558 CALL_SEQ(astfold_expr, expr, node_->v.List.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900559 break;
560 case Tuple_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100561 CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900562 CALL(fold_tuple, expr_ty, node_);
563 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200564 case Name_kind:
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100565 if (node_->v.Name.ctx == Load &&
566 _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
Pablo Galindod112c602020-03-18 23:02:09 +0000567 return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200568 }
569 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900570 default:
571 break;
572 }
573 return 1;
574}
575
576static int
Pablo Galindod112c602020-03-18 23:02:09 +0000577astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900578{
579 CALL(astfold_expr, expr_ty, node_->value);
580 return 1;
581}
582
583static int
Pablo Galindod112c602020-03-18 23:02:09 +0000584astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900585{
586 CALL(astfold_expr, expr_ty, node_->target);
587 CALL(astfold_expr, expr_ty, node_->iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100588 CALL_SEQ(astfold_expr, expr, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200589
590 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900591 return 1;
592}
593
594static int
Pablo Galindod112c602020-03-18 23:02:09 +0000595astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900596{
Pablo Galindoa5634c42020-09-16 19:42:00 +0100597 CALL_SEQ(astfold_expr, expr, node_->kw_defaults);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100598 CALL_SEQ(astfold_expr, expr, node_->defaults);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900599 return 1;
600}
601
602static int
Pablo Galindod112c602020-03-18 23:02:09 +0000603astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900604{
605 switch (node_->kind) {
606 case FunctionDef_kind:
607 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300608 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100609 CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900610 break;
611 case AsyncFunctionDef_kind:
612 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300613 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100614 CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900615 break;
616 case ClassDef_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100617 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
618 CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300619 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100620 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900621 break;
622 case Return_kind:
623 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
624 break;
625 case Delete_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100626 CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900627 break;
628 case Assign_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100629 CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900630 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
631 break;
632 case AugAssign_kind:
633 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
634 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
635 break;
636 case AnnAssign_kind:
637 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900638 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
639 break;
640 case For_kind:
641 CALL(astfold_expr, expr_ty, node_->v.For.target);
642 CALL(astfold_expr, expr_ty, node_->v.For.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100643 CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
644 CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200645
646 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900647 break;
648 case AsyncFor_kind:
649 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
650 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100651 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
652 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900653 break;
654 case While_kind:
655 CALL(astfold_expr, expr_ty, node_->v.While.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100656 CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
657 CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900658 break;
659 case If_kind:
660 CALL(astfold_expr, expr_ty, node_->v.If.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100661 CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);
662 CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900663 break;
664 case With_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100665 CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);
666 CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900667 break;
668 case AsyncWith_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100669 CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);
670 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900671 break;
672 case Raise_kind:
673 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
674 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
675 break;
676 case Try_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100677 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
678 CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
679 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
680 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900681 break;
682 case Assert_kind:
683 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
684 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
685 break;
686 case Expr_kind:
687 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
688 break;
689 default:
690 break;
691 }
692 return 1;
693}
694
695static int
Pablo Galindod112c602020-03-18 23:02:09 +0000696astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900697{
698 switch (node_->kind) {
699 case ExceptHandler_kind:
700 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100701 CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900702 break;
703 default:
704 break;
705 }
706 return 1;
707}
708
709static int
Pablo Galindod112c602020-03-18 23:02:09 +0000710astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900711{
712 CALL(astfold_expr, expr_ty, node_->context_expr);
713 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
714 return 1;
715}
716
717#undef CALL
718#undef CALL_OPT
719#undef CALL_SEQ
720#undef CALL_INT_SEQ
721
722int
Pablo Galindod112c602020-03-18 23:02:09 +0000723_PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900724{
Pablo Galindod112c602020-03-18 23:02:09 +0000725 int ret = astfold_mod(mod, arena, state);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900726 assert(ret || PyErr_Occurred());
727 return ret;
728}