Coverage Report

Created: 2025-07-11 06:59

/src/Python-3.8.3/Python/ast_opt.c
Line
Count
Source (jump to first uncovered line)
1
/* AST Optimizer */
2
#include "Python.h"
3
#include "Python-ast.h"
4
#include "ast.h"
5
6
7
static int
8
make_const(expr_ty node, PyObject *val, PyArena *arena)
9
14
{
10
14
    if (val == NULL) {
11
12
        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
12
0
            return 0;
13
0
        }
14
12
        PyErr_Clear();
15
12
        return 1;
16
12
    }
17
2
    if (PyArena_AddPyObject(arena, val) < 0) {
18
0
        Py_DECREF(val);
19
0
        return 0;
20
0
    }
21
2
    node->kind = Constant_kind;
22
2
    node->v.Constant.value = val;
23
2
    return 1;
24
2
}
25
26
0
#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
27
28
static PyObject*
29
unary_not(PyObject *v)
30
0
{
31
0
    int r = PyObject_IsTrue(v);
32
0
    if (r < 0)
33
0
        return NULL;
34
0
    return PyBool_FromLong(!r);
35
0
}
36
37
static int
38
fold_unaryop(expr_ty node, PyArena *arena, int optimize)
39
0
{
40
0
    expr_ty arg = node->v.UnaryOp.operand;
41
42
0
    if (arg->kind != Constant_kind) {
43
        /* Fold not into comparison */
44
0
        if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
45
0
                asdl_seq_LEN(arg->v.Compare.ops) == 1) {
46
            /* Eq and NotEq are often implemented in terms of one another, so
47
               folding not (self == other) into self != other breaks implementation
48
               of !=. Detecting such cases doesn't seem worthwhile.
49
               Python uses </> for 'is subset'/'is superset' operations on sets.
50
               They don't satisfy not folding laws. */
51
0
            int op = asdl_seq_GET(arg->v.Compare.ops, 0);
52
0
            switch (op) {
53
0
            case Is:
54
0
                op = IsNot;
55
0
                break;
56
0
            case IsNot:
57
0
                op = Is;
58
0
                break;
59
0
            case In:
60
0
                op = NotIn;
61
0
                break;
62
0
            case NotIn:
63
0
                op = In;
64
0
                break;
65
0
            default:
66
0
                op = 0;
67
0
            }
68
0
            if (op) {
69
0
                asdl_seq_SET(arg->v.Compare.ops, 0, op);
70
0
                COPY_NODE(node, arg);
71
0
                return 1;
72
0
            }
73
0
        }
74
0
        return 1;
75
0
    }
76
77
0
    typedef PyObject *(*unary_op)(PyObject*);
78
0
    static const unary_op ops[] = {
79
0
        [Invert] = PyNumber_Invert,
80
0
        [Not] = unary_not,
81
0
        [UAdd] = PyNumber_Positive,
82
0
        [USub] = PyNumber_Negative,
83
0
    };
84
0
    PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
85
0
    return make_const(node, newval, arena);
86
0
}
87
88
/* Check whether a collection doesn't containing too much items (including
89
   subcollections).  This protects from creating a constant that needs
90
   too much time for calculating a hash.
91
   "limit" is the maximal number of items.
92
   Returns the negative number if the total number of items exceeds the
93
   limit.  Otherwise returns the limit minus the total number of items.
94
*/
95
96
static Py_ssize_t
97
check_complexity(PyObject *obj, Py_ssize_t limit)
98
0
{
99
0
    if (PyTuple_Check(obj)) {
100
0
        Py_ssize_t i;
101
0
        limit -= PyTuple_GET_SIZE(obj);
102
0
        for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
103
0
            limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
104
0
        }
105
0
        return limit;
106
0
    }
107
0
    else if (PyFrozenSet_Check(obj)) {
108
0
        Py_ssize_t i = 0;
109
0
        PyObject *item;
110
0
        Py_hash_t hash;
111
0
        limit -= PySet_GET_SIZE(obj);
112
0
        while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
113
0
            limit = check_complexity(item, limit);
114
0
        }
