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