LCOV - code coverage report
Current view: top level - Python - ast_unparse.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 394 499 79.0 %
Date: 2022-07-07 18:19:46 Functions: 37 41 90.2 %

          Line data    Source code
       1             : #include "Python.h"
       2             : #include "pycore_ast.h"           // expr_ty
       3             : #include "pycore_runtime.h"       // _Py_ID()
       4             : #include <float.h>                // DBL_MAX_10_EXP
       5             : #include <stdbool.h>
       6             : 
       7             : /* This limited unparser is used to convert annotations back to strings
       8             :  * during compilation rather than being a full AST unparser.
       9             :  * See ast.unparse for a full unparser (written in Python)
      10             :  */
      11             : 
      12             : _Py_DECLARE_STR(open_br, "{");
      13             : _Py_DECLARE_STR(dbl_open_br, "{{");
      14             : _Py_DECLARE_STR(close_br, "}");
      15             : _Py_DECLARE_STR(dbl_close_br, "}}");
      16             : static PyObject *_str_replace_inf;
      17             : 
      18             : /* Forward declarations for recursion via helper functions. */
      19             : static PyObject *
      20             : expr_as_unicode(expr_ty e, int level);
      21             : static int
      22             : append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level);
      23             : static int
      24             : append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
      25             : static int
      26             : append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e);
      27             : static int
      28             : append_ast_slice(_PyUnicodeWriter *writer, expr_ty e);
      29             : 
      30             : static int
      31        7883 : append_charp(_PyUnicodeWriter *writer, const char *charp)
      32             : {
      33        7883 :     return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1);
      34             : }
      35             : 
      36             : #define APPEND_STR_FINISH(str)  do { \
      37             :         return append_charp(writer, (str)); \
      38             :     } while (0)
      39             : 
      40             : #define APPEND_STR(str)  do { \
      41             :         if (-1 == append_charp(writer, (str))) { \
      42             :             return -1; \
      43             :         } \
      44             :     } while (0)
      45             : 
      46             : #define APPEND_STR_IF(cond, str)  do { \
      47             :         if ((cond) && -1 == append_charp(writer, (str))) { \
      48             :             return -1; \
      49             :         } \
      50             :     } while (0)
      51             : 
      52             : #define APPEND_STR_IF_NOT_FIRST(str)  do { \
      53             :         APPEND_STR_IF(!first, (str)); \
      54             :         first = false; \
      55             :     } while (0)
      56             : 
      57             : #define APPEND_EXPR(expr, pr)  do { \
      58             :         if (-1 == append_ast_expr(writer, (expr), (pr))) { \
      59             :             return -1; \
      60             :         } \
      61             :     } while (0)
      62             : 
      63             : #define APPEND(type, value)  do { \
      64             :         if (-1 == append_ast_ ## type(writer, (value))) { \
      65             :             return -1; \
      66             :         } \
      67             :     } while (0)
      68             : 
      69             : static int
      70        3107 : append_repr(_PyUnicodeWriter *writer, PyObject *obj)
      71             : {
      72        3107 :     PyObject *repr = PyObject_Repr(obj);
      73             : 
      74        3107 :     if (!repr) {
      75           0 :         return -1;
      76             :     }
      77             : 
      78        6179 :     if ((PyFloat_CheckExact(obj) && Py_IS_INFINITY(PyFloat_AS_DOUBLE(obj))) ||
      79        3072 :        PyComplex_CheckExact(obj))
      80             :     {
      81          77 :         PyObject *new_repr = PyUnicode_Replace(
      82             :             repr,
      83             :             &_Py_ID(inf),
      84             :             _str_replace_inf,
      85             :             -1
      86             :         );
      87          77 :         Py_DECREF(repr);
      88          77 :         if (!new_repr) {
      89           0 :             return -1;
      90             :         }
      91          77 :         repr = new_repr;
      92             :     }
      93        3107 :     int ret = _PyUnicodeWriter_WriteStr(writer, repr);
      94        3107 :     Py_DECREF(repr);
      95        3107 :     return ret;
      96             : }
      97             : 
      98             : /* Priority levels */
      99             : 
     100             : enum {
     101             :     PR_TUPLE,
     102             :     PR_TEST,            /* 'if'-'else', 'lambda' */
     103             :     PR_OR,              /* 'or' */
     104             :     PR_AND,             /* 'and' */
     105             :     PR_NOT,             /* 'not' */
     106             :     PR_CMP,             /* '<', '>', '==', '>=', '<=', '!=',
     107             :                            'in', 'not in', 'is', 'is not' */
     108             :     PR_EXPR,
     109             :     PR_BOR = PR_EXPR,   /* '|' */
     110             :     PR_BXOR,            /* '^' */
     111             :     PR_BAND,            /* '&' */
     112             :     PR_SHIFT,           /* '<<', '>>' */
     113             :     PR_ARITH,           /* '+', '-' */
     114             :     PR_TERM,            /* '*', '@', '/', '%', '//' */
     115             :     PR_FACTOR,          /* unary '+', '-', '~' */
     116             :     PR_POWER,           /* '**' */
     117             :     PR_AWAIT,           /* 'await' */
     118             :     PR_ATOM,
     119             : };
     120             : 
     121             : static int
     122         224 : append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level)
     123             : {
     124             :     Py_ssize_t i, value_count;
     125             :     asdl_expr_seq *values;
     126         224 :     const char *op = (e->v.BoolOp.op == And) ? " and " : " or ";
     127         224 :     int pr = (e->v.BoolOp.op == And) ? PR_AND : PR_OR;
     128             : 
     129         224 :     APPEND_STR_IF(level > pr, "(");
     130             : 
     131         224 :     values = e->v.BoolOp.values;
     132         224 :     value_count = asdl_seq_LEN(values);
     133             : 
     134         714 :     for (i = 0; i < value_count; ++i) {
     135         490 :         APPEND_STR_IF(i > 0, op);
     136         490 :         APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 1);
     137             :     }
     138             : 
     139         224 :     APPEND_STR_IF(level > pr, ")");
     140         224 :     return 0;
     141             : }
     142             : 
     143             : static int
     144        1274 : append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level)
     145             : {
     146             :     const char *op;
     147             :     int pr;
     148        1274 :     bool rassoc = false;  /* is right-associative? */
     149             : 
     150        1274 :     switch (e->v.BinOp.op) {
     151         252 :     case Add: op = " + "; pr = PR_ARITH; break;
     152           7 :     case Sub: op = " - "; pr = PR_ARITH; break;
     153          28 :     case Mult: op = " * "; pr = PR_TERM; break;
     154           0 :     case MatMult: op = " @ "; pr = PR_TERM; break;
     155           7 :     case Div: op = " / "; pr = PR_TERM; break;
     156           7 :     case Mod: op = " % "; pr = PR_TERM; break;
     157          14 :     case LShift: op = " << "; pr = PR_SHIFT; break;
     158           7 :     case RShift: op = " >> "; pr = PR_SHIFT; break;
     159         840 :     case BitOr: op = " | "; pr = PR_BOR; break;
     160          14 :     case BitXor: op = " ^ "; pr = PR_BXOR; break;
     161           0 :     case BitAnd: op = " & "; pr = PR_BAND; break;
     162           7 :     case FloorDiv: op = " // "; pr = PR_TERM; break;
     163          91 :     case Pow: op = " ** "; pr = PR_POWER; rassoc = true; break;
     164           0 :     default:
     165           0 :         PyErr_SetString(PyExc_SystemError,
     166             :                         "unknown binary operator");
     167           0 :         return -1;
     168             :     }
     169             : 
     170        1274 :     APPEND_STR_IF(level > pr, "(");
     171        1274 :     APPEND_EXPR(e->v.BinOp.left, pr + rassoc);
     172        1274 :     APPEND_STR(op);
     173        1274 :     APPEND_EXPR(e->v.BinOp.right, pr + !rassoc);
     174        1274 :     APPEND_STR_IF(level > pr, ")");
     175        1274 :     return 0;
     176             : }
     177             : 
     178             : static int
     179         126 : append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level)
     180             : {
     181             :     const char *op;
     182             :     int pr;
     183             : 
     184         126 :     switch (e->v.UnaryOp.op) {
     185          14 :     case Invert: op = "~"; pr = PR_FACTOR; break;
     186          42 :     case Not: op = "not "; pr = PR_NOT; break;
     187          28 :     case UAdd: op = "+"; pr = PR_FACTOR; break;
     188          42 :     case USub: op = "-"; pr = PR_FACTOR; break;
     189           0 :     default:
     190           0 :         PyErr_SetString(PyExc_SystemError,
     191             :                         "unknown unary operator");
     192           0 :         return -1;
     193             :     }
     194             : 
     195         126 :     APPEND_STR_IF(level > pr, "(");
     196         126 :     APPEND_STR(op);
     197         126 :     APPEND_EXPR(e->v.UnaryOp.operand, pr);
     198         126 :     APPEND_STR_IF(level > pr, ")");
     199         126 :     return 0;
     200             : }
     201             : 
     202             : static int
     203         427 : append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg)
     204             : {
     205         427 :     if (-1 == _PyUnicodeWriter_WriteStr(writer, arg->arg)) {
     206           0 :         return -1;
     207             :     }
     208         427 :     if (arg->annotation) {
     209           0 :         APPEND_STR(": ");
     210           0 :         APPEND_EXPR(arg->annotation, PR_TEST);
     211             :     }
     212         427 :     return 0;
     213             : }
     214             : 
     215             : static int
     216         154 : append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
     217             : {
     218             :     bool first;
     219             :     Py_ssize_t i, di, arg_count, posonlyarg_count, default_count;
     220             : 
     221         154 :     first = true;
     222             : 
     223             :     /* positional-only and positional arguments with defaults */
     224         154 :     posonlyarg_count = asdl_seq_LEN(args->posonlyargs);
     225         154 :     arg_count = asdl_seq_LEN(args->args);
     226         154 :     default_count = asdl_seq_LEN(args->defaults);
     227         448 :     for (i = 0; i < posonlyarg_count + arg_count; i++) {
     228         294 :         APPEND_STR_IF_NOT_FIRST(", ");
     229         294 :         if (i < posonlyarg_count){
     230         112 :             APPEND(arg, (arg_ty)asdl_seq_GET(args->posonlyargs, i));
     231             :         } else {
     232         182 :             APPEND(arg, (arg_ty)asdl_seq_GET(args->args, i-posonlyarg_count));
     233             :         }
     234             : 
     235         294 :         di = i - posonlyarg_count - arg_count + default_count;
     236         294 :         if (di >= 0) {
     237         161 :             APPEND_STR("=");
     238         161 :             APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST);
     239             :         }
     240         294 :         if (posonlyarg_count && i + 1 == posonlyarg_count) {
     241          84 :             APPEND_STR(", /");
     242             :         }
     243             :     }
     244             : 
     245             :     /* vararg, or bare '*' if no varargs but keyword-only arguments present */
     246         154 :     if (args->vararg || asdl_seq_LEN(args->kwonlyargs)) {
     247          63 :         APPEND_STR_IF_NOT_FIRST(", ");
     248          63 :         APPEND_STR("*");
     249          63 :         if (args->vararg) {
     250          14 :             APPEND(arg, args->vararg);
     251             :         }
     252             :     }
     253             : 
     254             :     /* keyword-only arguments */
     255         154 :     arg_count = asdl_seq_LEN(args->kwonlyargs);
     256         154 :     default_count = asdl_seq_LEN(args->kw_defaults);
     257         252 :     for (i = 0; i < arg_count; i++) {
     258          98 :         APPEND_STR_IF_NOT_FIRST(", ");
     259          98 :         APPEND(arg, (arg_ty)asdl_seq_GET(args->kwonlyargs, i));
     260             : 
     261          98 :         di = i - arg_count + default_count;
     262          98 :         if (di >= 0) {
     263          98 :             expr_ty default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di);
     264          98 :             if (default_) {
     265          42 :                 APPEND_STR("=");
     266          42 :                 APPEND_EXPR(default_, PR_TEST);
     267             :             }
     268             :         }
     269             :     }
     270             : 
     271             :     /* **kwargs */
     272         154 :     if (args->kwarg) {
     273          21 :         APPEND_STR_IF_NOT_FIRST(", ");
     274          21 :         APPEND_STR("**");
     275          21 :         APPEND(arg, args->kwarg);
     276             :     }
     277             : 
     278         154 :     return 0;
     279             : }
     280             : 
     281             : static int
     282         154 : append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level)
     283             : {
     284         154 :     APPEND_STR_IF(level > PR_TEST, "(");
     285         154 :     Py_ssize_t n_positional = (asdl_seq_LEN(e->v.Lambda.args->args) +
     286         154 :                                asdl_seq_LEN(e->v.Lambda.args->posonlyargs));
     287         154 :     APPEND_STR(n_positional ? "lambda " : "lambda");
     288         154 :     APPEND(args, e->v.Lambda.args);
     289         154 :     APPEND_STR(": ");
     290         154 :     APPEND_EXPR(e->v.Lambda.body, PR_TEST);
     291         154 :     APPEND_STR_IF(level > PR_TEST, ")");
     292         154 :     return 0;
     293             : }
     294             : 
     295             : static int
     296          91 : append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level)
     297             : {
     298          91 :     APPEND_STR_IF(level > PR_TEST, "(");
     299          91 :     APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1);
     300          91 :     APPEND_STR(" if ");
     301          91 :     APPEND_EXPR(e->v.IfExp.test, PR_TEST + 1);
     302          91 :     APPEND_STR(" else ");
     303          91 :     APPEND_EXPR(e->v.IfExp.orelse, PR_TEST);
     304          91 :     APPEND_STR_IF(level > PR_TEST, ")");
     305          91 :     return 0;
     306             : }
     307             : 
     308             : static int
     309          35 : append_ast_dict(_PyUnicodeWriter *writer, expr_ty e)
     310             : {
     311             :     Py_ssize_t i, value_count;
     312             :     expr_ty key_node;
     313             : 
     314          35 :     APPEND_STR("{");
     315          35 :     value_count = asdl_seq_LEN(e->v.Dict.values);
     316             : 
     317         105 :     for (i = 0; i < value_count; i++) {
     318          70 :         APPEND_STR_IF(i > 0, ", ");
     319          70 :         key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i);
     320          70 :         if (key_node != NULL) {
     321          42 :             APPEND_EXPR(key_node, PR_TEST);
     322          42 :             APPEND_STR(": ");
     323          42 :             APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_TEST);
     324             :         }
     325             :         else {
     326          28 :             APPEND_STR("**");
     327          28 :             APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_EXPR);
     328             :         }
     329             :     }
     330             : 
     331          35 :     APPEND_STR_FINISH("}");
     332             : }
     333             : 
     334             : static int
     335          14 : append_ast_set(_PyUnicodeWriter *writer, expr_ty e)
     336             : {
     337             :     Py_ssize_t i, elem_count;
     338             : 
     339          14 :     APPEND_STR("{");
     340          14 :     elem_count = asdl_seq_LEN(e->v.Set.elts);
     341          77 :     for (i = 0; i < elem_count; i++) {
     342          63 :         APPEND_STR_IF(i > 0, ", ");
     343          63 :         APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST);
     344             :     }
     345             : 
     346          14 :     APPEND_STR_FINISH("}");
     347             : }
     348             : 
     349             : static int
     350          25 : append_ast_list(_PyUnicodeWriter *writer, expr_ty e)
     351             : {
     352             :     Py_ssize_t i, elem_count;
     353             : 
     354          25 :     APPEND_STR("[");
     355          25 :     elem_count = asdl_seq_LEN(e->v.List.elts);
     356         134 :     for (i = 0; i < elem_count; i++) {
     357         109 :         APPEND_STR_IF(i > 0, ", ");
     358         109 :         APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST);
     359             :     }
     360             : 
     361          25 :     APPEND_STR_FINISH("]");
     362             : }
     363             : 
     364             : static int
     365         600 : append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level)
     366             : {
     367             :     Py_ssize_t i, elem_count;
     368             : 
     369         600 :     elem_count = asdl_seq_LEN(e->v.Tuple.elts);
     370             : 
     371         600 :     if (elem_count == 0) {
     372          21 :         APPEND_STR_FINISH("()");
     373             :     }
     374             : 
     375         579 :     APPEND_STR_IF(level > PR_TUPLE, "(");
     376             : 
     377        1934 :     for (i = 0; i < elem_count; i++) {
     378        1355 :         APPEND_STR_IF(i > 0, ", ");
     379        1355 :         APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Tuple.elts, i), PR_TEST);
     380             :     }
     381             : 
     382         579 :     APPEND_STR_IF(elem_count == 1, ",");
     383         579 :     APPEND_STR_IF(level > PR_TUPLE, ")");
     384         579 :     return 0;
     385             : }
     386             : 
     387             : static int
     388         182 : append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen)
     389             : {
     390             :     Py_ssize_t i, if_count;
     391             : 
     392         182 :     APPEND_STR(gen->is_async ? " async for " : " for ");
     393         182 :     APPEND_EXPR(gen->target, PR_TUPLE);
     394         182 :     APPEND_STR(" in ");
     395         182 :     APPEND_EXPR(gen->iter, PR_TEST + 1);
     396             : 
     397         182 :     if_count = asdl_seq_LEN(gen->ifs);
     398         189 :     for (i = 0; i < if_count; i++) {
     399           7 :         APPEND_STR(" if ");
     400           7 :         APPEND_EXPR((expr_ty)asdl_seq_GET(gen->ifs, i), PR_TEST + 1);
     401             :     }
     402         182 :     return 0;
     403             : }
     404             : 
     405             : static int
     406         161 : append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_comprehension_seq *comprehensions)
     407             : {
     408             :     Py_ssize_t i, gen_count;
     409         161 :     gen_count = asdl_seq_LEN(comprehensions);
     410             : 
     411         343 :     for (i = 0; i < gen_count; i++) {
     412         182 :         APPEND(comprehension, (comprehension_ty)asdl_seq_GET(comprehensions, i));
     413             :     }
     414             : 
     415         161 :     return 0;
     416             : }
     417             : 
     418             : static int
     419          56 : append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e)
     420             : {
     421          56 :     APPEND_STR("(");
     422          56 :     APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST);
     423          56 :     APPEND(comprehensions, e->v.GeneratorExp.generators);
     424          56 :     APPEND_STR_FINISH(")");
     425             : }
     426             : 
     427             : static int
     428          56 : append_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e)
     429             : {
     430          56 :     APPEND_STR("[");
     431          56 :     APPEND_EXPR(e->v.ListComp.elt, PR_TEST);
     432          56 :     APPEND(comprehensions, e->v.ListComp.generators);
     433          56 :     APPEND_STR_FINISH("]");
     434             : }
     435             : 
     436             : static int
     437          35 : append_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e)
     438             : {
     439          35 :     APPEND_STR("{");
     440          35 :     APPEND_EXPR(e->v.SetComp.elt, PR_TEST);
     441          35 :     APPEND(comprehensions, e->v.SetComp.generators);
     442          35 :     APPEND_STR_FINISH("}");
     443             : }
     444             : 
     445             : static int
     446          14 : append_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e)
     447             : {
     448          14 :     APPEND_STR("{");
     449          14 :     APPEND_EXPR(e->v.DictComp.key, PR_TEST);
     450          14 :     APPEND_STR(": ");
     451          14 :     APPEND_EXPR(e->v.DictComp.value, PR_TEST);
     452          14 :     APPEND(comprehensions, e->v.DictComp.generators);
     453          14 :     APPEND_STR_FINISH("}");
     454             : }
     455             : 
     456             : static int
     457          35 : append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level)
     458             : {
     459             :     const char *op;
     460             :     Py_ssize_t i, comparator_count;
     461             :     asdl_expr_seq *comparators;
     462             :     asdl_int_seq *ops;
     463             : 
     464          35 :     APPEND_STR_IF(level > PR_CMP, "(");
     465             : 
     466          35 :     comparators = e->v.Compare.comparators;
     467          35 :     ops = e->v.Compare.ops;
     468          35 :     comparator_count = asdl_seq_LEN(comparators);
     469          35 :     assert(comparator_count > 0);
     470          35 :     assert(comparator_count == asdl_seq_LEN(ops));
     471             : 
     472          35 :     APPEND_EXPR(e->v.Compare.left, PR_CMP + 1);
     473             : 
     474          77 :     for (i = 0; i < comparator_count; i++) {
     475          42 :         switch ((cmpop_ty)asdl_seq_GET(ops, i)) {
     476           0 :         case Eq:
     477           0 :             op = " == ";
     478           0 :             break;
     479           0 :         case NotEq:
     480           0 :             op = " != ";
     481           0 :             break;
     482           0 :         case Lt:
     483           0 :             op = " < ";
     484           0 :             break;
     485           0 :         case LtE:
     486           0 :             op = " <= ";
     487           0 :             break;
     488          35 :         case Gt:
     489          35 :             op = " > ";
     490          35 :             break;
     491           0 :         case GtE:
     492           0 :             op = " >= ";
     493           0 :             break;
     494           7 :         case Is:
     495           7 :             op = " is ";
     496           7 :             break;
     497           0 :         case IsNot:
     498           0 :             op = " is not ";
     499           0 :             break;
     500           0 :         case In:
     501           0 :             op = " in ";
     502           0 :             break;
     503           0 :         case NotIn:
     504           0 :             op = " not in ";
     505           0 :             break;
     506           0 :         default:
     507           0 :             PyErr_SetString(PyExc_SystemError,
     508             :                             "unexpected comparison kind");
     509           0 :             return -1;
     510             :         }
     511             : 
     512          42 :         APPEND_STR(op);
     513          42 :         APPEND_EXPR((expr_ty)asdl_seq_GET(comparators, i), PR_CMP + 1);
     514             :     }
     515             : 
     516          35 :     APPEND_STR_IF(level > PR_CMP, ")");
     517          35 :     return 0;
     518             : }
     519             : 
     520             : static int
     521          42 : append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw)
     522             : {
     523          42 :     if (kw->arg == NULL) {
     524           7 :         APPEND_STR("**");
     525             :     }
     526             :     else {
     527          35 :         if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) {
     528           0 :             return -1;
     529             :         }
     530             : 
     531          35 :         APPEND_STR("=");
     532             :     }
     533             : 
     534          42 :     APPEND_EXPR(kw->value, PR_TEST);
     535          42 :     return 0;
     536             : }
     537             : 
     538             : static int
     539          77 : append_ast_call(_PyUnicodeWriter *writer, expr_ty e)
     540             : {
     541             :     bool first;
     542             :     Py_ssize_t i, arg_count, kw_count;
     543             :     expr_ty expr;
     544             : 
     545          77 :     APPEND_EXPR(e->v.Call.func, PR_ATOM);
     546             : 
     547          77 :     arg_count = asdl_seq_LEN(e->v.Call.args);
     548          77 :     kw_count = asdl_seq_LEN(e->v.Call.keywords);
     549          77 :     if (arg_count == 1 && kw_count == 0) {
     550          21 :         expr = (expr_ty)asdl_seq_GET(e->v.Call.args, 0);
     551          21 :         if (expr->kind == GeneratorExp_kind) {
     552             :             /* Special case: a single generator expression. */
     553           7 :             return append_ast_genexp(writer, expr);
     554             :         }
     555             :     }
     556             : 
     557          70 :     APPEND_STR("(");
     558             : 
     559          70 :     first = true;
     560         154 :     for (i = 0; i < arg_count; i++) {
     561          84 :         APPEND_STR_IF_NOT_FIRST(", ");
     562          84 :         APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Call.args, i), PR_TEST);
     563             :     }
     564             : 
     565         112 :     for (i = 0; i < kw_count; i++) {
     566          42 :         APPEND_STR_IF_NOT_FIRST(", ");
     567          42 :         APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i));
     568             :     }
     569             : 
     570          70 :     APPEND_STR_FINISH(")");
     571             : }
     572             : 
     573             : static PyObject *
     574         119 : escape_braces(PyObject *orig)
     575             : {
     576             :     PyObject *temp;
     577             :     PyObject *result;
     578         119 :     temp = PyUnicode_Replace(orig, &_Py_STR(open_br), &_Py_STR(dbl_open_br), -1);
     579         119 :     if (!temp) {
     580           0 :         return NULL;
     581             :     }
     582         119 :     result = PyUnicode_Replace(temp, &_Py_STR(close_br), &_Py_STR(dbl_close_br), -1);
     583         119 :     Py_DECREF(temp);
     584         119 :     return result;
     585             : }
     586             : 
     587             : static int
     588         119 : append_fstring_unicode(_PyUnicodeWriter *writer, PyObject *unicode)
     589             : {
     590             :     PyObject *escaped;
     591         119 :     int result = -1;
     592         119 :     escaped = escape_braces(unicode);
     593         119 :     if (escaped) {
     594         119 :         result = _PyUnicodeWriter_WriteStr(writer, escaped);
     595         119 :         Py_DECREF(escaped);
     596             :     }
     597         119 :     return result;
     598             : }
     599             : 
     600             : static int
     601         266 : append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
     602             : {
     603         266 :     switch (e->kind) {
     604         119 :     case Constant_kind:
     605         119 :         return append_fstring_unicode(writer, e->v.Constant.value);
     606          28 :     case JoinedStr_kind:
     607          28 :         return append_joinedstr(writer, e, is_format_spec);
     608         119 :     case FormattedValue_kind:
     609         119 :         return append_formattedvalue(writer, e);
     610           0 :     default:
     611           0 :         PyErr_SetString(PyExc_SystemError,
     612             :                         "unknown expression kind inside f-string");
     613           0 :         return -1;
     614             :     }
     615             : }
     616             : 
     617             : /* Build body separately to enable wrapping the entire stream of Strs,
     618             :    Constants and FormattedValues in one opening and one closing quote. */
     619             : static PyObject *
     620         147 : build_fstring_body(asdl_expr_seq *values, bool is_format_spec)
     621             : {
     622             :     Py_ssize_t i, value_count;
     623             :     _PyUnicodeWriter body_writer;
     624         147 :     _PyUnicodeWriter_Init(&body_writer);
     625         147 :     body_writer.min_length = 256;
     626         147 :     body_writer.overallocate = 1;
     627             : 
     628         147 :     value_count = asdl_seq_LEN(values);
     629         385 :     for (i = 0; i < value_count; ++i) {
     630         238 :         if (-1 == append_fstring_element(&body_writer,
     631         238 :                                          (expr_ty)asdl_seq_GET(values, i),
     632             :                                          is_format_spec
     633             :                                          )) {
     634           0 :             _PyUnicodeWriter_Dealloc(&body_writer);
     635           0 :             return NULL;
     636             :         }
     637             :     }
     638             : 
     639         147 :     return _PyUnicodeWriter_Finish(&body_writer);
     640             : }
     641             : 
     642             : static int
     643         147 : append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
     644             : {
     645         147 :     int result = -1;
     646         147 :     PyObject *body = build_fstring_body(e->v.JoinedStr.values, is_format_spec);
     647         147 :     if (!body) {
     648           0 :         return -1;
     649             :     }
     650             : 
     651         147 :     if (!is_format_spec) {
     652         238 :         if (-1 != append_charp(writer, "f") &&
     653         119 :             -1 != append_repr(writer, body))
     654             :         {
     655         119 :             result = 0;
     656             :         }
     657             :     }
     658             :     else {
     659          28 :         result = _PyUnicodeWriter_WriteStr(writer, body);
     660             :     }
     661         147 :     Py_DECREF(body);
     662         147 :     return result;
     663             : }
     664             : 
     665             : static int
     666         119 : append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e)
     667             : {
     668             :     const char *conversion;
     669         119 :     const char *outer_brace = "{";
     670             :     /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis
     671             :        around a lambda with ':' */
     672         119 :     PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, PR_TEST + 1);
     673         119 :     if (!temp_fv_str) {
     674           0 :         return -1;
     675             :     }
     676         119 :     if (PyUnicode_Find(temp_fv_str, &_Py_STR(open_br), 0, 1, 1) == 0) {
     677             :         /* Expression starts with a brace, split it with a space from the outer
     678             :            one. */
     679           7 :         outer_brace = "{ ";
     680             :     }
     681         119 :     if (-1 == append_charp(writer, outer_brace)) {
     682           0 :         Py_DECREF(temp_fv_str);
     683           0 :         return -1;
     684             :     }
     685         119 :     if (-1 == _PyUnicodeWriter_WriteStr(writer, temp_fv_str)) {
     686           0 :         Py_DECREF(temp_fv_str);
     687           0 :         return -1;
     688             :     }
     689         119 :     Py_DECREF(temp_fv_str);
     690             : 
     691         119 :     if (e->v.FormattedValue.conversion > 0) {
     692          49 :         switch (e->v.FormattedValue.conversion) {
     693          14 :         case 'a':
     694          14 :             conversion = "!a";
     695          14 :             break;
     696          28 :         case 'r':
     697          28 :             conversion = "!r";
     698          28 :             break;
     699           7 :         case 's':
     700           7 :             conversion = "!s";
     701           7 :             break;
     702           0 :         default:
     703           0 :             PyErr_SetString(PyExc_SystemError,
     704             :                             "unknown f-value conversion kind");
     705           0 :             return -1;
     706             :         }
     707          49 :         APPEND_STR(conversion);
     708             :     }
     709         119 :     if (e->v.FormattedValue.format_spec) {
     710          56 :         if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) ||
     711          28 :             -1 == append_fstring_element(writer,
     712             :                                          e->v.FormattedValue.format_spec,
     713             :                                          true
     714             :                                         ))
     715             :         {
     716           0 :             return -1;
     717             :         }
     718             :     }
     719             : 
     720         119 :     APPEND_STR_FINISH("}");
     721             : }
     722             : 
     723             : static int
     724        2988 : append_ast_constant(_PyUnicodeWriter *writer, PyObject *constant)
     725             : {
     726        2988 :     if (PyTuple_CheckExact(constant)) {
     727             :         Py_ssize_t i, elem_count;
     728             : 
     729           0 :         elem_count = PyTuple_GET_SIZE(constant);
     730           0 :         APPEND_STR("(");
     731           0 :         for (i = 0; i < elem_count; i++) {
     732           0 :             APPEND_STR_IF(i > 0, ", ");
     733           0 :             if (append_ast_constant(writer, PyTuple_GET_ITEM(constant, i)) < 0) {
     734           0 :                 return -1;
     735             :             }
     736             :         }
     737             : 
     738           0 :         APPEND_STR_IF(elem_count == 1, ",");
     739           0 :         APPEND_STR(")");
     740           0 :         return 0;
     741             :     }
     742        2988 :     return append_repr(writer, constant);
     743             : }
     744             : 
     745             : static int
     746          63 : append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)
     747             : {
     748             :     const char *period;
     749          63 :     expr_ty v = e->v.Attribute.value;
     750          63 :     APPEND_EXPR(v, PR_ATOM);
     751             : 
     752             :     /* Special case: integers require a space for attribute access to be
     753             :        unambiguous. */
     754          63 :     if (v->kind == Constant_kind && PyLong_CheckExact(v->v.Constant.value)) {
     755           7 :         period = " .";
     756             :     }
     757             :     else {
     758          56 :         period = ".";
     759             :     }
     760          63 :     APPEND_STR(period);
     761             : 
     762          63 :     return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr);
     763             : }
     764             : 
     765             : static int
     766         119 : append_ast_slice(_PyUnicodeWriter *writer, expr_ty e)
     767             : {
     768         119 :     if (e->v.Slice.lower) {
     769          91 :         APPEND_EXPR(e->v.Slice.lower, PR_TEST);
     770             :     }
     771             : 
     772         119 :     APPEND_STR(":");
     773             : 
     774         119 :     if (e->v.Slice.upper) {
     775          91 :         APPEND_EXPR(e->v.Slice.upper, PR_TEST);
     776             :     }
     777             : 
     778         119 :     if (e->v.Slice.step) {
     779          28 :         APPEND_STR(":");
     780          28 :         APPEND_EXPR(e->v.Slice.step, PR_TEST);
     781             :     }
     782         119 :     return 0;
     783             : }
     784             : 
     785             : static int
     786         546 : append_ast_subscript(_PyUnicodeWriter *writer, expr_ty e)
     787             : {
     788         546 :     APPEND_EXPR(e->v.Subscript.value, PR_ATOM);
     789         546 :     APPEND_STR("[");
     790         546 :     APPEND_EXPR(e->v.Subscript.slice, PR_TUPLE);
     791         546 :     APPEND_STR_FINISH("]");
     792             : }
     793             : 
     794             : static int
     795         204 : append_ast_starred(_PyUnicodeWriter *writer, expr_ty e)
     796             : {
     797         204 :     APPEND_STR("*");
     798         204 :     APPEND_EXPR(e->v.Starred.value, PR_EXPR);
     799         204 :     return 0;
     800             : }
     801             : 
     802             : static int
     803           0 : append_ast_yield(_PyUnicodeWriter *writer, expr_ty e)
     804             : {
     805           0 :     if (!e->v.Yield.value) {
     806           0 :         APPEND_STR_FINISH("(yield)");
     807             :     }
     808             : 
     809           0 :     APPEND_STR("(yield ");
     810           0 :     APPEND_EXPR(e->v.Yield.value, PR_TEST);
     811           0 :     APPEND_STR_FINISH(")");
     812             : }
     813             : 
     814             : static int
     815           0 : append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e)
     816             : {
     817           0 :     APPEND_STR("(yield from ");
     818           0 :     APPEND_EXPR(e->v.YieldFrom.value, PR_TEST);
     819           0 :     APPEND_STR_FINISH(")");
     820             : }
     821             : 
     822             : static int
     823           0 : append_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level)
     824             : {
     825           0 :     APPEND_STR_IF(level > PR_AWAIT, "(");
     826           0 :     APPEND_STR("await ");
     827           0 :     APPEND_EXPR(e->v.Await.value, PR_ATOM);
     828           0 :     APPEND_STR_IF(level > PR_AWAIT, ")");
     829           0 :     return 0;
     830             : }
     831             : 
     832             : static int
     833           0 : append_named_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
     834             : {
     835           0 :     APPEND_STR_IF(level > PR_TUPLE, "(");
     836           0 :     APPEND_EXPR(e->v.NamedExpr.target, PR_ATOM);
     837           0 :     APPEND_STR(" := ");
     838           0 :     APPEND_EXPR(e->v.NamedExpr.value, PR_ATOM);
     839           0 :     APPEND_STR_IF(level > PR_TUPLE, ")");
     840           0 :     return 0;
     841             : }
     842             : 
     843             : static int
     844       11440 : append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
     845             : {
     846       11440 :     switch (e->kind) {
     847         224 :     case BoolOp_kind:
     848         224 :         return append_ast_boolop(writer, e, level);
     849        1274 :     case BinOp_kind:
     850        1274 :         return append_ast_binop(writer, e, level);
     851         126 :     case UnaryOp_kind:
     852         126 :         return append_ast_unaryop(writer, e, level);
     853         154 :     case Lambda_kind:
     854         154 :         return append_ast_lambda(writer, e, level);
     855          91 :     case IfExp_kind:
     856          91 :         return append_ast_ifexp(writer, e, level);
     857          35 :     case Dict_kind:
     858          35 :         return append_ast_dict(writer, e);
     859          14 :     case Set_kind:
     860          14 :         return append_ast_set(writer, e);
     861          49 :     case GeneratorExp_kind:
     862          49 :         return append_ast_genexp(writer, e);
     863          56 :     case ListComp_kind:
     864          56 :         return append_ast_listcomp(writer, e);
     865          35 :     case SetComp_kind:
     866          35 :         return append_ast_setcomp(writer, e);
     867          14 :     case DictComp_kind:
     868          14 :         return append_ast_dictcomp(writer, e);
     869           0 :     case Yield_kind:
     870           0 :         return append_ast_yield(writer, e);
     871           0 :     case YieldFrom_kind:
     872           0 :         return append_ast_yield_from(writer, e);
     873           0 :     case Await_kind:
     874           0 :         return append_ast_await(writer, e, level);
     875          35 :     case Compare_kind:
     876          35 :         return append_ast_compare(writer, e, level);
     877          77 :     case Call_kind:
     878          77 :         return append_ast_call(writer, e);
     879        3009 :     case Constant_kind:
     880        3009 :         if (e->v.Constant.value == Py_Ellipsis) {
     881          21 :             APPEND_STR_FINISH("...");
     882             :         }
     883        2988 :         if (e->v.Constant.kind != NULL
     884           7 :             && -1 == _PyUnicodeWriter_WriteStr(writer, e->v.Constant.kind)) {
     885           0 :             return -1;
     886             :         }
     887        2988 :         return append_ast_constant(writer, e->v.Constant.value);
     888         119 :     case JoinedStr_kind:
     889         119 :         return append_joinedstr(writer, e, false);
     890           0 :     case FormattedValue_kind:
     891           0 :         return append_formattedvalue(writer, e);
     892             :     /* The following exprs can be assignment targets. */
     893          63 :     case Attribute_kind:
     894          63 :         return append_ast_attribute(writer, e);
     895         546 :     case Subscript_kind:
     896         546 :         return append_ast_subscript(writer, e);
     897         204 :     case Starred_kind:
     898         204 :         return append_ast_starred(writer, e);
     899         119 :     case Slice_kind:
     900         119 :         return append_ast_slice(writer, e);
     901        4571 :     case Name_kind:
     902        4571 :         return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id);
     903          25 :     case List_kind:
     904          25 :         return append_ast_list(writer, e);
     905         600 :     case Tuple_kind:
     906         600 :         return append_ast_tuple(writer, e, level);
     907           0 :     case NamedExpr_kind:
     908           0 :         return append_named_expr(writer, e, level);
     909             :     // No default so compiler emits a warning for unhandled cases
     910             :     }
     911           0 :     PyErr_SetString(PyExc_SystemError,
     912             :                     "unknown expression kind");
     913           0 :     return -1;
     914             : }
     915             : 
     916             : static int
     917        3612 : maybe_init_static_strings(void)
     918             : {
     919        3612 :     if (!_str_replace_inf &&
     920           9 :         !(_str_replace_inf = PyUnicode_FromFormat("1e%d", 1 + DBL_MAX_10_EXP))) {
     921           0 :         return -1;
     922             :     }
     923        3612 :     return 0;
     924             : }
     925             : 
     926             : static PyObject *
     927        3612 : expr_as_unicode(expr_ty e, int level)
     928             : {
     929             :     _PyUnicodeWriter writer;
     930        3612 :     _PyUnicodeWriter_Init(&writer);
     931        3612 :     writer.min_length = 256;
     932        3612 :     writer.overallocate = 1;
     933        7224 :     if (-1 == maybe_init_static_strings() ||
     934        3612 :         -1 == append_ast_expr(&writer, e, level))
     935             :     {
     936           0 :         _PyUnicodeWriter_Dealloc(&writer);
     937           0 :         return NULL;
     938             :     }
     939        3612 :     return _PyUnicodeWriter_Finish(&writer);
     940             : }
     941             : 
     942             : PyObject *
     943        3493 : _PyAST_ExprAsUnicode(expr_ty e)
     944             : {
     945        3493 :     return expr_as_unicode(e, PR_TEST);
     946             : }

Generated by: LCOV version 1.14