Coverage Report

Created: 2026-06-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Python-3.8.3/Python/ast_opt.c
Line
Count
Source
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
10
            arg->kind != Constant_kind ||
319
            /* TODO: handle other types of slices */
320
0
            slice->kind != Index_kind ||
321
0
            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
434
    if (!FUNC((ARG), ctx_, optimize_)) \
404
434
        return 0;
405
406
#define CALL_OPT(FUNC, TYPE, ARG) \
407
74
    if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \
408
74
        return 0;
409
410
430
#define CALL_SEQ(FUNC, TYPE, ARG) { \
411
430
    int i; \
412
430
    asdl_seq *seq = (ARG); /* avoid variable capture */ \
413
834
    for (i = 0; i < asdl_seq_LEN(seq); i++) { \
414
404
        TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
415
404
        if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \
416
404
            return 0; \
417
404
    } \
418
430
}
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
19
{
433
19
    int docstring = _PyAST_GetDocString(stmts) != NULL;
434
19
    CALL_SEQ(astfold_stmt, stmt_ty, stmts);
435
19
    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
19
    return 1;
450
19
}
451
452
static int
453
astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_)
454
15
{
455
15
    switch (node_->kind) {
456
15
    case Module_kind:
457
15
        CALL(astfold_body, asdl_seq, node_->v.Module.body);
458
15
        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
15
    }
471
15
    return 1;
472
15
}
473
474
static int
475
astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_)
476
577
{
477
577
    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
79
    case Call_kind:
538
79
        CALL(astfold_expr, expr_ty, node_->v.Call.func);
539
79
        CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
540
79
        CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
541
79
        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
59
    case Attribute_kind:
550
59
        CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
551
59
        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
291
    case Name_kind:
568
291
        if (_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
569
0
            return make_const(node_, PyBool_FromLong(!optimize_), ctx_);
570
0
        }
571
291
        break;
572
291
    default:
573
62
        break;
574
577
    }
575
577
    return 1;
576
577
}
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
137
{
640
137
    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
17
    case Try_kind:
715
17
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
716
17
        CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
717
17
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
718
17
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
719
17
        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
35
    case Expr_kind:
725
35
        CALL(astfold_expr, expr_ty, node_->v.Expr.value);
726
35
        break;
727
15
    default:
728
15
        break;
729
137
    }
730
137
    return 1;
731
137
}
732
733
static int
734
astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_)
735
19
{
736
19
    switch (node_->kind) {
737
19
    case ExceptHandler_kind:
738
19
        CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
739
19
        CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
740
19
        break;
741
0
    default:
742
0
        break;
743
19
    }
744
19
    return 1;
745
19
}
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
15
{
763
15
    int ret = astfold_mod(mod, arena, optimize);
764
    assert(ret || PyErr_Occurred());
765
15
    return ret;
766
15
}