115
0
    }
116
0
    return limit;
117
0
}
118
119
0
#define MAX_INT_SIZE           128  /* bits */
120
0
#define MAX_COLLECTION_SIZE    256  /* items */
121
0
#define MAX_STR_SIZE          4096  /* characters */
122
0
#define MAX_TOTAL_ITEMS       1024  /* including nested collections */
123
124
static PyObject *
125
safe_multiply(PyObject *v, PyObject *w)
126
0
{
127
0
    if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
128
0
        size_t vbits = _PyLong_NumBits(v);
129
0
        size_t wbits = _PyLong_NumBits(w);
130
0
        if (vbits == (size_t)-1 || wbits == (size_t)-1) {
131
0
            return NULL;
132
0
        }
133
0
        if (vbits + wbits > MAX_INT_SIZE) {
134
0
            return NULL;
135
0
        }
136
0
    }
137
0
    else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
138
0
        Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
139
0
                                             PySet_GET_SIZE(w);
140
0
        if (size) {
141
0
            long n = PyLong_AsLong(v);
142
0
            if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
143
0
                return NULL;
144
0
            }
145
0
            if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
146
0
                return NULL;
147
0
            }
148
0
        }
149
0
    }
150
0
    else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
151
0
        Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
152
0
                                               PyBytes_GET_SIZE(w);
153
0
        if (size) {
154
0
            long n = PyLong_AsLong(v);
155
0
            if (n < 0 || n > MAX_STR_SIZE / size) {
156
0
                return NULL;
157
0
            }
158
0
        }
159
0
    }
160
0
    else if (PyLong_Check(w) &&
161
0
             (PyTuple_Check(v) || PyFrozenSet_Check(v) ||
162
0
              PyUnicode_Check(v) || PyBytes_Check(v)))
163
0
    {
164
0
        return safe_multiply(w, v);
165
0
    }
166
167
0
    return PyNumber_Multiply(v, w);
168
0
}
169
170
static PyObject *
171
safe_power(PyObject *v, PyObject *w)
172
0
{
173
0
    if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
174
0
        size_t vbits = _PyLong_NumBits(v);
175
0
        size_t wbits = PyLong_AsSize_t(w);
176
0
        if (vbits == (size_t)-1 || wbits == (size_t)-1) {
177
0
            return NULL;
178
0
        }
179
0
        if (vbits > MAX_INT_SIZE / wbits) {
180
0
            return NULL;
181
0
        }
182
0
    }
183
184
0
    return PyNumber_Power(v, w, Py_None);
185
0
}
186
187
static PyObject *
188
safe_lshift(PyObject *v, PyObject *w)
189
0
{
190
0
    if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
191
0
        size_t vbits = _PyLong_NumBits(v);
192
0
        size_t wbits = PyLong_AsSize_t(w);
193
0
        if (vbits == (size_t)-1 || wbits == (size_t)-1) {
194
0
            return NULL;
195
0
        }
196
0
        if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
197
0
            return NULL;
198
0
        }
199
0
    }
200
201
0
    return PyNumber_Lshift(v, w);
202
0
}
203
204
static PyObject *
205
safe_mod(PyObject *v, PyObject *w)
206
0
{
207
0
    if (PyUnicode_Check(v) || PyBytes_Check(v)) {
208
0
        return NULL;
209
0
    }
210
211
0
    return PyNumber_Remainder(v, w);
212
0
}
213
214
static int
215
fold_binop(expr_ty node, PyArena *arena, int optimize)
216
12
{
217
12
    expr_ty lhs, rhs;
218
12
    lhs = node->v.BinOp.left;
219
12
    rhs = node->v.BinOp.right;
220
12
    if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
221
12
        return 1;
222
12
    }
223
224
0
    PyObject *lv = lhs->v.Constant.value;
225
0
    PyObject *rv = rhs->v.Constant.value;
226
0
    PyObject *newval;
