blob: dea20da07e69d6913af1ca972eac74e3fb51b8af [file] [log] [blame]
INADA Naoki7ea143a2017-12-14 16:47:20 +09001/* AST Optimizer */
2#include "Python.h"
Victor Stinner526fdeb2021-03-17 23:50:50 +01003#include "pycore_ast.h" // _PyAST_GetDocString()
Victor Stinnera81fca62021-03-24 00:51:50 +01004#include "pycore_compile.h" // _PyASTOptimizeState
INADA Naoki7ea143a2017-12-14 16:47:20 +09005
6
INADA Naoki7ea143a2017-12-14 16:47:20 +09007static int
8make_const(expr_ty node, PyObject *val, PyArena *arena)
9{
Nick Coghlan8805a4d2020-11-07 22:35:17 +100010 // Even if no new value was calculated, make_const may still
11 // need to clear an error (e.g. for division by zero)
INADA Naoki7ea143a2017-12-14 16:47:20 +090012 if (val == NULL) {
13 if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
14 return 0;
15 }
16 PyErr_Clear();
17 return 1;
18 }
Victor Stinner8370e072021-03-24 02:23:01 +010019 if (_PyArena_AddPyObject(arena, val) < 0) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090020 Py_DECREF(val);
21 return 0;
22 }
23 node->kind = Constant_kind;
Pablo Galindo33986462020-04-14 21:40:41 +010024 node->v.Constant.kind = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +090025 node->v.Constant.value = val;
26 return 1;
27}
28
29#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
30
31static PyObject*
32unary_not(PyObject *v)
33{
34 int r = PyObject_IsTrue(v);
35 if (r < 0)
36 return NULL;
37 return PyBool_FromLong(!r);
38}
39
40static int
Pablo Galindod112c602020-03-18 23:02:09 +000041fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +090042{
43 expr_ty arg = node->v.UnaryOp.operand;
44
Serhiy Storchaka3f228112018-09-27 17:42:37 +030045 if (arg->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +090046 /* Fold not into comparison */
47 if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
48 asdl_seq_LEN(arg->v.Compare.ops) == 1) {
49 /* Eq and NotEq are often implemented in terms of one another, so
50 folding not (self == other) into self != other breaks implementation
51 of !=. Detecting such cases doesn't seem worthwhile.
52 Python uses </> for 'is subset'/'is superset' operations on sets.
53 They don't satisfy not folding laws. */
Nick Coghlan8805a4d2020-11-07 22:35:17 +100054 cmpop_ty op = asdl_seq_GET(arg->v.Compare.ops, 0);
INADA Naoki7ea143a2017-12-14 16:47:20 +090055 switch (op) {
56 case Is:
57 op = IsNot;
58 break;
59 case IsNot:
60 op = Is;
61 break;
62 case In:
63 op = NotIn;
64 break;
65 case NotIn:
66 op = In;
67 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +100068 // The remaining comparison operators can't be safely inverted
69 case Eq:
70 case NotEq:
71 case Lt:
72 case LtE:
73 case Gt:
74 case GtE:
75 op = 0; // The AST enums leave "0" free as an "unused" marker
76 break;
77 // No default case, so the compiler will emit a warning if new
78 // comparison operators are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +090079 }
80 if (op) {
81 asdl_seq_SET(arg->v.Compare.ops, 0, op);
82 COPY_NODE(node, arg);
83 return 1;
84 }
85 }
86 return 1;
87 }
88
89 typedef PyObject *(*unary_op)(PyObject*);
90 static const unary_op ops[] = {
91 [Invert] = PyNumber_Invert,
92 [Not] = unary_not,
93 [UAdd] = PyNumber_Positive,
94 [USub] = PyNumber_Negative,
95 };
Serhiy Storchaka3f228112018-09-27 17:42:37 +030096 PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +090097 return make_const(node, newval, arena);
98}
99
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200100/* Check whether a collection doesn't containing too much items (including
101 subcollections). This protects from creating a constant that needs
102 too much time for calculating a hash.
103 "limit" is the maximal number of items.
104 Returns the negative number if the total number of items exceeds the
105 limit. Otherwise returns the limit minus the total number of items.
106*/
107
108static Py_ssize_t
109check_complexity(PyObject *obj, Py_ssize_t limit)
110{
111 if (PyTuple_Check(obj)) {
112 Py_ssize_t i;
113 limit -= PyTuple_GET_SIZE(obj);
114 for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
115 limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
116 }
117 return limit;
118 }
119 else if (PyFrozenSet_Check(obj)) {
120 Py_ssize_t i = 0;
121 PyObject *item;
122 Py_hash_t hash;
123 limit -= PySet_GET_SIZE(obj);
124 while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
125 limit = check_complexity(item, limit);
126 }
127 }
128 return limit;
129}
130
131#define MAX_INT_SIZE 128 /* bits */
132#define MAX_COLLECTION_SIZE 256 /* items */
133#define MAX_STR_SIZE 4096 /* characters */
134#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
135
136static PyObject *
137safe_multiply(PyObject *v, PyObject *w)
138{
139 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
140 size_t vbits = _PyLong_NumBits(v);
141 size_t wbits = _PyLong_NumBits(w);
142 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
143 return NULL;
144 }
145 if (vbits + wbits > MAX_INT_SIZE) {
146 return NULL;
147 }
148 }
149 else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
150 Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
151 PySet_GET_SIZE(w);
152 if (size) {
153 long n = PyLong_AsLong(v);
154 if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
155 return NULL;
156 }
157 if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
158 return NULL;
159 }
160 }
161 }
162 else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
163 Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
164 PyBytes_GET_SIZE(w);
165 if (size) {
166 long n = PyLong_AsLong(v);
167 if (n < 0 || n > MAX_STR_SIZE / size) {
168 return NULL;
169 }
170 }
171 }
172 else if (PyLong_Check(w) &&
173 (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
174 PyUnicode_Check(v) || PyBytes_Check(v)))
175 {
176 return safe_multiply(w, v);
177 }
178
179 return PyNumber_Multiply(v, w);
180}
181
182static PyObject *
183safe_power(PyObject *v, PyObject *w)
184{
185 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
186 size_t vbits = _PyLong_NumBits(v);
187 size_t wbits = PyLong_AsSize_t(w);
188 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
189 return NULL;
190 }
191 if (vbits > MAX_INT_SIZE / wbits) {
192 return NULL;
193 }
194 }
195
196 return PyNumber_Power(v, w, Py_None);
197}
198
199static PyObject *
200safe_lshift(PyObject *v, PyObject *w)
201{
202 if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
203 size_t vbits = _PyLong_NumBits(v);
204 size_t wbits = PyLong_AsSize_t(w);
205 if (vbits == (size_t)-1 || wbits == (size_t)-1) {
206 return NULL;
207 }
208 if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
209 return NULL;
210 }
211 }
212
213 return PyNumber_Lshift(v, w);
214}
215
216static PyObject *
217safe_mod(PyObject *v, PyObject *w)
218{
219 if (PyUnicode_Check(v) || PyBytes_Check(v)) {
220 return NULL;
221 }
222
223 return PyNumber_Remainder(v, w);
224}
225
INADA Naoki7ea143a2017-12-14 16:47:20 +0900226static int
Pablo Galindod112c602020-03-18 23:02:09 +0000227fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900228{
229 expr_ty lhs, rhs;
230 lhs = node->v.BinOp.left;
231 rhs = node->v.BinOp.right;
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300232 if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900233 return 1;
234 }
235
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300236 PyObject *lv = lhs->v.Constant.value;
237 PyObject *rv = rhs->v.Constant.value;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000238 PyObject *newval = NULL;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900239
240 switch (node->v.BinOp.op) {
241 case Add:
242 newval = PyNumber_Add(lv, rv);
243 break;
244 case Sub:
245 newval = PyNumber_Subtract(lv, rv);
246 break;
247 case Mult:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200248 newval = safe_multiply(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900249 break;
250 case Div:
251 newval = PyNumber_TrueDivide(lv, rv);
252 break;
253 case FloorDiv:
254 newval = PyNumber_FloorDivide(lv, rv);
255 break;
256 case Mod:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200257 newval = safe_mod(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900258 break;
259 case Pow:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200260 newval = safe_power(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900261 break;
262 case LShift:
Serhiy Storchaka2e3f5702017-12-15 14:11:43 +0200263 newval = safe_lshift(lv, rv);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900264 break;
265 case RShift:
266 newval = PyNumber_Rshift(lv, rv);
267 break;
268 case BitOr:
269 newval = PyNumber_Or(lv, rv);
270 break;
271 case BitXor:
272 newval = PyNumber_Xor(lv, rv);
273 break;
274 case BitAnd:
275 newval = PyNumber_And(lv, rv);
276 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000277 // No builtin constants implement the following operators
278 case MatMult:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900279 return 1;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000280 // No default case, so the compiler will emit a warning if new binary
281 // operators are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900282 }
283
INADA Naoki7ea143a2017-12-14 16:47:20 +0900284 return make_const(node, newval, arena);
285}
286
287static PyObject*
Pablo Galindoa5634c42020-09-16 19:42:00 +0100288make_const_tuple(asdl_expr_seq *elts)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900289{
290 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
291 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300292 if (e->kind != Constant_kind) {
INADA Naoki7ea143a2017-12-14 16:47:20 +0900293 return NULL;
294 }
295 }
296
297 PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
298 if (newval == NULL) {
299 return NULL;
300 }
301
302 for (int i = 0; i < asdl_seq_LEN(elts); i++) {
303 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300304 PyObject *v = e->v.Constant.value;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900305 Py_INCREF(v);
306 PyTuple_SET_ITEM(newval, i, v);
307 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900308 return newval;
309}
310
311static int
Pablo Galindod112c602020-03-18 23:02:09 +0000312fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900313{
314 PyObject *newval;
315
316 if (node->v.Tuple.ctx != Load)
317 return 1;
318
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200319 newval = make_const_tuple(node->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900320 return make_const(node, newval, arena);
321}
322
323static int
Pablo Galindod112c602020-03-18 23:02:09 +0000324fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900325{
326 PyObject *newval;
327 expr_ty arg, idx;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900328
329 arg = node->v.Subscript.value;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200330 idx = node->v.Subscript.slice;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900331 if (node->v.Subscript.ctx != Load ||
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300332 arg->kind != Constant_kind ||
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200333 idx->kind != Constant_kind)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900334 {
335 return 1;
336 }
337
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300338 newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900339 return make_const(node, newval, arena);
340}
341
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200342/* Change literal list or set of constants into constant
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200343 tuple or frozenset respectively. Change literal list of
344 non-constants into tuple.
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200345 Used for right operand of "in" and "not in" tests and for iterable
346 in "for" loop and comprehensions.
347*/
348static int
Pablo Galindod112c602020-03-18 23:02:09 +0000349fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200350{
351 PyObject *newval;
352 if (arg->kind == List_kind) {
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200353 /* First change a list into tuple. */
Pablo Galindoa5634c42020-09-16 19:42:00 +0100354 asdl_expr_seq *elts = arg->v.List.elts;
Serhiy Storchaka3f7e9aa2018-03-11 10:54:47 +0200355 Py_ssize_t n = asdl_seq_LEN(elts);
356 for (Py_ssize_t i = 0; i < n; i++) {
357 expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
358 if (e->kind == Starred_kind) {
359 return 1;
360 }
361 }
362 expr_context_ty ctx = arg->v.List.ctx;
363 arg->kind = Tuple_kind;
364 arg->v.Tuple.elts = elts;
365 arg->v.Tuple.ctx = ctx;
366 /* Try to create a constant tuple. */
367 newval = make_const_tuple(elts);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200368 }
369 else if (arg->kind == Set_kind) {
370 newval = make_const_tuple(arg->v.Set.elts);
371 if (newval) {
372 Py_SETREF(newval, PyFrozenSet_New(newval));
373 }
374 }
375 else {
376 return 1;
377 }
378 return make_const(arg, newval, arena);
379}
380
INADA Naoki7ea143a2017-12-14 16:47:20 +0900381static int
Pablo Galindod112c602020-03-18 23:02:09 +0000382fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900383{
384 asdl_int_seq *ops;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100385 asdl_expr_seq *args;
Victor Stinner05d68a82018-01-18 11:15:25 +0100386 Py_ssize_t i;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900387
388 ops = node->v.Compare.ops;
389 args = node->v.Compare.comparators;
390 /* TODO: optimize cases with literal arguments. */
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200391 /* Change literal list or set in 'in' or 'not in' into
392 tuple or frozenset respectively. */
393 i = asdl_seq_LEN(ops) - 1;
394 int op = asdl_seq_GET(ops, i);
395 if (op == In || op == NotIn) {
Pablo Galindod112c602020-03-18 23:02:09 +0000396 if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200397 return 0;
398 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900399 }
400 return 1;
401}
402
Pablo Galindod112c602020-03-18 23:02:09 +0000403static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
404static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
405static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
406static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
407static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
408static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100409static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Pablo Galindod112c602020-03-18 23:02:09 +0000410static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
411static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
Brandt Bucher145bf262021-02-26 14:51:55 -0800412static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
413static int astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
414
INADA Naoki7ea143a2017-12-14 16:47:20 +0900415#define CALL(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000416 if (!FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900417 return 0;
418
419#define CALL_OPT(FUNC, TYPE, ARG) \
Pablo Galindod112c602020-03-18 23:02:09 +0000420 if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900421 return 0;
422
423#define CALL_SEQ(FUNC, TYPE, ARG) { \
424 int i; \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100425 asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900426 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
Pablo Galindoa5634c42020-09-16 19:42:00 +0100427 TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000428 if (elt != NULL && !FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900429 return 0; \
430 } \
431}
432
433#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
434 int i; \
435 asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
436 for (i = 0; i < asdl_seq_LEN(seq); i++) { \
437 TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
Pablo Galindod112c602020-03-18 23:02:09 +0000438 if (!FUNC(elt, ctx_, state)) \
INADA Naoki7ea143a2017-12-14 16:47:20 +0900439 return 0; \
440 } \
441}
442
443static int
Pablo Galindoa5634c42020-09-16 19:42:00 +0100444astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300445{
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300446 int docstring = _PyAST_GetDocString(stmts) != NULL;
Pablo Galindoa5634c42020-09-16 19:42:00 +0100447 CALL_SEQ(astfold_stmt, stmt, stmts);
Serhiy Storchaka143ce5c2018-05-30 10:56:16 +0300448 if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
449 stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100450 asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300451 if (!values) {
452 return 0;
453 }
454 asdl_seq_SET(values, 0, st->v.Expr.value);
Victor Stinnerd27f8d22021-04-07 21:34:22 +0200455 expr_ty expr = _PyAST_JoinedStr(values, st->lineno, st->col_offset,
456 st->end_lineno, st->end_col_offset,
457 ctx_);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300458 if (!expr) {
459 return 0;
460 }
461 st->v.Expr.value = expr;
462 }
463 return 1;
464}
465
466static int
Pablo Galindod112c602020-03-18 23:02:09 +0000467astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900468{
469 switch (node_->kind) {
470 case Module_kind:
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300471 CALL(astfold_body, asdl_seq, node_->v.Module.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900472 break;
473 case Interactive_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100474 CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900475 break;
476 case Expression_kind:
477 CALL(astfold_expr, expr_ty, node_->v.Expression.body);
478 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000479 // The following top level nodes don't participate in constant folding
480 case FunctionType_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900481 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000482 // No default case, so the compiler will emit a warning if new top level
483 // compilation nodes are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900484 }
485 return 1;
486}
487
488static int
Pablo Galindod112c602020-03-18 23:02:09 +0000489astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900490{
491 switch (node_->kind) {
492 case BoolOp_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100493 CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900494 break;
495 case BinOp_kind:
496 CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
497 CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
498 CALL(fold_binop, expr_ty, node_);
499 break;
500 case UnaryOp_kind:
501 CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
502 CALL(fold_unaryop, expr_ty, node_);
503 break;
504 case Lambda_kind:
505 CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
506 CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
507 break;
508 case IfExp_kind:
509 CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
510 CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
511 CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
512 break;
513 case Dict_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100514 CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);
515 CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900516 break;
517 case Set_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100518 CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900519 break;
520 case ListComp_kind:
521 CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100522 CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900523 break;
524 case SetComp_kind:
525 CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100526 CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900527 break;
528 case DictComp_kind:
529 CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
530 CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100531 CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900532 break;
533 case GeneratorExp_kind:
534 CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100535 CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900536 break;
537 case Await_kind:
538 CALL(astfold_expr, expr_ty, node_->v.Await.value);
539 break;
540 case Yield_kind:
541 CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
542 break;
543 case YieldFrom_kind:
544 CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
545 break;
546 case Compare_kind:
547 CALL(astfold_expr, expr_ty, node_->v.Compare.left);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100548 CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900549 CALL(fold_compare, expr_ty, node_);
550 break;
551 case Call_kind:
552 CALL(astfold_expr, expr_ty, node_->v.Call.func);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100553 CALL_SEQ(astfold_expr, expr, node_->v.Call.args);
554 CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900555 break;
556 case FormattedValue_kind:
557 CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
558 CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
559 break;
560 case JoinedStr_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100561 CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900562 break;
563 case Attribute_kind:
564 CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
565 break;
566 case Subscript_kind:
567 CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200568 CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900569 CALL(fold_subscr, expr_ty, node_);
570 break;
571 case Starred_kind:
572 CALL(astfold_expr, expr_ty, node_->v.Starred.value);
573 break;
Serhiy Storchaka13d52c22020-03-10 18:52:34 +0200574 case Slice_kind:
575 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
576 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
577 CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
578 break;
INADA Naoki7ea143a2017-12-14 16:47:20 +0900579 case List_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100580 CALL_SEQ(astfold_expr, expr, node_->v.List.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900581 break;
582 case Tuple_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100583 CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900584 CALL(fold_tuple, expr_ty, node_);
585 break;
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200586 case Name_kind:
Pablo Galindoc5fc1562020-04-22 23:29:27 +0100587 if (node_->v.Name.ctx == Load &&
588 _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
Pablo Galindod112c602020-03-18 23:02:09 +0000589 return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
Serhiy Storchaka3dfbaf52017-12-25 12:47:50 +0200590 }
591 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000592 case NamedExpr_kind:
593 CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900594 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000595 case Constant_kind:
596 // Already a constant, nothing further to do
597 break;
Brandt Bucher145bf262021-02-26 14:51:55 -0800598 case MatchAs_kind:
599 case MatchOr_kind:
600 // These can't occur outside of patterns.
601 Py_UNREACHABLE();
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000602 // No default case, so the compiler will emit a warning if new expression
603 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900604 }
605 return 1;
606}
607
608static int
Pablo Galindod112c602020-03-18 23:02:09 +0000609astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900610{
611 CALL(astfold_expr, expr_ty, node_->value);
612 return 1;
613}
614
615static int
Pablo Galindod112c602020-03-18 23:02:09 +0000616astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900617{
618 CALL(astfold_expr, expr_ty, node_->target);
619 CALL(astfold_expr, expr_ty, node_->iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100620 CALL_SEQ(astfold_expr, expr, node_->ifs);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200621
622 CALL(fold_iter, expr_ty, node_->iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900623 return 1;
624}
625
626static int
Pablo Galindod112c602020-03-18 23:02:09 +0000627astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900628{
Pablo Galindob0544ba2021-04-21 12:41:19 +0100629 CALL_SEQ(astfold_arg, arg, node_->posonlyargs);
630 CALL_SEQ(astfold_arg, arg, node_->args);
631 CALL_OPT(astfold_arg, arg_ty, node_->vararg);
632 CALL_SEQ(astfold_arg, arg, node_->kwonlyargs);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100633 CALL_SEQ(astfold_expr, expr, node_->kw_defaults);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100634 CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100635 CALL_SEQ(astfold_expr, expr, node_->defaults);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900636 return 1;
637}
638
639static int
Pablo Galindob0544ba2021-04-21 12:41:19 +0100640astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
641{
642 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
643 CALL_OPT(astfold_expr, expr_ty, node_->annotation);
644 }
645 return 1;
646}
647
648static int
Pablo Galindod112c602020-03-18 23:02:09 +0000649astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900650{
651 switch (node_->kind) {
652 case FunctionDef_kind:
653 CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300654 CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100655 CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100656 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
657 CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
658 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900659 break;
660 case AsyncFunctionDef_kind:
661 CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300662 CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100663 CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100664 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
665 CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
666 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900667 break;
668 case ClassDef_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100669 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
670 CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
Serhiy Storchaka73cbe7a2018-05-29 12:04:55 +0300671 CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100672 CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900673 break;
674 case Return_kind:
675 CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
676 break;
677 case Delete_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100678 CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900679 break;
680 case Assign_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100681 CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900682 CALL(astfold_expr, expr_ty, node_->v.Assign.value);
683 break;
684 case AugAssign_kind:
685 CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
686 CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
687 break;
688 case AnnAssign_kind:
689 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
Pablo Galindob0544ba2021-04-21 12:41:19 +0100690 if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
691 CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
692 }
INADA Naoki7ea143a2017-12-14 16:47:20 +0900693 CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
694 break;
695 case For_kind:
696 CALL(astfold_expr, expr_ty, node_->v.For.target);
697 CALL(astfold_expr, expr_ty, node_->v.For.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100698 CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
699 CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
Serhiy Storchaka15a87282017-12-14 20:24:31 +0200700
701 CALL(fold_iter, expr_ty, node_->v.For.iter);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900702 break;
703 case AsyncFor_kind:
704 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
705 CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100706 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
707 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900708 break;
709 case While_kind:
710 CALL(astfold_expr, expr_ty, node_->v.While.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100711 CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
712 CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900713 break;
714 case If_kind:
715 CALL(astfold_expr, expr_ty, node_->v.If.test);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100716 CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);
717 CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900718 break;
719 case With_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100720 CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);
721 CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900722 break;
723 case AsyncWith_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100724 CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);
725 CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900726 break;
727 case Raise_kind:
728 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
729 CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
730 break;
731 case Try_kind:
Pablo Galindoa5634c42020-09-16 19:42:00 +0100732 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
733 CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
734 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
735 CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900736 break;
737 case Assert_kind:
738 CALL(astfold_expr, expr_ty, node_->v.Assert.test);
739 CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
740 break;
741 case Expr_kind:
742 CALL(astfold_expr, expr_ty, node_->v.Expr.value);
743 break;
Brandt Bucher145bf262021-02-26 14:51:55 -0800744 case Match_kind:
745 CALL(astfold_expr, expr_ty, node_->v.Match.subject);
746 CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases);
747 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000748 // The following statements don't contain any subexpressions to be folded
749 case Import_kind:
750 case ImportFrom_kind:
751 case Global_kind:
752 case Nonlocal_kind:
753 case Pass_kind:
754 case Break_kind:
755 case Continue_kind:
INADA Naoki7ea143a2017-12-14 16:47:20 +0900756 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000757 // No default case, so the compiler will emit a warning if new statement
758 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900759 }
760 return 1;
761}
762
763static int
Pablo Galindod112c602020-03-18 23:02:09 +0000764astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900765{
766 switch (node_->kind) {
767 case ExceptHandler_kind:
768 CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
Pablo Galindoa5634c42020-09-16 19:42:00 +0100769 CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900770 break;
Nick Coghlan8805a4d2020-11-07 22:35:17 +1000771 // No default case, so the compiler will emit a warning if new handler
772 // kinds are added without being handled here
INADA Naoki7ea143a2017-12-14 16:47:20 +0900773 }
774 return 1;
775}
776
777static int
Pablo Galindod112c602020-03-18 23:02:09 +0000778astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900779{
780 CALL(astfold_expr, expr_ty, node_->context_expr);
781 CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
782 return 1;
783}
784
Brandt Bucher145bf262021-02-26 14:51:55 -0800785static int
786astfold_pattern_negative(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
787{
788 assert(node_->kind == UnaryOp_kind);
789 assert(node_->v.UnaryOp.op == USub);
790 assert(node_->v.UnaryOp.operand->kind == Constant_kind);
791 PyObject *value = node_->v.UnaryOp.operand->v.Constant.value;
792 assert(PyComplex_CheckExact(value) ||
793 PyFloat_CheckExact(value) ||
794 PyLong_CheckExact(value));
795 PyObject *negated = PyNumber_Negative(value);
796 if (negated == NULL) {
797 return 0;
798 }
799 assert(PyComplex_CheckExact(negated) ||
800 PyFloat_CheckExact(negated) ||
801 PyLong_CheckExact(negated));
802 return make_const(node_, negated, ctx_);
803}
804
805static int
806astfold_pattern_complex(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
807{
808 expr_ty left = node_->v.BinOp.left;
809 expr_ty right = node_->v.BinOp.right;
810 if (left->kind == UnaryOp_kind) {
811 CALL(astfold_pattern_negative, expr_ty, left);
812 }
813 assert(left->kind = Constant_kind);
814 assert(right->kind = Constant_kind);
815 // LHS must be real, RHS must be imaginary:
816 if (!(PyFloat_CheckExact(left->v.Constant.value) ||
817 PyLong_CheckExact(left->v.Constant.value)) ||
818 !PyComplex_CheckExact(right->v.Constant.value))
819 {
820 // Not actually valid, but it's the compiler's job to complain:
821 return 1;
822 }
823 PyObject *new;
824 if (node_->v.BinOp.op == Add) {
825 new = PyNumber_Add(left->v.Constant.value, right->v.Constant.value);
826 }
827 else {
828 assert(node_->v.BinOp.op == Sub);
829 new = PyNumber_Subtract(left->v.Constant.value, right->v.Constant.value);
830 }
831 if (new == NULL) {
832 return 0;
833 }
834 assert(PyComplex_CheckExact(new));
835 return make_const(node_, new, ctx_);
836}
837
838static int
839astfold_pattern_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
840{
841 CALL(astfold_pattern, expr_ty, node_->value);
842 return 1;
843}
844
845static int
846astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
847{
848 // Don't blindly optimize the pattern as an expr; it plays by its own rules!
849 // Currently, this is only used to form complex/negative numeric constants.
850 switch (node_->kind) {
851 case Attribute_kind:
852 break;
853 case BinOp_kind:
854 CALL(astfold_pattern_complex, expr_ty, node_);
855 break;
856 case Call_kind:
857 CALL_SEQ(astfold_pattern, expr, node_->v.Call.args);
858 CALL_SEQ(astfold_pattern_keyword, keyword, node_->v.Call.keywords);
859 break;
860 case Constant_kind:
861 break;
862 case Dict_kind:
863 CALL_SEQ(astfold_pattern, expr, node_->v.Dict.keys);
864 CALL_SEQ(astfold_pattern, expr, node_->v.Dict.values);
865 break;
866 // Not actually valid, but it's the compiler's job to complain:
867 case JoinedStr_kind:
868 break;
869 case List_kind:
870 CALL_SEQ(astfold_pattern, expr, node_->v.List.elts);
871 break;
872 case MatchAs_kind:
873 CALL(astfold_pattern, expr_ty, node_->v.MatchAs.pattern);
874 break;
875 case MatchOr_kind:
876 CALL_SEQ(astfold_pattern, expr, node_->v.MatchOr.patterns);
877 break;
878 case Name_kind:
879 break;
880 case Starred_kind:
881 CALL(astfold_pattern, expr_ty, node_->v.Starred.value);
882 break;
883 case Tuple_kind:
884 CALL_SEQ(astfold_pattern, expr, node_->v.Tuple.elts);
885 break;
886 case UnaryOp_kind:
887 CALL(astfold_pattern_negative, expr_ty, node_);
888 break;
889 default:
890 Py_UNREACHABLE();
891 }
892 return 1;
893}
894
895static int
896astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
897{
898 CALL(astfold_pattern, expr_ty, node_->pattern);
899 CALL_OPT(astfold_expr, expr_ty, node_->guard);
900 CALL_SEQ(astfold_stmt, stmt, node_->body);
901 return 1;
902}
903
INADA Naoki7ea143a2017-12-14 16:47:20 +0900904#undef CALL
905#undef CALL_OPT
906#undef CALL_SEQ
907#undef CALL_INT_SEQ
908
909int
Pablo Galindod112c602020-03-18 23:02:09 +0000910_PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
INADA Naoki7ea143a2017-12-14 16:47:20 +0900911{
Pablo Galindod112c602020-03-18 23:02:09 +0000912 int ret = astfold_mod(mod, arena, state);
INADA Naoki7ea143a2017-12-14 16:47:20 +0900913 assert(ret || PyErr_Occurred());
914 return ret;
915}