/src/cpython3/Python/ast_preprocess.c
Line | Count | Source |
1 | | /* AST pre-processing */ |
2 | | #include "Python.h" |
3 | | #include "pycore_ast.h" // _PyAST_GetDocString() |
4 | | #include "pycore_c_array.h" // _Py_CArray_EnsureCapacity() |
5 | | #include "pycore_format.h" // F_LJUST |
6 | | #include "pycore_runtime.h" // _Py_STR() |
7 | | #include "pycore_unicodeobject.h" // _PyUnicode_EqualToASCIIString() |
8 | | |
9 | | |
10 | | /* See PEP 765 */ |
11 | | typedef struct { |
12 | | bool in_finally; |
13 | | bool in_funcdef; |
14 | | bool in_loop; |
15 | | } ControlFlowInFinallyContext; |
16 | | |
17 | | typedef struct { |
18 | | PyObject *filename; |
19 | | int optimize; |
20 | | int ff_features; |
21 | | int syntax_check_only; |
22 | | |
23 | | _Py_c_array_t cf_finally; /* context for PEP 765 check */ |
24 | | int cf_finally_used; |
25 | | } _PyASTPreprocessState; |
26 | | |
27 | 2.18M | #define ENTER_RECURSIVE() \ |
28 | 2.18M | if (Py_EnterRecursiveCall(" during compilation")) { \ |
29 | 0 | return 0; \ |
30 | 0 | } |
31 | | |
32 | 2.18M | #define LEAVE_RECURSIVE() Py_LeaveRecursiveCall(); |
33 | | |
34 | | static ControlFlowInFinallyContext* |
35 | | get_cf_finally_top(_PyASTPreprocessState *state) |
36 | 9.74k | { |
37 | 9.74k | int idx = state->cf_finally_used; |
38 | 9.74k | return ((ControlFlowInFinallyContext*)state->cf_finally.array) + idx; |
39 | 9.74k | } |
40 | | |
41 | | static int |
42 | | push_cf_context(_PyASTPreprocessState *state, stmt_ty node, bool finally, bool funcdef, bool loop) |
43 | 9.11k | { |
44 | 9.11k | if (_Py_CArray_EnsureCapacity(&state->cf_finally, state->cf_finally_used+1) < 0) { |
45 | 0 | return 0; |
46 | 0 | } |
47 | | |
48 | 9.11k | state->cf_finally_used++; |
49 | 9.11k | ControlFlowInFinallyContext *ctx = get_cf_finally_top(state); |
50 | | |
51 | 9.11k | ctx->in_finally = finally; |
52 | 9.11k | ctx->in_funcdef = funcdef; |
53 | 9.11k | ctx->in_loop = loop; |
54 | 9.11k | return 1; |
55 | 9.11k | } |
56 | | |
57 | | static void |
58 | | pop_cf_context(_PyASTPreprocessState *state) |
59 | 9.11k | { |
60 | 9.11k | assert(state->cf_finally_used > 0); |
61 | 9.11k | state->cf_finally_used--; |
62 | 9.11k | } |
63 | | |
64 | | static int |
65 | | control_flow_in_finally_warning(const char *kw, stmt_ty n, _PyASTPreprocessState *state) |
66 | 134 | { |
67 | 134 | PyObject *msg = PyUnicode_FromFormat("'%s' in a 'finally' block", kw); |
68 | 134 | if (msg == NULL) { |
69 | 0 | return 0; |
70 | 0 | } |
71 | 134 | int ret = _PyErr_EmitSyntaxWarning(msg, state->filename, n->lineno, |
72 | 134 | n->col_offset + 1, n->end_lineno, |
73 | 134 | n->end_col_offset + 1); |
74 | 134 | Py_DECREF(msg); |
75 | 134 | return ret < 0 ? 0 : 1; |
76 | 134 | } |
77 | | |
78 | | static int |
79 | | before_return(_PyASTPreprocessState *state, stmt_ty node_) |
80 | 292 | { |
81 | 292 | if (state->cf_finally_used > 0) { |
82 | 215 | ControlFlowInFinallyContext *ctx = get_cf_finally_top(state); |
83 | 215 | if (ctx->in_finally && ! ctx->in_funcdef) { |
84 | 26 | if (!control_flow_in_finally_warning("return", node_, state)) { |
85 | 0 | return 0; |
86 | 0 | } |
87 | 26 | } |
88 | 215 | } |
89 | 292 | return 1; |
90 | 292 | } |
91 | | |
92 | | static int |
93 | | before_loop_exit(_PyASTPreprocessState *state, stmt_ty node_, const char *kw) |
94 | 630 | { |
95 | 630 | if (state->cf_finally_used > 0) { |
96 | 415 | ControlFlowInFinallyContext *ctx = get_cf_finally_top(state); |
97 | 415 | if (ctx->in_finally && ! ctx->in_loop) { |
98 | 108 | if (!control_flow_in_finally_warning(kw, node_, state)) { |
99 | 0 | return 0; |
100 | 0 | } |
101 | 108 | } |
102 | 415 | } |
103 | 630 | return 1; |
104 | 630 | } |
105 | | |
106 | | #define PUSH_CONTEXT(S, N, FINALLY, FUNCDEF, LOOP) \ |
107 | 9.11k | if (!push_cf_context((S), (N), (FINALLY), (FUNCDEF), (LOOP))) { \ |
108 | 0 | return 0; \ |
109 | 0 | } |
110 | | |
111 | 9.11k | #define POP_CONTEXT(S) pop_cf_context(S) |
112 | | |
113 | 1.98k | #define BEFORE_FINALLY(S, N) PUSH_CONTEXT((S), (N), true, false, false) |
114 | 1.98k | #define AFTER_FINALLY(S) POP_CONTEXT(S) |
115 | 6.08k | #define BEFORE_FUNC_BODY(S, N) PUSH_CONTEXT((S), (N), false, true, false) |
116 | 6.08k | #define AFTER_FUNC_BODY(S) POP_CONTEXT(S) |
117 | 1.05k | #define BEFORE_LOOP_BODY(S, N) PUSH_CONTEXT((S), (N), false, false, true) |
118 | 1.05k | #define AFTER_LOOP_BODY(S) POP_CONTEXT(S) |
119 | | |
120 | | #define BEFORE_RETURN(S, N) \ |
121 | 292 | if (!before_return((S), (N))) { \ |
122 | 0 | return 0; \ |
123 | 0 | } |
124 | | |
125 | | #define BEFORE_LOOP_EXIT(S, N, KW) \ |
126 | 630 | if (!before_loop_exit((S), (N), (KW))) { \ |
127 | 0 | return 0; \ |
128 | 0 | } |
129 | | |
130 | | static int |
131 | | make_const(expr_ty node, PyObject *val, PyArena *arena) |
132 | 812 | { |
133 | | // Even if no new value was calculated, make_const may still |
134 | | // need to clear an error (e.g. for division by zero) |
135 | 812 | if (val == NULL) { |
136 | 0 | if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { |
137 | 0 | return 0; |
138 | 0 | } |
139 | 0 | PyErr_Clear(); |
140 | 0 | return 1; |
141 | 0 | } |
142 | 812 | if (_PyArena_AddPyObject(arena, val) < 0) { |
143 | 0 | Py_DECREF(val); |
144 | 0 | return 0; |
145 | 0 | } |
146 | 812 | node->kind = Constant_kind; |
147 | 812 | node->v.Constant.kind = NULL; |
148 | 812 | node->v.Constant.value = val; |
149 | 812 | return 1; |
150 | 812 | } |
151 | | |
152 | 1.80k | #define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr))) |
153 | | |
154 | | static int |
155 | | has_starred(asdl_expr_seq *elts) |
156 | 10.0k | { |
157 | 10.0k | Py_ssize_t n = asdl_seq_LEN(elts); |
158 | 20.7k | for (Py_ssize_t i = 0; i < n; i++) { |
159 | 10.9k | expr_ty e = (expr_ty)asdl_seq_GET(elts, i); |
160 | 10.9k | if (e->kind == Starred_kind) { |
161 | 216 | return 1; |
162 | 216 | } |
163 | 10.9k | } |
164 | 9.85k | return 0; |
165 | 10.0k | } |
166 | | |
167 | | static expr_ty |
168 | | parse_literal(PyObject *fmt, Py_ssize_t *ppos, PyArena *arena) |
169 | 12.9k | { |
170 | 12.9k | const void *data = PyUnicode_DATA(fmt); |
171 | 12.9k | int kind = PyUnicode_KIND(fmt); |
172 | 12.9k | Py_ssize_t size = PyUnicode_GET_LENGTH(fmt); |
173 | 12.9k | Py_ssize_t start, pos; |
174 | 12.9k | int has_percents = 0; |
175 | 12.9k | start = pos = *ppos; |
176 | 239k | while (pos < size) { |
177 | 236k | if (PyUnicode_READ(kind, data, pos) != '%') { |
178 | 213k | pos++; |
179 | 213k | } |
180 | 22.2k | else if (pos+1 < size && PyUnicode_READ(kind, data, pos+1) == '%') { |
181 | 12.4k | has_percents = 1; |
182 | 12.4k | pos += 2; |
183 | 12.4k | } |
184 | 9.73k | else { |
185 | 9.73k | break; |
186 | 9.73k | } |
187 | 236k | } |
188 | 12.9k | *ppos = pos; |
189 | 12.9k | if (pos == start) { |
190 | 2.48k | return NULL; |
191 | 2.48k | } |
192 | 10.5k | PyObject *str = PyUnicode_Substring(fmt, start, pos); |
193 | | /* str = str.replace('%%', '%') */ |
194 | 10.5k | if (str && has_percents) { |
195 | 3.95k | _Py_DECLARE_STR(dbl_percent, "%%"); |
196 | 3.95k | Py_SETREF(str, PyUnicode_Replace(str, &_Py_STR(dbl_percent), |
197 | 3.95k | _Py_LATIN1_CHR('%'), -1)); |
198 | 3.95k | } |
199 | 10.5k | if (!str) { |
200 | 0 | return NULL; |
201 | 0 | } |
202 | | |
203 | 10.5k | if (_PyArena_AddPyObject(arena, str) < 0) { |
204 | 0 | Py_DECREF(str); |
205 | 0 | return NULL; |
206 | 0 | } |
207 | 10.5k | return _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena); |
208 | 10.5k | } |
209 | | |
210 | 10.9k | #define MAXDIGITS 3 |
211 | | |
212 | | static int |
213 | | simple_format_arg_parse(PyObject *fmt, Py_ssize_t *ppos, |
214 | | int *spec, int *flags, int *width, int *prec) |
215 | 8.16k | { |
216 | 8.16k | Py_ssize_t pos = *ppos, len = PyUnicode_GET_LENGTH(fmt); |
217 | 8.16k | Py_UCS4 ch; |
218 | | |
219 | 23.2k | #define NEXTC do { \ |
220 | 23.2k | if (pos >= len) { \ |
221 | 1.31k | return 0; \ |
222 | 1.31k | } \ |
223 | 23.2k | ch = PyUnicode_READ_CHAR(fmt, pos); \ |
224 | 21.9k | pos++; \ |
225 | 21.9k | } while (0) |
226 | | |
227 | 8.16k | *flags = 0; |
228 | 11.7k | while (1) { |
229 | 11.7k | NEXTC; |
230 | 10.9k | switch (ch) { |
231 | 771 | case '-': *flags |= F_LJUST; continue; |
232 | 469 | case '+': *flags |= F_SIGN; continue; |
233 | 120 | case ' ': *flags |= F_BLANK; continue; |
234 | 314 | case '#': *flags |= F_ALT; continue; |
235 | 1.86k | case '0': *flags |= F_ZERO; continue; |
236 | 10.9k | } |
237 | 7.40k | break; |
238 | 10.9k | } |
239 | 7.40k | if ('0' <= ch && ch <= '9') { |
240 | 3.96k | *width = 0; |
241 | 3.96k | int digits = 0; |
242 | 9.61k | while ('0' <= ch && ch <= '9') { |
243 | 6.16k | *width = *width * 10 + (ch - '0'); |
244 | 6.16k | NEXTC; |
245 | 5.78k | if (++digits >= MAXDIGITS) { |
246 | 130 | return 0; |
247 | 130 | } |
248 | 5.78k | } |
249 | 3.96k | } |
250 | | |
251 | 6.88k | if (ch == '.') { |
252 | 2.46k | NEXTC; |
253 | 2.36k | *prec = 0; |
254 | 2.36k | if ('0' <= ch && ch <= '9') { |
255 | 1.90k | int digits = 0; |
256 | 4.71k | while ('0' <= ch && ch <= '9') { |
257 | 2.90k | *prec = *prec * 10 + (ch - '0'); |
258 | 2.90k | NEXTC; |
259 | 2.84k | if (++digits >= MAXDIGITS) { |
260 | 30 | return 0; |
261 | 30 | } |
262 | 2.84k | } |
263 | 1.90k | } |
264 | 2.36k | } |
265 | 6.69k | *spec = ch; |
266 | 6.69k | *ppos = pos; |
267 | 6.69k | return 1; |
268 | | |
269 | 6.88k | #undef NEXTC |
270 | 6.88k | } |
271 | | |
272 | | static expr_ty |
273 | | parse_format(PyObject *fmt, Py_ssize_t *ppos, expr_ty arg, PyArena *arena) |
274 | 8.16k | { |
275 | 8.16k | int spec, flags, width = -1, prec = -1; |
276 | 8.16k | if (!simple_format_arg_parse(fmt, ppos, &spec, &flags, &width, &prec)) { |
277 | | // Unsupported format. |
278 | 1.47k | return NULL; |
279 | 1.47k | } |
280 | 6.69k | if (spec == 's' || spec == 'r' || spec == 'a') { |
281 | 3.13k | char buf[1 + MAXDIGITS + 1 + MAXDIGITS + 1], *p = buf; |
282 | 3.13k | if (!(flags & F_LJUST) && width > 0) { |
283 | 1.06k | *p++ = '>'; |
284 | 1.06k | } |
285 | 3.13k | if (width >= 0) { |
286 | 1.34k | p += snprintf(p, MAXDIGITS + 1, "%d", width); |
287 | 1.34k | } |
288 | 3.13k | if (prec >= 0) { |
289 | 971 | p += snprintf(p, MAXDIGITS + 2, ".%d", prec); |
290 | 971 | } |
291 | 3.13k | expr_ty format_spec = NULL; |
292 | 3.13k | if (p != buf) { |
293 | 1.38k | PyObject *str = PyUnicode_FromString(buf); |
294 | 1.38k | if (str == NULL) { |
295 | 0 | return NULL; |
296 | 0 | } |
297 | 1.38k | if (_PyArena_AddPyObject(arena, str) < 0) { |
298 | 0 | Py_DECREF(str); |
299 | 0 | return NULL; |
300 | 0 | } |
301 | 1.38k | format_spec = _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena); |
302 | 1.38k | if (format_spec == NULL) { |
303 | 0 | return NULL; |
304 | 0 | } |
305 | 1.38k | } |
306 | 3.13k | return _PyAST_FormattedValue(arg, spec, format_spec, |
307 | 3.13k | arg->lineno, arg->col_offset, |
308 | 3.13k | arg->end_lineno, arg->end_col_offset, |
309 | 3.13k | arena); |
310 | 3.13k | } |
311 | | // Unsupported format. |
312 | 3.55k | return NULL; |
313 | 6.69k | } |
314 | | |
315 | | static int |
316 | | optimize_format(expr_ty node, PyObject *fmt, asdl_expr_seq *elts, PyArena *arena) |
317 | 9.85k | { |
318 | 9.85k | Py_ssize_t pos = 0; |
319 | 9.85k | Py_ssize_t cnt = 0; |
320 | 9.85k | asdl_expr_seq *seq = _Py_asdl_expr_seq_new(asdl_seq_LEN(elts) * 2 + 1, arena); |
321 | 9.85k | if (!seq) { |
322 | 0 | return 0; |
323 | 0 | } |
324 | 9.85k | seq->size = 0; |
325 | | |
326 | 12.9k | while (1) { |
327 | 12.9k | expr_ty lit = parse_literal(fmt, &pos, arena); |
328 | 12.9k | if (lit) { |
329 | 10.5k | asdl_seq_SET(seq, seq->size++, lit); |
330 | 10.5k | } |
331 | 2.48k | else if (PyErr_Occurred()) { |
332 | 0 | return 0; |
333 | 0 | } |
334 | | |
335 | 12.9k | if (pos >= PyUnicode_GET_LENGTH(fmt)) { |
336 | 3.24k | break; |
337 | 3.24k | } |
338 | 9.73k | if (cnt >= asdl_seq_LEN(elts)) { |
339 | | // More format units than items. |
340 | 1.57k | return 1; |
341 | 1.57k | } |
342 | 9.73k | assert(PyUnicode_READ_CHAR(fmt, pos) == '%'); |
343 | 8.16k | pos++; |
344 | 8.16k | expr_ty expr = parse_format(fmt, &pos, asdl_seq_GET(elts, cnt), arena); |
345 | 8.16k | cnt++; |
346 | 8.16k | if (!expr) { |
347 | 5.03k | return !PyErr_Occurred(); |
348 | 5.03k | } |
349 | 3.13k | asdl_seq_SET(seq, seq->size++, expr); |
350 | 3.13k | } |
351 | 3.24k | if (cnt < asdl_seq_LEN(elts)) { |
352 | | // More items than format units. |
353 | 1.44k | return 1; |
354 | 1.44k | } |
355 | 1.80k | expr_ty res = _PyAST_JoinedStr(seq, |
356 | 1.80k | node->lineno, node->col_offset, |
357 | 1.80k | node->end_lineno, node->end_col_offset, |
358 | 1.80k | arena); |
359 | 1.80k | if (!res) { |
360 | 0 | return 0; |
361 | 0 | } |
362 | 1.80k | COPY_NODE(node, res); |
363 | | // PySys_FormatStderr("format = %R\n", fmt); |
364 | 1.80k | return 1; |
365 | 1.80k | } |
366 | | |
367 | | static int |
368 | | fold_binop(expr_ty node, PyArena *arena, _PyASTPreprocessState *state) |
369 | 508k | { |
370 | 508k | if (state->syntax_check_only) { |
371 | 4 | return 1; |
372 | 4 | } |
373 | 508k | expr_ty lhs, rhs; |
374 | 508k | lhs = node->v.BinOp.left; |
375 | 508k | rhs = node->v.BinOp.right; |
376 | 508k | if (lhs->kind != Constant_kind) { |
377 | 342k | return 1; |
378 | 342k | } |
379 | 166k | PyObject *lv = lhs->v.Constant.value; |
380 | | |
381 | 166k | if (node->v.BinOp.op == Mod && |
382 | 19.7k | rhs->kind == Tuple_kind && |
383 | 166k | PyUnicode_Check(lv) && |
384 | 10.0k | !has_starred(rhs->v.Tuple.elts)) |
385 | 9.85k | { |
386 | 9.85k | return optimize_format(node, lv, rhs->v.Tuple.elts, arena); |
387 | 9.85k | } |
388 | | |
389 | 156k | return 1; |
390 | 166k | } |
391 | | |
392 | | static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
393 | | static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
394 | | static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
395 | | static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
396 | | static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
397 | | static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
398 | | static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
399 | | static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
400 | | static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
401 | | static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
402 | | static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
403 | | static int astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTPreprocessState *state); |
404 | | |
405 | | #define CALL(FUNC, TYPE, ARG) \ |
406 | 2.14M | if (!FUNC((ARG), ctx_, state)) \ |
407 | 2.14M | return 0; |
408 | | |
409 | | #define CALL_OPT(FUNC, TYPE, ARG) \ |
410 | 126k | if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \ |
411 | 126k | return 0; |
412 | | |
413 | 288k | #define CALL_SEQ(FUNC, TYPE, ARG) { \ |
414 | 288k | Py_ssize_t i; \ |
415 | 288k | asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \ |
416 | 927k | for (i = 0; i < asdl_seq_LEN(seq); i++) { \ |
417 | 639k | TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ |
418 | 639k | if (elt != NULL && !FUNC(elt, ctx_, state)) \ |
419 | 639k | return 0; \ |
420 | 639k | } \ |
421 | 288k | } |
422 | | |
423 | | |
424 | | static int |
425 | | stmt_seq_remove_item(asdl_stmt_seq *stmts, Py_ssize_t idx) |
426 | 28 | { |
427 | 28 | if (idx >= asdl_seq_LEN(stmts)) { |
428 | 0 | return 0; |
429 | 0 | } |
430 | 297 | for (Py_ssize_t i = idx; i < asdl_seq_LEN(stmts) - 1; i++) { |
431 | 269 | stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, i+1); |
432 | 269 | asdl_seq_SET(stmts, i, st); |
433 | 269 | } |
434 | 28 | stmts->size--; |
435 | 28 | return 1; |
436 | 28 | } |
437 | | |
438 | | static int |
439 | | remove_docstring(asdl_stmt_seq *stmts, Py_ssize_t idx, PyArena *ctx_) |
440 | 75 | { |
441 | 75 | assert(_PyAST_GetDocString(stmts) != NULL); |
442 | | // In case there's just the docstring in the body, replace it with `pass` |
443 | | // keyword, so body won't be empty. |
444 | 75 | if (asdl_seq_LEN(stmts) == 1) { |
445 | 47 | stmt_ty docstring = (stmt_ty)asdl_seq_GET(stmts, 0); |
446 | 47 | stmt_ty pass = _PyAST_Pass( |
447 | 47 | docstring->lineno, docstring->col_offset, |
448 | | // we know that `pass` always takes 4 chars and a single line, |
449 | | // while docstring can span on multiple lines |
450 | 47 | docstring->lineno, docstring->col_offset + 4, |
451 | 47 | ctx_ |
452 | 47 | ); |
453 | 47 | if (pass == NULL) { |
454 | 0 | return 0; |
455 | 0 | } |
456 | 47 | asdl_seq_SET(stmts, 0, pass); |
457 | 47 | return 1; |
458 | 47 | } |
459 | | // In case there are more than 1 body items, just remove the docstring. |
460 | 28 | return stmt_seq_remove_item(stmts, idx); |
461 | 75 | } |
462 | | |
463 | | static int |
464 | | astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTPreprocessState *state) |
465 | 19.5k | { |
466 | 19.5k | int docstring = _PyAST_GetDocString(stmts) != NULL; |
467 | 19.5k | if (docstring && (state->optimize >= 2)) { |
468 | | /* remove the docstring */ |
469 | 75 | if (!remove_docstring(stmts, 0, ctx_)) { |
470 | 0 | return 0; |
471 | 0 | } |
472 | 75 | docstring = 0; |
473 | 75 | } |
474 | 19.5k | CALL_SEQ(astfold_stmt, stmt, stmts); |
475 | 19.5k | if (!docstring && _PyAST_GetDocString(stmts) != NULL) { |
476 | 15 | stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); |
477 | 15 | asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_); |
478 | 15 | if (!values) { |
479 | 0 | return 0; |
480 | 0 | } |
481 | 15 | asdl_seq_SET(values, 0, st->v.Expr.value); |
482 | 15 | expr_ty expr = _PyAST_JoinedStr(values, st->lineno, st->col_offset, |
483 | 15 | st->end_lineno, st->end_col_offset, |
484 | 15 | ctx_); |
485 | 15 | if (!expr) { |
486 | 0 | return 0; |
487 | 0 | } |
488 | 15 | st->v.Expr.value = expr; |
489 | 15 | } |
490 | 19.5k | return 1; |
491 | 19.5k | } |
492 | | |
493 | | static int |
494 | | astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
495 | 13.6k | { |
496 | 13.6k | switch (node_->kind) { |
497 | 8.17k | case Module_kind: |
498 | 8.17k | CALL(astfold_body, asdl_seq, node_->v.Module.body); |
499 | 8.17k | break; |
500 | 3.35k | case Interactive_kind: |
501 | 3.35k | CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body); |
502 | 3.35k | break; |
503 | 2.07k | case Expression_kind: |
504 | 2.07k | CALL(astfold_expr, expr_ty, node_->v.Expression.body); |
505 | 2.07k | break; |
506 | | // The following top level nodes don't participate in constant folding |
507 | 0 | case FunctionType_kind: |
508 | 0 | break; |
509 | | // No default case, so the compiler will emit a warning if new top level |
510 | | // compilation nodes are added without being handled here |
511 | 13.6k | } |
512 | 13.6k | return 1; |
513 | 13.6k | } |
514 | | |
515 | | static int |
516 | | astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
517 | 1.99M | { |
518 | 1.99M | ENTER_RECURSIVE(); |
519 | 1.99M | switch (node_->kind) { |
520 | 1.59k | case BoolOp_kind: |
521 | 1.59k | CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values); |
522 | 1.59k | break; |
523 | 508k | case BinOp_kind: |
524 | 508k | CALL(astfold_expr, expr_ty, node_->v.BinOp.left); |
525 | 508k | CALL(astfold_expr, expr_ty, node_->v.BinOp.right); |
526 | 508k | CALL(fold_binop, expr_ty, node_); |
527 | 508k | break; |
528 | 269k | case UnaryOp_kind: |
529 | 269k | CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand); |
530 | 269k | break; |
531 | 3.96k | case Lambda_kind: |
532 | 3.96k | CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args); |
533 | 3.96k | CALL(astfold_expr, expr_ty, node_->v.Lambda.body); |
534 | 3.96k | break; |
535 | 1.20k | case IfExp_kind: |
536 | 1.20k | CALL(astfold_expr, expr_ty, node_->v.IfExp.test); |
537 | 1.20k | CALL(astfold_expr, expr_ty, node_->v.IfExp.body); |
538 | 1.20k | CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse); |
539 | 1.20k | break; |
540 | 1.15k | case Dict_kind: |
541 | 1.15k | CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys); |
542 | 1.15k | CALL_SEQ(astfold_expr, expr, node_->v.Dict.values); |
543 | 1.15k | break; |
544 | 6.45k | case Set_kind: |
545 | 6.45k | CALL_SEQ(astfold_expr, expr, node_->v.Set.elts); |
546 | 6.45k | break; |
547 | 1.57k | case ListComp_kind: |
548 | 1.57k | CALL(astfold_expr, expr_ty, node_->v.ListComp.elt); |
549 | 1.57k | CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators); |
550 | 1.57k | break; |
551 | 1.64k | case SetComp_kind: |
552 | 1.64k | CALL(astfold_expr, expr_ty, node_->v.SetComp.elt); |
553 | 1.64k | CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators); |
554 | 1.64k | break; |
555 | 778 | case DictComp_kind: |
556 | 778 | CALL(astfold_expr, expr_ty, node_->v.DictComp.key); |
557 | 778 | CALL(astfold_expr, expr_ty, node_->v.DictComp.value); |
558 | 778 | CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators); |
559 | 778 | break; |
560 | 611 | case GeneratorExp_kind: |
561 | 611 | CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt); |
562 | 611 | CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators); |
563 | 611 | break; |
564 | 218 | case Await_kind: |
565 | 218 | CALL(astfold_expr, expr_ty, node_->v.Await.value); |
566 | 218 | break; |
567 | 1.15k | case Yield_kind: |
568 | 1.15k | CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value); |
569 | 1.15k | break; |
570 | 29 | case YieldFrom_kind: |
571 | 29 | CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value); |
572 | 29 | break; |
573 | 15.1k | case Compare_kind: |
574 | 15.1k | CALL(astfold_expr, expr_ty, node_->v.Compare.left); |
575 | 15.1k | CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators); |
576 | 15.1k | break; |
577 | 10.0k | case Call_kind: |
578 | 10.0k | CALL(astfold_expr, expr_ty, node_->v.Call.func); |
579 | 10.0k | CALL_SEQ(astfold_expr, expr, node_->v.Call.args); |
580 | 10.0k | CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords); |
581 | 10.0k | break; |
582 | 2.68k | case FormattedValue_kind: |
583 | 2.68k | CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value); |
584 | 2.68k | CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec); |
585 | 2.68k | break; |
586 | 2.80k | case Interpolation_kind: |
587 | 2.80k | CALL(astfold_expr, expr_ty, node_->v.Interpolation.value); |
588 | 2.80k | CALL_OPT(astfold_expr, expr_ty, node_->v.Interpolation.format_spec); |
589 | 2.80k | break; |
590 | 2.08k | case JoinedStr_kind: |
591 | 2.08k | CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values); |
592 | 2.08k | break; |
593 | 231 | case TemplateStr_kind: |
594 | 231 | CALL_SEQ(astfold_expr, expr, node_->v.TemplateStr.values); |
595 | 231 | break; |
596 | 13.6k | case Attribute_kind: |
597 | 13.6k | CALL(astfold_expr, expr_ty, node_->v.Attribute.value); |
598 | 13.6k | break; |
599 | 24.6k | case Subscript_kind: |
600 | 24.6k | CALL(astfold_expr, expr_ty, node_->v.Subscript.value); |
601 | 24.6k | CALL(astfold_expr, expr_ty, node_->v.Subscript.slice); |
602 | 24.6k | break; |
603 | 7.96k | case Starred_kind: |
604 | 7.96k | CALL(astfold_expr, expr_ty, node_->v.Starred.value); |
605 | 7.96k | break; |
606 | 12.4k | case Slice_kind: |
607 | 12.4k | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower); |
608 | 12.4k | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper); |
609 | 12.4k | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step); |
610 | 12.4k | break; |
611 | 4.77k | case List_kind: |
612 | 4.77k | CALL_SEQ(astfold_expr, expr, node_->v.List.elts); |
613 | 4.77k | break; |
614 | 86.1k | case Tuple_kind: |
615 | 86.1k | CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts); |
616 | 86.1k | break; |
617 | 341k | case Name_kind: |
618 | 341k | if (state->syntax_check_only) { |
619 | 11 | break; |
620 | 11 | } |
621 | 341k | if (node_->v.Name.ctx == Load && |
622 | 248k | _PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) { |
623 | 577 | LEAVE_RECURSIVE(); |
624 | 577 | return make_const(node_, PyBool_FromLong(!state->optimize), ctx_); |
625 | 577 | } |
626 | 340k | break; |
627 | 340k | case NamedExpr_kind: |
628 | 615 | CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value); |
629 | 615 | break; |
630 | 671k | case Constant_kind: |
631 | | // Already a constant, nothing further to do |
632 | 671k | break; |
633 | | // No default case, so the compiler will emit a warning if new expression |
634 | | // kinds are added without being handled here |
635 | 1.99M | } |
636 | 1.99M | LEAVE_RECURSIVE(); |
637 | 1.99M | return 1; |
638 | 1.99M | } |
639 | | |
640 | | static int |
641 | | astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
642 | 3.47k | { |
643 | 3.47k | CALL(astfold_expr, expr_ty, node_->value); |
644 | 3.47k | return 1; |
645 | 3.47k | } |
646 | | |
647 | | static int |
648 | | astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
649 | 5.90k | { |
650 | 5.90k | CALL(astfold_expr, expr_ty, node_->target); |
651 | 5.90k | CALL(astfold_expr, expr_ty, node_->iter); |
652 | 5.90k | CALL_SEQ(astfold_expr, expr, node_->ifs); |
653 | 5.90k | return 1; |
654 | 5.90k | } |
655 | | |
656 | | static int |
657 | | astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
658 | 10.0k | { |
659 | 10.0k | CALL_SEQ(astfold_arg, arg, node_->posonlyargs); |
660 | 10.0k | CALL_SEQ(astfold_arg, arg, node_->args); |
661 | 10.0k | CALL_OPT(astfold_arg, arg_ty, node_->vararg); |
662 | 10.0k | CALL_SEQ(astfold_arg, arg, node_->kwonlyargs); |
663 | 10.0k | CALL_SEQ(astfold_expr, expr, node_->kw_defaults); |
664 | 10.0k | CALL_OPT(astfold_arg, arg_ty, node_->kwarg); |
665 | 10.0k | CALL_SEQ(astfold_expr, expr, node_->defaults); |
666 | 10.0k | return 1; |
667 | 10.0k | } |
668 | | |
669 | | static int |
670 | | astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
671 | 10.8k | { |
672 | 10.8k | if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) { |
673 | 10.4k | CALL_OPT(astfold_expr, expr_ty, node_->annotation); |
674 | 10.4k | } |
675 | 10.8k | return 1; |
676 | 10.8k | } |
677 | | |
678 | | static int |
679 | | astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
680 | 143k | { |
681 | 143k | ENTER_RECURSIVE(); |
682 | 143k | switch (node_->kind) { |
683 | 4.79k | case FunctionDef_kind: { |
684 | 4.79k | CALL_SEQ(astfold_type_param, type_param, node_->v.FunctionDef.type_params); |
685 | 4.79k | CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args); |
686 | 4.79k | BEFORE_FUNC_BODY(state, node_); |
687 | 4.79k | CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body); |
688 | 4.79k | AFTER_FUNC_BODY(state); |
689 | 4.79k | CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list); |
690 | 4.79k | if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) { |
691 | 4.52k | CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns); |
692 | 4.52k | } |
693 | 4.79k | break; |
694 | 4.79k | } |
695 | 4.79k | case AsyncFunctionDef_kind: { |
696 | 1.29k | CALL_SEQ(astfold_type_param, type_param, node_->v.AsyncFunctionDef.type_params); |
697 | 1.29k | CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args); |
698 | 1.29k | BEFORE_FUNC_BODY(state, node_); |
699 | 1.29k | CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body); |
700 | 1.29k | AFTER_FUNC_BODY(state); |
701 | 1.29k | CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list); |
702 | 1.29k | if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) { |
703 | 1.28k | CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns); |
704 | 1.28k | } |
705 | 1.29k | break; |
706 | 1.29k | } |
707 | 5.24k | case ClassDef_kind: |
708 | 5.24k | CALL_SEQ(astfold_type_param, type_param, node_->v.ClassDef.type_params); |
709 | 5.24k | CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases); |
710 | 5.24k | CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords); |
711 | 5.24k | CALL(astfold_body, asdl_seq, node_->v.ClassDef.body); |
712 | 5.24k | CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list); |
713 | 5.24k | break; |
714 | 292 | case Return_kind: |
715 | 292 | BEFORE_RETURN(state, node_); |
716 | 292 | CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value); |
717 | 292 | break; |
718 | 1.47k | case Delete_kind: |
719 | 1.47k | CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets); |
720 | 1.47k | break; |
721 | 5.95k | case Assign_kind: |
722 | 5.95k | CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets); |
723 | 5.95k | CALL(astfold_expr, expr_ty, node_->v.Assign.value); |
724 | 5.95k | break; |
725 | 1.95k | case AugAssign_kind: |
726 | 1.95k | CALL(astfold_expr, expr_ty, node_->v.AugAssign.target); |
727 | 1.95k | CALL(astfold_expr, expr_ty, node_->v.AugAssign.value); |
728 | 1.95k | break; |
729 | 16.0k | case AnnAssign_kind: |
730 | 16.0k | CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target); |
731 | 16.0k | if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) { |
732 | 13.9k | CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation); |
733 | 13.9k | } |
734 | 16.0k | CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value); |
735 | 16.0k | break; |
736 | 541 | case TypeAlias_kind: |
737 | 541 | CALL(astfold_expr, expr_ty, node_->v.TypeAlias.name); |
738 | 541 | CALL_SEQ(astfold_type_param, type_param, node_->v.TypeAlias.type_params); |
739 | 541 | CALL(astfold_expr, expr_ty, node_->v.TypeAlias.value); |
740 | 541 | break; |
741 | 153 | case For_kind: { |
742 | 153 | CALL(astfold_expr, expr_ty, node_->v.For.target); |
743 | 153 | CALL(astfold_expr, expr_ty, node_->v.For.iter); |
744 | 153 | BEFORE_LOOP_BODY(state, node_); |
745 | 153 | CALL_SEQ(astfold_stmt, stmt, node_->v.For.body); |
746 | 153 | AFTER_LOOP_BODY(state); |
747 | 153 | CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse); |
748 | 153 | break; |
749 | 153 | } |
750 | 13 | case AsyncFor_kind: { |
751 | 13 | CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target); |
752 | 13 | CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter); |
753 | 13 | BEFORE_LOOP_BODY(state, node_); |
754 | 13 | CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body); |
755 | 13 | AFTER_LOOP_BODY(state); |
756 | 13 | CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse); |
757 | 13 | break; |
758 | 13 | } |
759 | 884 | case While_kind: { |
760 | 884 | CALL(astfold_expr, expr_ty, node_->v.While.test); |
761 | 884 | BEFORE_LOOP_BODY(state, node_); |
762 | 884 | CALL_SEQ(astfold_stmt, stmt, node_->v.While.body); |
763 | 884 | AFTER_LOOP_BODY(state); |
764 | 884 | CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse); |
765 | 884 | break; |
766 | 884 | } |
767 | 1.80k | case If_kind: |
768 | 1.80k | CALL(astfold_expr, expr_ty, node_->v.If.test); |
769 | 1.80k | CALL_SEQ(astfold_stmt, stmt, node_->v.If.body); |
770 | 1.80k | CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse); |
771 | 1.80k | break; |
772 | 1.21k | case With_kind: |
773 | 1.21k | CALL_SEQ(astfold_withitem, withitem, node_->v.With.items); |
774 | 1.21k | CALL_SEQ(astfold_stmt, stmt, node_->v.With.body); |
775 | 1.21k | break; |
776 | 294 | case AsyncWith_kind: |
777 | 294 | CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items); |
778 | 294 | CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body); |
779 | 294 | break; |
780 | 1.42k | case Raise_kind: |
781 | 1.42k | CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc); |
782 | 1.42k | CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause); |
783 | 1.42k | break; |
784 | 1.59k | case Try_kind: { |
785 | 1.59k | CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body); |
786 | 1.59k | CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers); |
787 | 1.59k | CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse); |
788 | 1.59k | BEFORE_FINALLY(state, node_); |
789 | 1.59k | CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody); |
790 | 1.59k | AFTER_FINALLY(state); |
791 | 1.59k | break; |
792 | 1.59k | } |
793 | 385 | case TryStar_kind: { |
794 | 385 | CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.body); |
795 | 385 | CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.TryStar.handlers); |
796 | 385 | CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.orelse); |
797 | 385 | BEFORE_FINALLY(state, node_); |
798 | 385 | CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.finalbody); |
799 | 385 | AFTER_FINALLY(state); |
800 | 385 | break; |
801 | 385 | } |
802 | 580 | case Assert_kind: |
803 | 580 | CALL(astfold_expr, expr_ty, node_->v.Assert.test); |
804 | 580 | CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg); |
805 | 580 | break; |
806 | 92.2k | case Expr_kind: |
807 | 92.2k | CALL(astfold_expr, expr_ty, node_->v.Expr.value); |
808 | 92.2k | break; |
809 | 277 | case Match_kind: |
810 | 277 | CALL(astfold_expr, expr_ty, node_->v.Match.subject); |
811 | 277 | CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases); |
812 | 277 | break; |
813 | 306 | case Break_kind: |
814 | 306 | BEFORE_LOOP_EXIT(state, node_, "break"); |
815 | 306 | break; |
816 | 324 | case Continue_kind: |
817 | 324 | BEFORE_LOOP_EXIT(state, node_, "continue"); |
818 | 324 | break; |
819 | | // The following statements don't contain any subexpressions to be folded |
820 | 505 | case Import_kind: |
821 | 3.42k | case ImportFrom_kind: |
822 | 4.00k | case Global_kind: |
823 | 4.14k | case Nonlocal_kind: |
824 | 4.38k | case Pass_kind: |
825 | 4.38k | break; |
826 | | // No default case, so the compiler will emit a warning if new statement |
827 | | // kinds are added without being handled here |
828 | 143k | } |
829 | 143k | LEAVE_RECURSIVE(); |
830 | 143k | return 1; |
831 | 143k | } |
832 | | |
833 | | static int |
834 | | astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
835 | 1.79k | { |
836 | 1.79k | switch (node_->kind) { |
837 | 1.79k | case ExceptHandler_kind: |
838 | 1.79k | CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type); |
839 | 1.79k | CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body); |
840 | 1.79k | break; |
841 | | // No default case, so the compiler will emit a warning if new handler |
842 | | // kinds are added without being handled here |
843 | 1.79k | } |
844 | 1.79k | return 1; |
845 | 1.79k | } |
846 | | |
847 | | static int |
848 | | astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
849 | 6.43k | { |
850 | 6.43k | CALL(astfold_expr, expr_ty, node_->context_expr); |
851 | 6.43k | CALL_OPT(astfold_expr, expr_ty, node_->optional_vars); |
852 | 6.43k | return 1; |
853 | 6.43k | } |
854 | | |
855 | | static int |
856 | | fold_const_match_patterns(expr_ty node, PyArena *ctx_, _PyASTPreprocessState *state) |
857 | 43.6k | { |
858 | 43.6k | if (state->syntax_check_only) { |
859 | 0 | return 1; |
860 | 0 | } |
861 | 43.6k | switch (node->kind) |
862 | 43.6k | { |
863 | 201 | case UnaryOp_kind: |
864 | 201 | { |
865 | 201 | if (node->v.UnaryOp.op == USub && |
866 | 201 | node->v.UnaryOp.operand->kind == Constant_kind) |
867 | 201 | { |
868 | 201 | PyObject *operand = node->v.UnaryOp.operand->v.Constant.value; |
869 | 201 | PyObject *folded = PyNumber_Negative(operand); |
870 | 201 | return make_const(node, folded, ctx_); |
871 | 201 | } |
872 | 0 | break; |
873 | 201 | } |
874 | 34 | case BinOp_kind: |
875 | 34 | { |
876 | 34 | operator_ty op = node->v.BinOp.op; |
877 | 34 | if ((op == Add || op == Sub) && |
878 | 34 | node->v.BinOp.right->kind == Constant_kind) |
879 | 34 | { |
880 | 34 | CALL(fold_const_match_patterns, expr_ty, node->v.BinOp.left); |
881 | 34 | if (node->v.BinOp.left->kind == Constant_kind) { |
882 | 34 | PyObject *left = node->v.BinOp.left->v.Constant.value; |
883 | 34 | PyObject *right = node->v.BinOp.right->v.Constant.value; |
884 | 34 | PyObject *folded = op == Add ? PyNumber_Add(left, right) : PyNumber_Subtract(left, right); |
885 | 34 | return make_const(node, folded, ctx_); |
886 | 34 | } |
887 | 34 | } |
888 | 0 | break; |
889 | 34 | } |
890 | 43.3k | default: |
891 | 43.3k | break; |
892 | 43.6k | } |
893 | 43.3k | return 1; |
894 | 43.6k | } |
895 | | |
896 | | static int |
897 | | astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
898 | 51.5k | { |
899 | | // Currently, this is really only used to form complex/negative numeric |
900 | | // constants in MatchValue and MatchMapping nodes |
901 | | // We still recurse into all subexpressions and subpatterns anyway |
902 | 51.5k | ENTER_RECURSIVE(); |
903 | 51.5k | switch (node_->kind) { |
904 | 43.5k | case MatchValue_kind: |
905 | 43.5k | CALL(fold_const_match_patterns, expr_ty, node_->v.MatchValue.value); |
906 | 43.5k | break; |
907 | 572 | case MatchSingleton_kind: |
908 | 572 | break; |
909 | 1.73k | case MatchSequence_kind: |
910 | 1.73k | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchSequence.patterns); |
911 | 1.73k | break; |
912 | 2 | case MatchMapping_kind: |
913 | 2 | CALL_SEQ(fold_const_match_patterns, expr, node_->v.MatchMapping.keys); |
914 | 2 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchMapping.patterns); |
915 | 2 | break; |
916 | 847 | case MatchClass_kind: |
917 | 847 | CALL(astfold_expr, expr_ty, node_->v.MatchClass.cls); |
918 | 847 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.patterns); |
919 | 847 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.kwd_patterns); |
920 | 847 | break; |
921 | 1.03k | case MatchStar_kind: |
922 | 1.03k | break; |
923 | 2.85k | case MatchAs_kind: |
924 | 2.85k | if (node_->v.MatchAs.pattern) { |
925 | 211 | CALL(astfold_pattern, pattern_ty, node_->v.MatchAs.pattern); |
926 | 211 | } |
927 | 2.85k | break; |
928 | 2.85k | case MatchOr_kind: |
929 | 885 | CALL_SEQ(astfold_pattern, pattern, node_->v.MatchOr.patterns); |
930 | 885 | break; |
931 | | // No default case, so the compiler will emit a warning if new pattern |
932 | | // kinds are added without being handled here |
933 | 51.5k | } |
934 | 51.5k | LEAVE_RECURSIVE(); |
935 | 51.5k | return 1; |
936 | 51.5k | } |
937 | | |
938 | | static int |
939 | | astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
940 | 1.30k | { |
941 | 1.30k | CALL(astfold_pattern, expr_ty, node_->pattern); |
942 | 1.30k | CALL_OPT(astfold_expr, expr_ty, node_->guard); |
943 | 1.30k | CALL_SEQ(astfold_stmt, stmt, node_->body); |
944 | 1.30k | return 1; |
945 | 1.30k | } |
946 | | |
947 | | static int |
948 | | astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTPreprocessState *state) |
949 | 8.70k | { |
950 | 8.70k | switch (node_->kind) { |
951 | 8.04k | case TypeVar_kind: |
952 | 8.04k | CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.bound); |
953 | 8.04k | CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.default_value); |
954 | 8.04k | break; |
955 | 326 | case ParamSpec_kind: |
956 | 326 | CALL_OPT(astfold_expr, expr_ty, node_->v.ParamSpec.default_value); |
957 | 326 | break; |
958 | 332 | case TypeVarTuple_kind: |
959 | 332 | CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVarTuple.default_value); |
960 | 332 | break; |
961 | 8.70k | } |
962 | 8.70k | return 1; |
963 | 8.70k | } |
964 | | |
965 | | #undef CALL |
966 | | #undef CALL_OPT |
967 | | #undef CALL_SEQ |
968 | | |
969 | | int |
970 | | _PyAST_Preprocess(mod_ty mod, PyArena *arena, PyObject *filename, int optimize, |
971 | | int ff_features, int syntax_check_only) |
972 | 13.6k | { |
973 | 13.6k | _PyASTPreprocessState state; |
974 | 13.6k | memset(&state, 0, sizeof(_PyASTPreprocessState)); |
975 | 13.6k | state.filename = filename; |
976 | 13.6k | state.optimize = optimize; |
977 | 13.6k | state.ff_features = ff_features; |
978 | 13.6k | state.syntax_check_only = syntax_check_only; |
979 | 13.6k | if (_Py_CArray_Init(&state.cf_finally, sizeof(ControlFlowInFinallyContext), 20) < 0) { |
980 | 0 | return -1; |
981 | 0 | } |
982 | | |
983 | 13.6k | int ret = astfold_mod(mod, arena, &state); |
984 | 13.6k | assert(ret || PyErr_Occurred()); |
985 | | |
986 | 13.6k | _Py_CArray_Fini(&state.cf_finally); |
987 | 13.6k | return ret; |
988 | 13.6k | } |