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