227
228
0
    switch (node->v.BinOp.op) {
229
0
    case Add:
230
0
        newval = PyNumber_Add(lv, rv);
231
0
        break;
232
0
    case Sub:
233
0
        newval = PyNumber_Subtract(lv, rv);
234
0
        break;
235
0
    case Mult:
236
0
        newval = safe_multiply(lv, rv);
237
0
        break;
238
0
    case Div:
239
0
        newval = PyNumber_TrueDivide(lv, rv);
240
0
        break;
241
0
    case FloorDiv:
242
0
        newval = PyNumber_FloorDivide(lv, rv);
243
0
        break;
244
0
    case Mod:
245
0
        newval = safe_mod(lv, rv);
246
0
        break;
247
0
    case Pow:
248
0
        newval = safe_power(lv, rv);
249
0
        break;
250
0
    case LShift:
251
0
        newval = safe_lshift(lv, rv);
252
0
        break;
253
0
    case RShift:
254
0
        newval = PyNumber_Rshift(lv, rv);
255
0
        break;
256
0
    case BitOr:
257
0
        newval = PyNumber_Or(lv, rv);
258
0
        break;
259
0
    case BitXor:
260
0
        newval = PyNumber_Xor(lv, rv);
261
0
        break;
262
0
    case BitAnd:
263
0
        newval = PyNumber_And(lv, rv);
264
0
        break;
265
0
    default: // Unknown operator
266
0
        return 1;
267
0
    }
268
269
0
    return make_const(node, newval, arena);
270
0
}
271
272
static PyObject*
273
make_const_tuple(asdl_seq *elts)
274
14
{
275
18
    for (int i = 0; i < asdl_seq_LEN(elts); i++) {
276
16
        expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
277
16
        if (e->kind != Constant_kind) {
278
12
            return NULL;
279
12
        }
280
16
    }
281
282
2
    PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
283
2
    if (newval == NULL) {
284
0
        return NULL;
285
0
    }
286
287
6
    for (int i = 0; i < asdl_seq_LEN(elts); i++) {
288
4
        expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
289
4
        PyObject *v = e->v.Constant.value;
290
4
        Py_INCREF(v);
291
4
        PyTuple_SET_ITEM(newval, i, v);
292
4
    }
293
2
    return newval;
294
2
}
295
296
static int
297
fold_tuple(expr_ty node, PyArena *arena, int optimize)
298
24
{
299
24
    PyObject *newval;
300
301
24
    if (node->v.Tuple.ctx != Load)
302
10
        return 1;
303
304
14
    newval = make_const_tuple(node->v.Tuple.elts);
305
14
    return make_const(node, newval, arena);
306
24
}
307
308
static int
309
fold_subscr(expr_ty node, PyArena *arena, int optimize)
310
14
{
311
14
    PyObject *newval;
312
14
    expr_ty arg, idx;
313
14
    slice_ty slice;
314
315
14
    arg = node->v.Subscript.value;
316
14
    slice = node->v.Subscript.slice;
317
14
    if (node->v.Subscript.ctx != Load ||
318
14
            arg->kind != Constant_kind ||
319
            /* TODO: handle other types of slices */
320
14
            slice->kind != Index_kind ||
321
14
            slice->v.Index.value->kind != Constant_kind)
322
14
    {
323
14
        return 1;
324
14
    }
325
326
0
    idx = slice->v.Index.value;
327
0
    newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
328
0
    return make_const(node, newval, arena);
329
14
}
330
331
/* Change literal list or set of constants into constant
332
   tuple or frozenset respectively.  Change literal list of
333
   non-constants into tuple.
334
   Used for right operand of "in" and "not in" tests and for iterable
335
   in "for" loop and comprehensions.
336
*/
337
static int
338
fold_iter(expr_ty arg, PyArena *arena, int optimize)
339
18
{
340
18
    PyObject *newval;
341
18
    if (arg->kind == List_kind) {
342
        /* First change a list into tuple. */
343
0
        asdl_seq *elts = arg->v.List.elts;
344
0
        Py_ssize_t n = asdl_seq_LEN(elts);
345
0
        for (Py_ssize_t i = 0; i < n; i++) {
346
0
            expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
347
0
            if (e->kind == Starred_kind) {
348
0
                return 1;
349
0
            }
350
0
        }
351
0
        expr_context_ty ctx = arg->v.List.ctx;
352
0
        arg->kind = Tuple_kind;
353
0
        arg->v.Tuple.elts = elts;
354
0
        arg->v.Tuple.ctx = ctx;
355
        /* Try to create a constant tuple. */
356
0
        newval = make_const_tuple(elts);
357
0
    }
358
18
    else if (arg->kind == Set_kind) {
359
0
        newval = make_const_tuple(arg->v.Set.elts);
360
0
        if (newval) {
361
0
            Py_SETREF(newval, PyFrozenSet_New(newval));
362
0
        }
363
0
    }
364
18
    else {
365
18
        return 1;
366
18
    }
367
0
    return make_const(arg, newval, arena);
368
18
}
369
370
static int
371
fold_compare(expr_ty node, PyArena *arena, int optimize)
372
24
{
373
24
    asdl_int_seq *ops;
374
24
    asdl_seq *args;
375
24
    Py_ssize_t i;
376
377
24
    ops = node->v.Compare.ops;
378
24
    args = node->v.Compare.comparators;
379
    /* TODO: optimize cases with literal arguments. */
380
    /* Change literal list or set in 'in' or 'not in' into
381
       tuple or frozenset respectively. */
382
24
    i = asdl_seq_LEN(ops) - 1;
383
24
    int op = asdl_seq_GET(ops, i);
384
24
    if (op == In || op == NotIn) {
385
10
        if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, optimize)) {
386
0
            return 0;
387
0
        }
