LCOV - code coverage report
Current view: | top level - Python - ast_opt.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 531 | 667 | 79.6 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 29 | 32 | 90.6 %
|  |  | Branches: | 632 | 1059 | 59.7 %

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

Generated by: LCOV version 1.14