Coverage Report

Created: 2022-07-08 09:39

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