Branch data Line data Source code
1 : : /* AST Optimizer */
2 : : #include "Python.h"
3 : : #include "pycore_ast.h" // _PyAST_GetDocString()
4 : : #include "pycore_compile.h" // _PyASTOptimizeState
5 : : #include "pycore_pystate.h" // _PyThreadState_GET()
6 : : #include "pycore_format.h" // F_LJUST
7 : :
8 : :
9 : : static int
10 : 4118 : make_const(expr_ty node, PyObject *val, PyArena *arena)
11 : : {
12 : : // Even if no new value was calculated, make_const may still
13 : : // need to clear an error (e.g. for division by zero)
14 [ + + ]: 4118 : if (val == NULL) {
15 [ - + ]: 2156 : if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
16 : 0 : return 0;
17 : : }
18 : 2156 : PyErr_Clear();
19 : 2156 : return 1;
20 : : }
21 [ - + ]: 1962 : if (_PyArena_AddPyObject(arena, val) < 0) {
22 : 0 : Py_DECREF(val);
23 : 0 : return 0;
24 : : }
25 : 1962 : node->kind = Constant_kind;
26 : 1962 : node->v.Constant.kind = NULL;
27 : 1962 : node->v.Constant.value = val;
28 : 1962 : return 1;
29 : : }
30 : :
31 : : #define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
32 : :
33 : : static int
34 : 422 : has_starred(asdl_expr_seq *elts)
35 : : {
36 [ + - ]: 422 : Py_ssize_t n = asdl_seq_LEN(elts);
37 [ + + ]: 1399 : for (Py_ssize_t i = 0; i < n; i++) {
38 : 978 : expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
39 [ + + ]: 978 : if (e->kind == Starred_kind) {
40 : 1 : return 1;
41 : : }
42 : : }
43 : 421 : return 0;
44 : : }
45 : :
46 : :
47 : : static PyObject*
48 : 0 : unary_not(PyObject *v)
49 : : {
50 : 0 : int r = PyObject_IsTrue(v);
51 [ # # ]: 0 : if (r < 0)
52 : 0 : return NULL;
53 : 0 : return PyBool_FromLong(!r);
54 : : }
55 : :
56 : : static int
57 : 2670 : fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
58 : : {
59 : 2670 : expr_ty arg = node->v.UnaryOp.operand;
60 : :
61 [ + + ]: 2670 : if (arg->kind != Constant_kind) {
62 : : /* Fold not into comparison */
63 [ + + + + ]: 1805 : if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
64 [ + - + + ]: 56 : asdl_seq_LEN(arg->v.Compare.ops) == 1) {
65 : : /* Eq and NotEq are often implemented in terms of one another, so
66 : : folding not (self == other) into self != other breaks implementation
67 : : of !=. Detecting such cases doesn't seem worthwhile.
68 : : Python uses </> for 'is subset'/'is superset' operations on sets.
69 : : They don't satisfy not folding laws. */
70 : 34 : cmpop_ty op = asdl_seq_GET(arg->v.Compare.ops, 0);
71 [ - - + - : 34 : switch (op) {
+ - ]
72 : 0 : case Is:
73 : 0 : op = IsNot;
74 : 0 : break;
75 : 0 : case IsNot:
76 : 0 : op = Is;
77 : 0 : break;
78 : 17 : case In:
79 : 17 : op = NotIn;
80 : 17 : break;
81 : 0 : case NotIn:
82 : 0 : op = In;
83 : 0 : break;
84 : : // The remaining comparison operators can't be safely inverted
85 : 17 : case Eq:
86 : : case NotEq:
87 : : case Lt:
88 : : case LtE:
89 : : case Gt:
90 : : case GtE:
91 : 17 : op = 0; // The AST enums leave "0" free as an "unused" marker
92 : 17 : break;
93 : : // No default case, so the compiler will emit a warning if new
94 : : // comparison operators are added without being handled here
95 : : }
96 [ + + ]: 34 : if (op) {
97 : 17 : asdl_seq_SET(arg->v.Compare.ops, 0, op);
98 : 17 : COPY_NODE(node, arg);
99 : 17 : return 1;
100 : : }
101 : : }
102 : 1788 : return 1;
103 : : }
104 : :
105 : : typedef PyObject *(*unary_op)(PyObject*);
106 : : static const unary_op ops[] = {
107 : : [Invert] = PyNumber_Invert,
108 : : [Not] = unary_not,
109 : : [UAdd] = PyNumber_Positive,
110 : : [USub] = PyNumber_Negative,
111 : : };
112 : 865 : PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
113 : 865 : return make_const(node, newval, arena);
114 : : }
115 : :
116 : : /* Check whether a collection doesn't containing too much items (including
117 : : subcollections). This protects from creating a constant that needs
118 : : too much time for calculating a hash.
119 : : "limit" is the maximal number of items.
120 : : Returns the negative number if the total number of items exceeds the
121 : : limit. Otherwise returns the limit minus the total number of items.
122 : : */
123 : :
124 : : static Py_ssize_t
125 : 0 : check_complexity(PyObject *obj, Py_ssize_t limit)
126 : : {
127 [ # # ]: 0 : if (PyTuple_Check(obj)) {
128 : : Py_ssize_t i;
129 : 0 : limit -= PyTuple_GET_SIZE(obj);
130 [ # # # # ]: 0 : for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
131 : 0 : limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
132 : : }
133 : 0 : return limit;
134 : : }
135 [ # # # # ]: 0 : else if (PyFrozenSet_Check(obj)) {
136 : 0 : Py_ssize_t i = 0;
137 : : PyObject *item;
138 : : Py_hash_t hash;
139 : 0 : limit -= PySet_GET_SIZE(obj);
140 [ # # # # ]: 0 : while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
141 : 0 : limit = check_complexity(item, limit);
142 : : }
143 : : }
144 : 0 : return limit;
145 : : }
146 : :
147 : : #define MAX_INT_SIZE 128 /* bits */
148 : : #define MAX_COLLECTION_SIZE 256 /* items */
149 : : #define MAX_STR_SIZE 4096 /* characters */
150 : : #define MAX_TOTAL_ITEMS 1024 /* including nested collections */
151 : :
152 : : static PyObject *
153 : 61 : safe_multiply(PyObject *v, PyObject *w)
154 : : {
155 [ + + + + : 92 : if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
+ - + - ]
156 : 31 : size_t vbits = _PyLong_NumBits(v);
157 : 31 : size_t wbits = _PyLong_NumBits(w);
158 [ + - - + ]: 31 : if (vbits == (size_t)-1 || wbits == (size_t)-1) {
159 : 0 : return NULL;
160 : : }
161 [ - + ]: 31 : if (vbits + wbits > MAX_INT_SIZE) {
162 : 0 : return NULL;
163 : : }
164 : : }
165 [ + + + - : 30 : else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
+ - - + ]
166 [ # # ]: 0 : Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
167 : 0 : PySet_GET_SIZE(w);
168 [ # # ]: 0 : if (size) {
169 : 0 : long n = PyLong_AsLong(v);
170 [ # # # # ]: 0 : if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
171 : 0 : return NULL;
172 : : }
173 [ # # # # ]: 0 : if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
174 : 0 : return NULL;
175 : : }
176 : : }
177 : : }
178 [ + + + + : 40 : else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
+ + ]
179 [ + + ]: 11 : Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
180 : 3 : PyBytes_GET_SIZE(w);
181 [ + - ]: 11 : if (size) {
182 : 11 : long n = PyLong_AsLong(v);
183 [ + - + + ]: 11 : if (n < 0 || n > MAX_STR_SIZE / size) {
184 : 1 : return NULL;
185 : : }
186 : : }
187 : : }
188 [ + + + - ]: 30 : else if (PyLong_Check(w) &&
189 [ + - + - : 33 : (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
+ + ]
190 [ + - ]: 14 : PyUnicode_Check(v) || PyBytes_Check(v)))
191 : : {
192 : 11 : return safe_multiply(w, v);
193 : : }
194 : :
195 : 49 : return PyNumber_Multiply(v, w);
196 : : }
197 : :
198 : : static PyObject *
199 : 96 : safe_power(PyObject *v, PyObject *w)
200 : : {
201 [ + + + - : 96 : if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
+ + + + ]
202 : 73 : size_t vbits = _PyLong_NumBits(v);
203 : 73 : size_t wbits = PyLong_AsSize_t(w);
204 [ + - - + ]: 73 : if (vbits == (size_t)-1 || wbits == (size_t)-1) {
205 : 0 : return NULL;
206 : : }
207 [ + + ]: 73 : if (vbits > MAX_INT_SIZE / wbits) {
208 : 30 : return NULL;
209 : : }
210 : : }
211 : :
212 : 66 : return PyNumber_Power(v, w, Py_None);
213 : : }
214 : :
215 : : static PyObject *
216 : 20 : safe_lshift(PyObject *v, PyObject *w)
217 : : {
218 [ + - + - : 20 : if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
+ - + + ]
219 : 18 : size_t vbits = _PyLong_NumBits(v);
220 : 18 : size_t wbits = PyLong_AsSize_t(w);
221 [ + - - + ]: 18 : if (vbits == (size_t)-1 || wbits == (size_t)-1) {
222 : 0 : return NULL;
223 : : }
224 [ + + - + ]: 18 : if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
225 : 2 : return NULL;
226 : : }
227 : : }
228 : :
229 : 18 : return PyNumber_Lshift(v, w);
230 : : }
231 : :
232 : : static PyObject *
233 : 0 : safe_mod(PyObject *v, PyObject *w)
234 : : {
235 [ # # # # ]: 0 : if (PyUnicode_Check(v) || PyBytes_Check(v)) {
236 : 0 : return NULL;
237 : : }
238 : :
239 : 0 : return PyNumber_Remainder(v, w);
240 : : }
241 : :
242 : :
243 : : static expr_ty
244 : 1034 : parse_literal(PyObject *fmt, Py_ssize_t *ppos, PyArena *arena)
245 : : {
246 : 1034 : const void *data = PyUnicode_DATA(fmt);
247 : 1034 : int kind = PyUnicode_KIND(fmt);
248 : 1034 : Py_ssize_t size = PyUnicode_GET_LENGTH(fmt);
249 : : Py_ssize_t start, pos;
250 : 1034 : int has_percents = 0;
251 : 1034 : start = pos = *ppos;
252 [ + + ]: 8020 : while (pos < size) {
253 [ + + ]: 7726 : if (PyUnicode_READ(kind, data, pos) != '%') {
254 : 6985 : pos++;
255 : : }
256 [ + - + + ]: 741 : else if (pos+1 < size && PyUnicode_READ(kind, data, pos+1) == '%') {
257 : 1 : has_percents = 1;
258 : 1 : pos += 2;
259 : : }
260 : : else {
261 : : break;
262 : : }
263 : : }
264 : 1034 : *ppos = pos;
265 [ + + ]: 1034 : if (pos == start) {
266 : 359 : return NULL;
267 : : }
268 : 675 : PyObject *str = PyUnicode_Substring(fmt, start, pos);
269 : : /* str = str.replace('%%', '%') */
270 [ + - + + ]: 675 : if (str && has_percents) {
271 : : _Py_DECLARE_STR(percent, "%");
272 : : _Py_DECLARE_STR(dbl_percent, "%%");
273 : 1 : Py_SETREF(str, PyUnicode_Replace(str, &_Py_STR(dbl_percent),
274 : : &_Py_STR(percent), -1));
275 : : }
276 [ - + ]: 675 : if (!str) {
277 : 0 : return NULL;
278 : : }
279 : :
280 [ - + ]: 675 : if (_PyArena_AddPyObject(arena, str) < 0) {
281 : 0 : Py_DECREF(str);
282 : 0 : return NULL;
283 : : }
284 : 675 : return _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena);
285 : : }
286 : :
287 : : #define MAXDIGITS 3
288 : :
289 : : static int
290 : 740 : simple_format_arg_parse(PyObject *fmt, Py_ssize_t *ppos,
291 : : int *spec, int *flags, int *width, int *prec)
292 : : {
293 : 740 : Py_ssize_t pos = *ppos, len = PyUnicode_GET_LENGTH(fmt);
294 : : Py_UCS4 ch;
295 : :
296 : : #define NEXTC do { \
297 : : if (pos >= len) { \
298 : : return 0; \
299 : : } \
300 : : ch = PyUnicode_READ_CHAR(fmt, pos); \
301 : : pos++; \
302 : : } while (0)
303 : :
304 : 740 : *flags = 0;
305 : : while (1) {
306 [ - + ]: 766 : NEXTC;
307 [ + - - + : 766 : switch (ch) {
+ - + ]
308 : 6 : case '-': *flags |= F_LJUST; continue;
309 : 0 : case '+': *flags |= F_SIGN; continue;
310 : 0 : case ' ': *flags |= F_BLANK; continue;
311 : 13 : case '#': *flags |= F_ALT; continue;
312 : 7 : case '0': *flags |= F_ZERO; continue;
313 : 0 : case 'z': *flags |= F_NO_NEG_0; continue;
314 : : }
315 : 740 : break;
316 : : }
317 [ + + + + ]: 740 : if ('0' <= ch && ch <= '9') {
318 : 15 : *width = 0;
319 : 15 : int digits = 0;
320 [ + - + + ]: 34 : while ('0' <= ch && ch <= '9') {
321 : 19 : *width = *width * 10 + (ch - '0');
322 [ - + ]: 19 : NEXTC;
323 [ - + ]: 19 : if (++digits >= MAXDIGITS) {
324 : 0 : return 0;
325 : : }
326 : : }
327 : : }
328 : :
329 [ - + ]: 740 : if (ch == '.') {
330 [ # # ]: 0 : NEXTC;
331 : 0 : *prec = 0;
332 [ # # # # ]: 0 : if ('0' <= ch && ch <= '9') {
333 : 0 : int digits = 0;
334 [ # # # # ]: 0 : while ('0' <= ch && ch <= '9') {
335 : 0 : *prec = *prec * 10 + (ch - '0');
336 [ # # ]: 0 : NEXTC;
337 [ # # ]: 0 : if (++digits >= MAXDIGITS) {
338 : 0 : return 0;
339 : : }
340 : : }
341 : : }
342 : : }
343 : 740 : *spec = ch;
344 : 740 : *ppos = pos;
345 : 740 : return 1;
346 : :
347 : : #undef NEXTC
348 : : }
349 : :
350 : : static expr_ty
351 : 740 : parse_format(PyObject *fmt, Py_ssize_t *ppos, expr_ty arg, PyArena *arena)
352 : : {
353 : 740 : int spec, flags, width = -1, prec = -1;
354 [ - + ]: 740 : if (!simple_format_arg_parse(fmt, ppos, &spec, &flags, &width, &prec)) {
355 : : // Unsupported format.
356 : 0 : return NULL;
357 : : }
358 [ + + + + : 740 : if (spec == 's' || spec == 'r' || spec == 'a') {
- + ]
359 : 651 : char buf[1 + MAXDIGITS + 1 + MAXDIGITS + 1], *p = buf;
360 [ + + - + ]: 651 : if (!(flags & F_LJUST) && width > 0) {
361 : 0 : *p++ = '>';
362 : : }
363 [ + + ]: 651 : if (width >= 0) {
364 : 4 : p += snprintf(p, MAXDIGITS + 1, "%d", width);
365 : : }
366 [ - + ]: 651 : if (prec >= 0) {
367 : 0 : p += snprintf(p, MAXDIGITS + 2, ".%d", prec);
368 : : }
369 : 651 : expr_ty format_spec = NULL;
370 [ + + ]: 651 : if (p != buf) {
371 : 4 : PyObject *str = PyUnicode_FromString(buf);
372 [ - + ]: 4 : if (str == NULL) {
373 : 0 : return NULL;
374 : : }
375 [ - + ]: 4 : if (_PyArena_AddPyObject(arena, str) < 0) {
376 : 0 : Py_DECREF(str);
377 : 0 : return NULL;
378 : : }
379 : 4 : format_spec = _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena);
380 [ - + ]: 4 : if (format_spec == NULL) {
381 : 0 : return NULL;
382 : : }
383 : : }
384 : 651 : return _PyAST_FormattedValue(arg, spec, format_spec,
385 : : arg->lineno, arg->col_offset,
386 : : arg->end_lineno, arg->end_col_offset,
387 : : arena);
388 : : }
389 : : // Unsupported format.
390 : 89 : return NULL;
391 : : }
392 : :
393 : : static int
394 : 383 : optimize_format(expr_ty node, PyObject *fmt, asdl_expr_seq *elts, PyArena *arena)
395 : : {
396 : 383 : Py_ssize_t pos = 0;
397 : 383 : Py_ssize_t cnt = 0;
398 [ + - ]: 383 : asdl_expr_seq *seq = _Py_asdl_expr_seq_new(asdl_seq_LEN(elts) * 2 + 1, arena);
399 [ - + ]: 383 : if (!seq) {
400 : 0 : return 0;
401 : : }
402 : 383 : seq->size = 0;
403 : :
404 : 651 : while (1) {
405 : 1034 : expr_ty lit = parse_literal(fmt, &pos, arena);
406 [ + + ]: 1034 : if (lit) {
407 : 675 : asdl_seq_SET(seq, seq->size++, lit);
408 : : }
409 [ - + ]: 359 : else if (PyErr_Occurred()) {
410 : 0 : return 0;
411 : : }
412 : :
413 [ + + ]: 1034 : if (pos >= PyUnicode_GET_LENGTH(fmt)) {
414 : 294 : break;
415 : : }
416 [ + - - + ]: 740 : if (cnt >= asdl_seq_LEN(elts)) {
417 : : // More format units than items.
418 : 0 : return 1;
419 : : }
420 : : assert(PyUnicode_READ_CHAR(fmt, pos) == '%');
421 : 740 : pos++;
422 : 740 : expr_ty expr = parse_format(fmt, &pos, asdl_seq_GET(elts, cnt), arena);
423 : 740 : cnt++;
424 [ + + ]: 740 : if (!expr) {
425 : 89 : return !PyErr_Occurred();
426 : : }
427 : 651 : asdl_seq_SET(seq, seq->size++, expr);
428 : : }
429 [ + - - + ]: 294 : if (cnt < asdl_seq_LEN(elts)) {
430 : : // More items than format units.
431 : 0 : return 1;
432 : : }
433 : 294 : expr_ty res = _PyAST_JoinedStr(seq,
434 : : node->lineno, node->col_offset,
435 : : node->end_lineno, node->end_col_offset,
436 : : arena);
437 [ - + ]: 294 : if (!res) {
438 : 0 : return 0;
439 : : }
440 : 294 : COPY_NODE(node, res);
441 : : // PySys_FormatStderr("format = %R\n", fmt);
442 : 294 : return 1;
443 : : }
444 : :
445 : : static int
446 : 3955 : fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
447 : : {
448 : : expr_ty lhs, rhs;
449 : 3955 : lhs = node->v.BinOp.left;
450 : 3955 : rhs = node->v.BinOp.right;
451 [ + + ]: 3955 : if (lhs->kind != Constant_kind) {
452 : 2661 : return 1;
453 : : }
454 : 1294 : PyObject *lv = lhs->v.Constant.value;
455 : :
456 [ + + ]: 1294 : if (node->v.BinOp.op == Mod &&
457 [ + + + - ]: 1117 : rhs->kind == Tuple_kind &&
458 [ + + ]: 768 : PyUnicode_Check(lv) &&
459 : 384 : !has_starred(rhs->v.Tuple.elts))
460 : : {
461 : 383 : return optimize_format(node, lv, rhs->v.Tuple.elts, arena);
462 : : }
463 : :
464 [ + + ]: 911 : if (rhs->kind != Constant_kind) {
465 : 718 : return 1;
466 : : }
467 : :
468 : 193 : PyObject *rv = rhs->v.Constant.value;
469 : 193 : PyObject *newval = NULL;
470 : :
471 [ + + + + : 193 : switch (node->v.BinOp.op) {
- - + + -
- - - -
- ]
472 : 15 : case Add:
473 : 15 : newval = PyNumber_Add(lv, rv);
474 : 15 : break;
475 : 10 : case Sub:
476 : 10 : newval = PyNumber_Subtract(lv, rv);
477 : 10 : break;
478 : 50 : case Mult:
479 : 50 : newval = safe_multiply(lv, rv);
480 : 50 : break;
481 : 2 : case Div:
482 : 2 : newval = PyNumber_TrueDivide(lv, rv);
483 : 2 : break;
484 : 0 : case FloorDiv:
485 : 0 : newval = PyNumber_FloorDivide(lv, rv);
486 : 0 : break;
487 : 0 : case Mod:
488 : 0 : newval = safe_mod(lv, rv);
489 : 0 : break;
490 : 96 : case Pow:
491 : 96 : newval = safe_power(lv, rv);
492 : 96 : break;
493 : 20 : case LShift:
494 : 20 : newval = safe_lshift(lv, rv);
495 : 20 : break;
496 : 0 : case RShift:
497 : 0 : newval = PyNumber_Rshift(lv, rv);
498 : 0 : break;
499 : 0 : case BitOr:
500 : 0 : newval = PyNumber_Or(lv, rv);
501 : 0 : break;
502 : 0 : case BitXor:
503 : 0 : newval = PyNumber_Xor(lv, rv);
504 : 0 : break;
505 : 0 : case BitAnd:
506 : 0 : newval = PyNumber_And(lv, rv);
507 : 0 : break;
508 : : // No builtin constants implement the following operators
509 : 0 : case MatMult:
510 : 0 : return 1;
511 : : // No default case, so the compiler will emit a warning if new binary
512 : : // operators are added without being handled here
513 : : }
514 : :
515 : 193 : return make_const(node, newval, arena);
516 : : }
517 : :
518 : : static PyObject*
519 : 3054 : make_const_tuple(asdl_expr_seq *elts)
520 : : {
521 [ + + + + ]: 5258 : for (int i = 0; i < asdl_seq_LEN(elts); i++) {
522 : 4325 : expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
523 [ + + ]: 4325 : if (e->kind != Constant_kind) {
524 : 2121 : return NULL;
525 : : }
526 : : }
527 : :
528 [ + + ]: 933 : PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
529 [ - + ]: 933 : if (newval == NULL) {
530 : 0 : return NULL;
531 : : }
532 : :
533 [ + + + + ]: 3006 : for (int i = 0; i < asdl_seq_LEN(elts); i++) {
534 : 2073 : expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
535 : 2073 : PyObject *v = e->v.Constant.value;
536 : 2073 : PyTuple_SET_ITEM(newval, i, Py_NewRef(v));
537 : : }
538 : 933 : return newval;
539 : : }
540 : :
541 : : static int
542 : 4110 : fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
543 : : {
544 : : PyObject *newval;
545 : :
546 [ + + ]: 4110 : if (node->v.Tuple.ctx != Load)
547 : 1134 : return 1;
548 : :
549 : 2976 : newval = make_const_tuple(node->v.Tuple.elts);
550 : 2976 : return make_const(node, newval, arena);
551 : : }
552 : :
553 : : static int
554 : 3489 : fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
555 : : {
556 : : PyObject *newval;
557 : : expr_ty arg, idx;
558 : :
559 : 3489 : arg = node->v.Subscript.value;
560 : 3489 : idx = node->v.Subscript.slice;
561 [ + + ]: 3489 : if (node->v.Subscript.ctx != Load ||
562 [ + + ]: 2552 : arg->kind != Constant_kind ||
563 [ - + ]: 5 : idx->kind != Constant_kind)
564 : : {
565 : 3484 : return 1;
566 : : }
567 : :
568 : 5 : newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
569 : 5 : return make_const(node, newval, arena);
570 : : }
571 : :
572 : : /* Change literal list or set of constants into constant
573 : : tuple or frozenset respectively. Change literal list of
574 : : non-constants into tuple.
575 : : Used for right operand of "in" and "not in" tests and for iterable
576 : : in "for" loop and comprehensions.
577 : : */
578 : : static int
579 : 2667 : fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
580 : : {
581 : : PyObject *newval;
582 [ + + ]: 2667 : if (arg->kind == List_kind) {
583 : : /* First change a list into tuple. */
584 : 38 : asdl_expr_seq *elts = arg->v.List.elts;
585 [ - + ]: 38 : if (has_starred(elts)) {
586 : 0 : return 1;
587 : : }
588 : 38 : expr_context_ty ctx = arg->v.List.ctx;
589 : 38 : arg->kind = Tuple_kind;
590 : 38 : arg->v.Tuple.elts = elts;
591 : 38 : arg->v.Tuple.ctx = ctx;
592 : : /* Try to create a constant tuple. */
593 : 38 : newval = make_const_tuple(elts);
594 : : }
595 [ + + ]: 2629 : else if (arg->kind == Set_kind) {
596 : 40 : newval = make_const_tuple(arg->v.Set.elts);
597 [ + + ]: 40 : if (newval) {
598 : 32 : Py_SETREF(newval, PyFrozenSet_New(newval));
599 : : }
600 : : }
601 : : else {
602 : 2589 : return 1;
603 : : }
604 : 78 : return make_const(arg, newval, arena);
605 : : }
606 : :
607 : : static int
608 : 6203 : fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
609 : : {
610 : : asdl_int_seq *ops;
611 : : asdl_expr_seq *args;
612 : : Py_ssize_t i;
613 : :
614 : 6203 : ops = node->v.Compare.ops;
615 : 6203 : args = node->v.Compare.comparators;
616 : : /* Change literal list or set in 'in' or 'not in' into
617 : : tuple or frozenset respectively. */
618 [ + - ]: 6203 : i = asdl_seq_LEN(ops) - 1;
619 : 6203 : int op = asdl_seq_GET(ops, i);
620 [ + + + + ]: 6203 : if (op == In || op == NotIn) {
621 [ - + ]: 978 : if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
622 : 0 : return 0;
623 : : }
624 : : }
625 : 6203 : return 1;
626 : : }
627 : :
628 : : static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
629 : : static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
630 : : static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
631 : : static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
632 : : static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
633 : : static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
634 : : static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
635 : : static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
636 : : static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
637 : : static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
638 : : static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
639 : :
640 : : #define CALL(FUNC, TYPE, ARG) \
641 : : if (!FUNC((ARG), ctx_, state)) \
642 : : return 0;
643 : :
644 : : #define CALL_OPT(FUNC, TYPE, ARG) \
645 : : if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
646 : : return 0;
647 : :
648 : : #define CALL_SEQ(FUNC, TYPE, ARG) { \
649 : : int i; \
650 : : asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \
651 : : for (i = 0; i < asdl_seq_LEN(seq); i++) { \
652 : : TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \
653 : : if (elt != NULL && !FUNC(elt, ctx_, state)) \
654 : : return 0; \
655 : : } \
656 : : }
657 : :
658 : :
659 : : static int
660 : 7340 : astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
661 : : {
662 : 7340 : int docstring = _PyAST_GetDocString(stmts) != NULL;
663 [ + - - + : 40600 : CALL_SEQ(astfold_stmt, stmt, stmts);
+ + + + ]
664 [ + + - + ]: 7340 : if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
665 : 0 : stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
666 : 0 : asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);
667 [ # # ]: 0 : if (!values) {
668 : 0 : return 0;
669 : : }
670 : 0 : asdl_seq_SET(values, 0, st->v.Expr.value);
671 : 0 : expr_ty expr = _PyAST_JoinedStr(values, st->lineno, st->col_offset,
672 : : st->end_lineno, st->end_col_offset,
673 : : ctx_);
674 [ # # ]: 0 : if (!expr) {
675 : 0 : return 0;
676 : : }
677 : 0 : st->v.Expr.value = expr;
678 : : }
679 : 7340 : return 1;
680 : : }
681 : :
682 : : static int
683 : 319 : astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
684 : : {
685 [ + + + - : 319 : switch (node_->kind) {
- ]
686 : 206 : case Module_kind:
687 [ - + ]: 206 : CALL(astfold_body, asdl_seq, node_->v.Module.body);
688 : 206 : break;
689 : 56 : case Interactive_kind:
690 [ + - - + : 112 : CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);
+ - + + ]
691 : 56 : break;
692 : 57 : case Expression_kind:
693 [ - + ]: 57 : CALL(astfold_expr, expr_ty, node_->v.Expression.body);
694 : 57 : break;
695 : : // The following top level nodes don't participate in constant folding
696 : 0 : case FunctionType_kind:
697 : 0 : break;
698 : : // No default case, so the compiler will emit a warning if new top level
699 : : // compilation nodes are added without being handled here
700 : : }
701 : 319 : return 1;
702 : : }
703 : :
704 : : static int
705 : 223010 : astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
706 : : {
707 [ - + ]: 223010 : if (++state->recursion_depth > state->recursion_limit) {
708 : 0 : PyErr_SetString(PyExc_RecursionError,
709 : : "maximum recursion depth exceeded during compilation");
710 : 0 : return 0;
711 : : }
712 [ + + + + : 223010 : switch (node_->kind) {
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + - ]
713 : 1755 : case BoolOp_kind:
714 [ + - - + : 5525 : CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);
+ - + + ]
715 : 1755 : break;
716 : 3955 : case BinOp_kind:
717 [ - + ]: 3955 : CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
718 [ - + ]: 3955 : CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
719 [ - + ]: 3955 : CALL(fold_binop, expr_ty, node_);
720 : 3955 : break;
721 : 2670 : case UnaryOp_kind:
722 [ - + ]: 2670 : CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
723 [ - + ]: 2670 : CALL(fold_unaryop, expr_ty, node_);
724 : 2670 : break;
725 : 135 : case Lambda_kind:
726 [ - + ]: 135 : CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
727 [ - + ]: 135 : CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
728 : 135 : break;
729 : 233 : case IfExp_kind:
730 [ - + ]: 233 : CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
731 [ - + ]: 233 : CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
732 [ - + ]: 233 : CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
733 : 233 : break;
734 : 397 : case Dict_kind:
735 [ + + - + : 3297 : CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);
+ - + + ]
736 [ + - - + : 3297 : CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);
+ - + + ]
737 : 397 : break;
738 : 72 : case Set_kind:
739 [ + - - + : 278 : CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);
+ - + + ]
740 : 72 : break;
741 : 215 : case ListComp_kind:
742 [ - + ]: 215 : CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
743 [ + - - + : 439 : CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);
+ - + + ]
744 : 215 : break;
745 : 14 : case SetComp_kind:
746 [ - + ]: 14 : CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
747 [ + - - + : 28 : CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);
+ - + + ]
748 : 14 : break;
749 : 23 : case DictComp_kind:
750 [ - + ]: 23 : CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
751 [ - + ]: 23 : CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
752 [ + - - + : 49 : CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);
+ - + + ]
753 : 23 : break;
754 : 197 : case GeneratorExp_kind:
755 [ - + ]: 197 : CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
756 [ + - - + : 400 : CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);
+ - + + ]
757 : 197 : break;
758 : 128 : case Await_kind:
759 [ - + ]: 128 : CALL(astfold_expr, expr_ty, node_->v.Await.value);
760 : 128 : break;
761 : 252 : case Yield_kind:
762 [ + + - + ]: 252 : CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
763 : 252 : break;
764 : 44 : case YieldFrom_kind:
765 [ - + ]: 44 : CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
766 : 44 : break;
767 : 6203 : case Compare_kind:
768 [ - + ]: 6203 : CALL(astfold_expr, expr_ty, node_->v.Compare.left);
769 [ + - - + : 12456 : CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);
+ - + + ]
770 [ - + ]: 6203 : CALL(fold_compare, expr_ty, node_);
771 : 6203 : break;
772 : 26248 : case Call_kind:
773 [ - + ]: 26248 : CALL(astfold_expr, expr_ty, node_->v.Call.func);
774 [ + - - + : 59450 : CALL_SEQ(astfold_expr, expr, node_->v.Call.args);
+ + + + ]
775 [ + - - + : 28377 : CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);
+ + + + ]
776 : 26248 : break;
777 : 1234 : case FormattedValue_kind:
778 [ - + ]: 1234 : CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
779 [ + + - + ]: 1234 : CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
780 : 1234 : break;
781 : 892 : case JoinedStr_kind:
782 [ + - - + : 3569 : CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);
+ - + + ]
783 : 892 : break;
784 : 29606 : case Attribute_kind:
785 [ - + ]: 29606 : CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
786 : 29606 : break;
787 : 3489 : case Subscript_kind:
788 [ - + ]: 3489 : CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
789 [ - + ]: 3489 : CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
790 [ - + ]: 3489 : CALL(fold_subscr, expr_ty, node_);
791 : 3489 : break;
792 : 310 : case Starred_kind:
793 [ - + ]: 310 : CALL(astfold_expr, expr_ty, node_->v.Starred.value);
794 : 310 : break;
795 : 807 : case Slice_kind:
796 [ + + - + ]: 807 : CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
797 [ + + - + ]: 807 : CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
798 [ + + - + ]: 807 : CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
799 : 807 : break;
800 : 1067 : case List_kind:
801 [ + - - + : 4096 : CALL_SEQ(astfold_expr, expr, node_->v.List.elts);
+ + + + ]
802 : 1067 : break;
803 : 4110 : case Tuple_kind:
804 [ + - - + : 13771 : CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);
+ + + + ]
805 [ - + ]: 4110 : CALL(fold_tuple, expr_ty, node_);
806 : 4110 : break;
807 : 100923 : case Name_kind:
808 [ + + + + ]: 184588 : if (node_->v.Name.ctx == Load &&
809 : 83665 : _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
810 : 1 : state->recursion_depth--;
811 : 1 : return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
812 : : }
813 : 100922 : break;
814 : 23 : case NamedExpr_kind:
815 [ - + ]: 23 : CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value);
816 : 23 : break;
817 : 38008 : case Constant_kind:
818 : : // Already a constant, nothing further to do
819 : 38008 : break;
820 : : // No default case, so the compiler will emit a warning if new expression
821 : : // kinds are added without being handled here
822 : : }
823 : 223009 : state->recursion_depth--;
824 : 223009 : return 1;
825 : : }
826 : :
827 : : static int
828 : 2185 : astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
829 : : {
830 [ - + ]: 2185 : CALL(astfold_expr, expr_ty, node_->value);
831 : 2185 : return 1;
832 : : }
833 : :
834 : : static int
835 : 467 : astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
836 : : {
837 [ - + ]: 467 : CALL(astfold_expr, expr_ty, node_->target);
838 [ - + ]: 467 : CALL(astfold_expr, expr_ty, node_->iter);
839 [ + - - + : 583 : CALL_SEQ(astfold_expr, expr, node_->ifs);
+ - + + ]
840 : :
841 [ - + ]: 467 : CALL(fold_iter, expr_ty, node_->iter);
842 : 467 : return 1;
843 : : }
844 : :
845 : : static int
846 : 6536 : astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
847 : : {
848 [ + - - + : 6648 : CALL_SEQ(astfold_arg, arg, node_->posonlyargs);
+ - + + ]
849 [ + - - + : 18846 : CALL_SEQ(astfold_arg, arg, node_->args);
+ - + + ]
850 [ + + - + ]: 6536 : CALL_OPT(astfold_arg, arg_ty, node_->vararg);
851 [ + - - + : 7109 : CALL_SEQ(astfold_arg, arg, node_->kwonlyargs);
+ - + + ]
852 [ + + - + : 7109 : CALL_SEQ(astfold_expr, expr, node_->kw_defaults);
+ - + + ]
853 [ + + - + ]: 6536 : CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
854 [ + - - + : 8312 : CALL_SEQ(astfold_expr, expr, node_->defaults);
+ - + + ]
855 : 6536 : return 1;
856 : : }
857 : :
858 : : static int
859 : 13520 : astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
860 : : {
861 [ + - ]: 13520 : if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
862 [ + + - + ]: 13520 : CALL_OPT(astfold_expr, expr_ty, node_->annotation);
863 : : }
864 : 13520 : return 1;
865 : : }
866 : :
867 : : static int
868 : 58316 : astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
869 : : {
870 [ - + ]: 58316 : if (++state->recursion_depth > state->recursion_limit) {
871 : 0 : PyErr_SetString(PyExc_RecursionError,
872 : : "maximum recursion depth exceeded during compilation");
873 : 0 : return 0;
874 : : }
875 [ + + + + : 58316 : switch (node_->kind) {
+ + + + +
- + + + +
+ + - + +
+ + - ]
876 : 6243 : case FunctionDef_kind:
877 [ - + ]: 6243 : CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
878 [ - + ]: 6243 : CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
879 [ + - - + : 6838 : CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
+ + + + ]
880 [ + - ]: 6243 : if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
881 [ + + - + ]: 6243 : CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
882 : : }
883 : 6243 : break;
884 : 158 : case AsyncFunctionDef_kind:
885 [ - + ]: 158 : CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
886 [ - + ]: 158 : CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
887 [ + - - + : 166 : CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
+ + + + ]
888 [ + - ]: 158 : if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
889 [ + + - + ]: 158 : CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
890 : : }
891 : 158 : break;
892 : 733 : case ClassDef_kind:
893 [ + - - + : 1337 : CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);
+ + + + ]
894 [ + - - + : 789 : CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);
+ + + + ]
895 [ - + ]: 733 : CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
896 [ + - - + : 751 : CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);
+ + + + ]
897 : 733 : break;
898 : 5841 : case Return_kind:
899 [ + + - + ]: 5841 : CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
900 : 5841 : break;
901 : 192 : case Delete_kind:
902 [ + - - + : 417 : CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);
+ - + + ]
903 : 192 : break;
904 : 16574 : case Assign_kind:
905 [ + - - + : 33303 : CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);
+ - + + ]
906 [ - + ]: 16574 : CALL(astfold_expr, expr_ty, node_->v.Assign.value);
907 : 16574 : break;
908 : 715 : case AugAssign_kind:
909 [ - + ]: 715 : CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
910 [ - + ]: 715 : CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
911 : 715 : break;
912 : 17 : case AnnAssign_kind:
913 [ - + ]: 17 : CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
914 [ + - ]: 17 : if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
915 [ - + ]: 17 : CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
916 : : }
917 [ + + - + ]: 17 : CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
918 : 17 : break;
919 : 1222 : case For_kind:
920 [ - + ]: 1222 : CALL(astfold_expr, expr_ty, node_->v.For.target);
921 [ - + ]: 1222 : CALL(astfold_expr, expr_ty, node_->v.For.iter);
922 [ + - - + : 3566 : CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
+ - + + ]
923 [ + - - + : 1282 : CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
+ + + + ]
924 : :
925 [ - + ]: 1222 : CALL(fold_iter, expr_ty, node_->v.For.iter);
926 : 1222 : break;
927 : 0 : case AsyncFor_kind:
928 [ # # ]: 0 : CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
929 [ # # ]: 0 : CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
930 [ # # # # : 0 : CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
# # # # ]
931 [ # # # # : 0 : CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
# # # # ]
932 : 0 : break;
933 : 302 : case While_kind:
934 [ - + ]: 302 : CALL(astfold_expr, expr_ty, node_->v.While.test);
935 [ + - - + : 1208 : CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
+ - + + ]
936 [ + - - + : 308 : CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
+ + + + ]
937 : 302 : break;
938 : 8830 : case If_kind:
939 [ - + ]: 8830 : CALL(astfold_expr, expr_ty, node_->v.If.test);
940 [ + - - + : 21926 : CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);
+ - + + ]
941 [ + - - + : 12003 : CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);
+ + + + ]
942 : 8830 : break;
943 : 378 : case With_kind:
944 [ + - - + : 761 : CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);
+ - + + ]
945 [ + - - + : 1129 : CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);
+ - + + ]
946 : 378 : break;
947 : 5 : case AsyncWith_kind:
948 [ + - - + : 10 : CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);
+ - + + ]
949 [ + - - + : 13 : CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);
+ - + + ]
950 : 5 : break;
951 : 1931 : case Raise_kind:
952 [ + + - + ]: 1931 : CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
953 [ + + - + ]: 1931 : CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
954 : 1931 : break;
955 : 1455 : case Try_kind:
956 [ + - - + : 3528 : CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
+ - + + ]
957 [ + - - + : 2886 : CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
+ + + + ]
958 [ + - - + : 1841 : CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
+ + + + ]
959 [ + - - + : 1715 : CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
+ + + + ]
960 : 1455 : break;
961 : 0 : case TryStar_kind:
962 [ # # # # : 0 : CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.body);
# # # # ]
963 [ # # # # : 0 : CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.TryStar.handlers);
# # # # ]
964 [ # # # # : 0 : CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.orelse);
# # # # ]
965 [ # # # # : 0 : CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.finalbody);
# # # # ]
966 : 0 : break;
967 : 239 : case Assert_kind:
968 [ - + ]: 239 : CALL(astfold_expr, expr_ty, node_->v.Assert.test);
969 [ + + - + ]: 239 : CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
970 : 239 : break;
971 : 10972 : case Expr_kind:
972 [ - + ]: 10972 : CALL(astfold_expr, expr_ty, node_->v.Expr.value);
973 : 10972 : break;
974 : 4 : case Match_kind:
975 [ - + ]: 4 : CALL(astfold_expr, expr_ty, node_->v.Match.subject);
976 [ + - - + : 16 : CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases);
+ - + + ]
977 : 4 : break;
978 : : // The following statements don't contain any subexpressions to be folded
979 : 2505 : case Import_kind:
980 : : case ImportFrom_kind:
981 : : case Global_kind:
982 : : case Nonlocal_kind:
983 : : case Pass_kind:
984 : : case Break_kind:
985 : : case Continue_kind:
986 : 2505 : break;
987 : : // No default case, so the compiler will emit a warning if new statement
988 : : // kinds are added without being handled here
989 : : }
990 : 58316 : state->recursion_depth--;
991 : 58316 : return 1;
992 : : }
993 : :
994 : : static int
995 : 1431 : astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
996 : : {
997 [ + - ]: 1431 : switch (node_->kind) {
998 : 1431 : case ExceptHandler_kind:
999 [ + + - + ]: 1431 : CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
1000 [ + - - + : 3347 : CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);
+ - + + ]
1001 : 1431 : break;
1002 : : // No default case, so the compiler will emit a warning if new handler
1003 : : // kinds are added without being handled here
1004 : : }
1005 : 1431 : return 1;
1006 : : }
1007 : :
1008 : : static int
1009 : 388 : astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
1010 : : {
1011 [ - + ]: 388 : CALL(astfold_expr, expr_ty, node_->context_expr);
1012 [ + + - + ]: 388 : CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
1013 : 388 : return 1;
1014 : : }
1015 : :
1016 : : static int
1017 : 19 : astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
1018 : : {
1019 : : // Currently, this is really only used to form complex/negative numeric
1020 : : // constants in MatchValue and MatchMapping nodes
1021 : : // We still recurse into all subexpressions and subpatterns anyway
1022 [ - + ]: 19 : if (++state->recursion_depth > state->recursion_limit) {
1023 : 0 : PyErr_SetString(PyExc_RecursionError,
1024 : : "maximum recursion depth exceeded during compilation");
1025 : 0 : return 0;
1026 : : }
1027 [ + + + - : 19 : switch (node_->kind) {
+ + + -
- ]
1028 : 4 : case MatchValue_kind:
1029 [ - + ]: 4 : CALL(astfold_expr, expr_ty, node_->v.MatchValue.value);
1030 : 4 : break;
1031 : 1 : case MatchSingleton_kind:
1032 : 1 : break;
1033 : 5 : case MatchSequence_kind:
1034 [ + - - + : 10 : CALL_SEQ(astfold_pattern, pattern, node_->v.MatchSequence.patterns);
+ - + + ]
1035 : 5 : break;
1036 : 0 : case MatchMapping_kind:
1037 [ # # # # : 0 : CALL_SEQ(astfold_expr, expr, node_->v.MatchMapping.keys);
# # # # ]
1038 [ # # # # : 0 : CALL_SEQ(astfold_pattern, pattern, node_->v.MatchMapping.patterns);
# # # # ]
1039 : 0 : break;
1040 : 4 : case MatchClass_kind:
1041 [ - + ]: 4 : CALL(astfold_expr, expr_ty, node_->v.MatchClass.cls);
1042 [ + - - + : 6 : CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.patterns);
+ + + + ]
1043 [ - - - - : 4 : CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.kwd_patterns);
- + - + ]
1044 : 4 : break;
1045 : 1 : case MatchStar_kind:
1046 : 1 : break;
1047 : 4 : case MatchAs_kind:
1048 [ - + ]: 4 : if (node_->v.MatchAs.pattern) {
1049 [ # # ]: 0 : CALL(astfold_pattern, pattern_ty, node_->v.MatchAs.pattern);
1050 : : }
1051 : 4 : break;
1052 : 0 : case MatchOr_kind:
1053 [ # # # # : 0 : CALL_SEQ(astfold_pattern, pattern, node_->v.MatchOr.patterns);
# # # # ]
1054 : 0 : break;
1055 : : // No default case, so the compiler will emit a warning if new pattern
1056 : : // kinds are added without being handled here
1057 : : }
1058 : 19 : state->recursion_depth--;
1059 : 19 : return 1;
1060 : : }
1061 : :
1062 : : static int
1063 : 12 : astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
1064 : : {
1065 [ - + ]: 12 : CALL(astfold_pattern, expr_ty, node_->pattern);
1066 [ + + - + ]: 12 : CALL_OPT(astfold_expr, expr_ty, node_->guard);
1067 [ + - - + : 33 : CALL_SEQ(astfold_stmt, stmt, node_->body);
+ - + + ]
1068 : 12 : return 1;
1069 : : }
1070 : :
1071 : : #undef CALL
1072 : : #undef CALL_OPT
1073 : : #undef CALL_SEQ
1074 : :
1075 : : /* See comments in symtable.c. */
1076 : : #define COMPILER_STACK_FRAME_SCALE 3
1077 : :
1078 : : int
1079 : 319 : _PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
1080 : : {
1081 : : PyThreadState *tstate;
1082 : : int starting_recursion_depth;
1083 : :
1084 : : /* Setup recursion depth check counters */
1085 : 319 : tstate = _PyThreadState_GET();
1086 [ - + ]: 319 : if (!tstate) {
1087 : 0 : return 0;
1088 : : }
1089 : : /* Be careful here to prevent overflow. */
1090 : 319 : int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
1091 : 319 : starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
1092 : 319 : state->recursion_depth = starting_recursion_depth;
1093 : 319 : state->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
1094 : :
1095 : 319 : int ret = astfold_mod(mod, arena, state);
1096 : : assert(ret || PyErr_Occurred());
1097 : :
1098 : : /* Check that the recursion depth counting balanced correctly */
1099 [ + - - + ]: 319 : if (ret && state->recursion_depth != starting_recursion_depth) {
1100 : 0 : PyErr_Format(PyExc_SystemError,
1101 : : "AST optimizer recursion depth mismatch (before=%d, after=%d)",
1102 : : starting_recursion_depth, state->recursion_depth);
1103 : 0 : return 0;
1104 : : }
1105 : :
1106 : 319 : return ret;
1107 : : }
|