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