388
10
    }
389
24
    return 1;
390
24
}
391
392
static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_);
393
static int astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_);
394
static int astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_);
395
static int astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_);
396
static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_);
397
static int astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_);
398
static int astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_);
399
static int astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_);
400
static int astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_);
401
static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_);
402
#define CALL(FUNC, TYPE, ARG) \
403
438
    if (!FUNC((ARG), ctx_, optimize_)) \
404
438
        return 0;
405
406
#define CALL_OPT(FUNC, TYPE, ARG) \
407
75
    if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \
408
75
        return 0;
409
410
438
#define CALL_SEQ(FUNC, TYPE, ARG) { \
411
438
    int i; \
412
438
    asdl_seq *seq = (ARG); /* avoid variable capture */ \
413
848
    for (i = 0; i < asdl_seq_LEN(seq); i++) { \
414
410
        TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
415
410
        if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \
416
410
            return 0; \
417
410
    } \
418
438
}
419
420
#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
421
    int i; \
422
    asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
423
    for (i = 0; i < asdl_seq_LEN(seq); i++) { \
424
        TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
425
        if (!FUNC(elt, ctx_, optimize_)) \
426
            return 0; \
427
    } \
428
}
429
430
static int
431
astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_)
432
20
{
433
20
    int docstring = _PyAST_GetDocString(stmts) != NULL;
434
20
    CALL_SEQ(astfold_stmt, stmt_ty, stmts);
435
20
    if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
436
0
        stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
437
0
        asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
438
0
        if (!values) {
439
0
            return 0;
440
0
        }
441
0
        asdl_seq_SET(values, 0, st->v.Expr.value);
442
0
        expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
443
0
                                 st->end_lineno, st->end_col_offset, ctx_);
444
0
        if (!expr) {
445
0
            return 0;
446
0
        }
447
0
        st->v.Expr.value = expr;
448
0
    }
449
20
    return 1;
450
20
}
451
452
static int
453
astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_)
454
16
{
455
16
    switch (node_->kind) {
456
16
    case Module_kind:
457
16
        CALL(astfold_body, asdl_seq, node_->v.Module.body);
458
16
        break;
459
0
    case Interactive_kind:
460
0
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
461
0
        break;
462
0
    case Expression_kind:
463
0
        CALL(astfold_expr, expr_ty, node_->v.Expression.body);
464
0
        break;
465
0
    case Suite_kind:
466
0
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Suite.body);
467
0
        break;
468
0
    default:
469
0
        break;
470
16
    }
471
16
    return 1;
