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