472
16
}
473
474
static int
475
astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_)
476
583
{
477
583
    switch (node_->kind) {
478
0
    case BoolOp_kind:
479
0
        CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
480
0
        break;
481
12
    case BinOp_kind:
482
12
        CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
483
12
        CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
484
12
        CALL(fold_binop, expr_ty, node_);
485
12
        break;
486
0
    case UnaryOp_kind:
487
0
        CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
488
0
        CALL(fold_unaryop, expr_ty, node_);
489
0
        break;
490
2
    case Lambda_kind:
491
2
        CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
492
2
        CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
493
2
        break;
494
0
    case IfExp_kind:
495
0
        CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
496
0
        CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
497
0
        CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
498
0
        break;
499
6
    case Dict_kind:
500
6
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
501
6
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
502
6
        break;
503
0
    case Set_kind:
504
0
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
505
0
        break;
506
0
    case ListComp_kind:
507
0
        CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
508
0
        CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
509
0
        break;
510
0
    case SetComp_kind:
511
0
        CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
512
0
        CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
513
0
        break;
514
0
    case DictComp_kind:
515
0
        CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
516
0
        CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
517
0
        CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
518
0
        break;
519
0
    case GeneratorExp_kind:
520
0
        CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
521
0
        CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
522
0
        break;
523
0
    case Await_kind:
524
0
        CALL(astfold_expr, expr_ty, node_->v.Await.value);
525
0
        break;
526
0
    case Yield_kind:
527
0
        CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
528
0
        break;
529
0
    case YieldFrom_kind:
530
0
        CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
531
0
        break;
532
24
    case Compare_kind:
533
24
        CALL(astfold_expr, expr_ty, node_->v.Compare.left);
534
24
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
535
24
        CALL(fold_compare, expr_ty, node_);
536
24
        break;
537
80
    case Call_kind:
538
80
        CALL(astfold_expr, expr_ty, node_->v.Call.func);
539
80
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
540
80
        CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
541
80
        break;
542
0
    case FormattedValue_kind:
543
0
        CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
544
0
        CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
545
0
        break;
546
0
    case JoinedStr_kind:
547
0
        CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
548
0
        break;
549
60
    case Attribute_kind:
550
60
        CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
551
60
        break;
552
14
    case Subscript_kind:
553
14
        CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
554
14
        CALL(astfold_slice, slice_ty, node_->v.Subscript.slice);
555
14
        CALL(fold_subscr, expr_ty, node_);
556
14
        break;
557
0
    case Starred_kind:
558
0
        CALL(astfold_expr, expr_ty, node_->v.Starred.value);
559
0
        break;
560
4
    case List_kind:
561
4
        CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
562
4
        break;
563
24
    case Tuple_kind:
564
24
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
565
24
        CALL(fold_tuple, expr_ty, node_);
566
24
        break;
567
295
    case Name_kind:
568
295
        if (_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
569
0
            return make_const(node_, PyBool_FromLong(!optimize_), ctx_);
570
0
        }
571
295
        break;
572
295
    default:
573
62
        break;
574
583
    }
575
583
    return 1;
576
583
}
577
578
static int
579
astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_)
580
14
{
581
14
    switch (node_->kind) {
582
2
    case Slice_kind:
583
2
        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
584
2
        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
585
2
        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
586
2
        break;
587
0
    case ExtSlice_kind:
588
0
        CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims);
589
0
        break;
590
12
    case Index_kind:
591
12
        CALL(astfold_expr, expr_ty, node_->v.Index.value);
592
12
        break;
593
0
    default:
594
0
        break;
595
14
    }
596
14
    return 1;
597
14
}
598
599
static int
600
astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_)
601
0
{
602
0
    CALL(astfold_expr, expr_ty, node_->value);
603
0
    return 1;
604
0
}
605
606
static int
607
astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_)
608
0
{
609
0
    CALL(astfold_expr, expr_ty, node_->target);
610
0
    CALL(astfold_expr, expr_ty, node_->iter);
611
0
    CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
612
613
0
    CALL(fold_iter, expr_ty, node_->iter);
614
0
    return 1;
615
0
}
616
617
static int
618
astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_)
619
6
{
620
6
    CALL_SEQ(astfold_arg, arg_ty, node_->posonlyargs);
621
6
    CALL_SEQ(astfold_arg, arg_ty, node_->args);
622
6
    CALL_OPT(astfold_arg, arg_ty, node_->vararg);
623
6
    CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
624
6
    CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
625
6
    CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
626
6
    CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
627
6
    return 1;
628
6
}
629
630
static int
631
astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_)
632
17
{
633
17
    CALL_OPT(astfold_expr, expr_ty, node_->annotation);
634
17
    return 1;
635
17
}
636
637
static int
638
astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_)
639
140
{
640
140
    switch (node_->kind) {
641
4
    case FunctionDef_kind:
642
4
        CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
643
4
        CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
644
4
        CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
645
4
        CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
646
4
        break;
647
0
    case AsyncFunctionDef_kind:
648
0
        CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
649
0
        CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
650
0
        CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
651
0
        CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
652
0
        break;
653
0
    case ClassDef_kind:
654
0
        CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
655
0
        CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
656
0
        CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
657
0
        CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
658
0
        break;
659
6
    case Return_kind:
660
6
        CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
661
6
        break;
662
2
    case Delete_kind:
663
2
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
664
2
        break;
665
34
    case Assign_kind:
666
34
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
667
34
        CALL(astfold_expr, expr_ty, node_->v.Assign.value);
668
34
        break;
669
0
    case AugAssign_kind:
670
0
        CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
671
0
        CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
672
0
        break;
673
0
    case AnnAssign_kind:
674
0
        CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
675
0
        CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
676
0
        CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
677
0
        break;
678
8
    case For_kind:
679
8
        CALL(astfold_expr, expr_ty, node_->v.For.target);
680
8
        CALL(astfold_expr, expr_ty, node_->v.For.iter);
681
8
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
682
8
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
683
684
8
        CALL(fold_iter, expr_ty, node_->v.For.iter);
685
8
        break;
686
0
    case AsyncFor_kind:
687
0
        CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
688
0
        CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
689
0
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
690
0
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
691
0
        break;
692
0
    case While_kind:
693
0
        CALL(astfold_expr, expr_ty, node_->v.While.test);
694
0
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
695
0
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
696
0
        break;
697
8
    case If_kind:
698
8
        CALL(astfold_expr, expr_ty, node_->v.If.test);
699
8
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
700
8
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
701
8
        break;
702
0
    case With_kind:
703
0
        CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
704
0
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
705
0
        break;
706
0
    case AsyncWith_kind:
707
0
        CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
708
0
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
709
0
        break;
710
2
    case Raise_kind:
711
2
        CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
712
2
        CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
713
2
        break;
714
18
    case Try_kind:
715
18
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
716
18
        CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
717
18
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
718
18
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
719
18
        break;
720
6
    case Assert_kind:
721
6
        CALL(astfold_expr, expr_ty, node_->v.Assert.test);
722
6
        CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
723
6
        break;
724
36
    case Expr_kind:
725
36
        CALL(astfold_expr, expr_ty, node_->v.Expr.value);
726
36
        break;
727
16
    default:
728
16
        break;
729
140
    }
730
140
    return 1;
731
140
}
732
733
static int
734
astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_)
735
20
{
736
20
    switch (node_->kind) {
737
20
    case ExceptHandler_kind:
738
20
        CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
739
20
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
740
20
        break;
741
0
    default:
742
0
        break;
743
20
    }
744
20
    return 1;
745
20
}
746
747
static int
748
astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_)
749
0
{
750
0
    CALL(astfold_expr, expr_ty, node_->context_expr);
751
0
    CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
752
0
    return 1;
753
0
}
754
755
#undef CALL
756
#undef CALL_OPT
757
#undef CALL_SEQ
758
#undef CALL_INT_SEQ
759
760
int
761
_PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize)
762
16
{
763
16
    int ret = astfold_mod(mod, arena, optimize);
764
16
    assert(ret || PyErr_Occurred());
765
16
    return ret;
766
16
}