/src/Python-3.8.3/Python/ast_opt.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* AST Optimizer */ |
2 | | #include "Python.h" |
3 | | #include "Python-ast.h" |
4 | | #include "ast.h" |
5 | | |
6 | | |
7 | | static int |
8 | | make_const(expr_ty node, PyObject *val, PyArena *arena) |
9 | 14 | { |
10 | 14 | if (val == NULL) { |
11 | 12 | if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) { |
12 | 0 | return 0; |
13 | 0 | } |
14 | 12 | PyErr_Clear(); |
15 | 12 | return 1; |
16 | 12 | } |
17 | 2 | if (PyArena_AddPyObject(arena, val) < 0) { |
18 | 0 | Py_DECREF(val); |
19 | 0 | return 0; |
20 | 0 | } |
21 | 2 | node->kind = Constant_kind; |
22 | 2 | node->v.Constant.value = val; |
23 | 2 | return 1; |
24 | 2 | } |
25 | | |
26 | 0 | #define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr))) |
27 | | |
28 | | static PyObject* |
29 | | unary_not(PyObject *v) |
30 | 0 | { |
31 | 0 | int r = PyObject_IsTrue(v); |
32 | 0 | if (r < 0) |
33 | 0 | return NULL; |
34 | 0 | return PyBool_FromLong(!r); |
35 | 0 | } |
36 | | |
37 | | static int |
38 | | fold_unaryop(expr_ty node, PyArena *arena, int optimize) |
39 | 0 | { |
40 | 0 | expr_ty arg = node->v.UnaryOp.operand; |
41 | |
|
42 | 0 | if (arg->kind != Constant_kind) { |
43 | | /* Fold not into comparison */ |
44 | 0 | if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind && |
45 | 0 | asdl_seq_LEN(arg->v.Compare.ops) == 1) { |
46 | | /* Eq and NotEq are often implemented in terms of one another, so |
47 | | folding not (self == other) into self != other breaks implementation |
48 | | of !=. Detecting such cases doesn't seem worthwhile. |
49 | | Python uses </> for 'is subset'/'is superset' operations on sets. |
50 | | They don't satisfy not folding laws. */ |
51 | 0 | int op = asdl_seq_GET(arg->v.Compare.ops, 0); |
52 | 0 | switch (op) { |
53 | 0 | case Is: |
54 | 0 | op = IsNot; |
55 | 0 | break; |
56 | 0 | case IsNot: |
57 | 0 | op = Is; |
58 | 0 | break; |
59 | 0 | case In: |
60 | 0 | op = NotIn; |
61 | 0 | break; |
62 | 0 | case NotIn: |
63 | 0 | op = In; |
64 | 0 | break; |
65 | 0 | default: |
66 | 0 | op = 0; |
67 | 0 | } |
68 | 0 | if (op) { |
69 | 0 | asdl_seq_SET(arg->v.Compare.ops, 0, op); |
70 | 0 | COPY_NODE(node, arg); |
71 | 0 | return 1; |
72 | 0 | } |
73 | 0 | } |
74 | 0 | return 1; |
75 | 0 | } |
76 | | |
77 | 0 | typedef PyObject *(*unary_op)(PyObject*); |
78 | 0 | static const unary_op ops[] = { |
79 | 0 | [Invert] = PyNumber_Invert, |
80 | 0 | [Not] = unary_not, |
81 | 0 | [UAdd] = PyNumber_Positive, |
82 | 0 | [USub] = PyNumber_Negative, |
83 | 0 | }; |
84 | 0 | PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value); |
85 | 0 | return make_const(node, newval, arena); |
86 | 0 | } |
87 | | |
88 | | /* Check whether a collection doesn't containing too much items (including |
89 | | subcollections). This protects from creating a constant that needs |
90 | | too much time for calculating a hash. |
91 | | "limit" is the maximal number of items. |
92 | | Returns the negative number if the total number of items exceeds the |
93 | | limit. Otherwise returns the limit minus the total number of items. |
94 | | */ |
95 | | |
96 | | static Py_ssize_t |
97 | | check_complexity(PyObject *obj, Py_ssize_t limit) |
98 | 0 | { |
99 | 0 | if (PyTuple_Check(obj)) { |
100 | 0 | Py_ssize_t i; |
101 | 0 | limit -= PyTuple_GET_SIZE(obj); |
102 | 0 | for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) { |
103 | 0 | limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit); |
104 | 0 | } |
105 | 0 | return limit; |
106 | 0 | } |
107 | 0 | else if (PyFrozenSet_Check(obj)) { |
108 | 0 | Py_ssize_t i = 0; |
109 | 0 | PyObject *item; |
110 | 0 | Py_hash_t hash; |
111 | 0 | limit -= PySet_GET_SIZE(obj); |
112 | 0 | while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) { |
113 | 0 | limit = check_complexity(item, limit); |
114 | 0 | } |
115 | 0 | } |
116 | 0 | return limit; |
117 | 0 | } |
118 | | |
119 | 0 | #define MAX_INT_SIZE 128 /* bits */ |
120 | 0 | #define MAX_COLLECTION_SIZE 256 /* items */ |
121 | 0 | #define MAX_STR_SIZE 4096 /* characters */ |
122 | 0 | #define MAX_TOTAL_ITEMS 1024 /* including nested collections */ |
123 | | |
124 | | static PyObject * |
125 | | safe_multiply(PyObject *v, PyObject *w) |
126 | 0 | { |
127 | 0 | if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) { |
128 | 0 | size_t vbits = _PyLong_NumBits(v); |
129 | 0 | size_t wbits = _PyLong_NumBits(w); |
130 | 0 | if (vbits == (size_t)-1 || wbits == (size_t)-1) { |
131 | 0 | return NULL; |
132 | 0 | } |
133 | 0 | if (vbits + wbits > MAX_INT_SIZE) { |
134 | 0 | return NULL; |
135 | 0 | } |
136 | 0 | } |
137 | 0 | else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) { |
138 | 0 | Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) : |
139 | 0 | PySet_GET_SIZE(w); |
140 | 0 | if (size) { |
141 | 0 | long n = PyLong_AsLong(v); |
142 | 0 | if (n < 0 || n > MAX_COLLECTION_SIZE / size) { |
143 | 0 | return NULL; |
144 | 0 | } |
145 | 0 | if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) { |
146 | 0 | return NULL; |
147 | 0 | } |
148 | 0 | } |
149 | 0 | } |
150 | 0 | else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) { |
151 | 0 | Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) : |
152 | 0 | PyBytes_GET_SIZE(w); |
153 | 0 | if (size) { |
154 | 0 | long n = PyLong_AsLong(v); |
155 | 0 | if (n < 0 || n > MAX_STR_SIZE / size) { |
156 | 0 | return NULL; |
157 | 0 | } |
158 | 0 | } |
159 | 0 | } |
160 | 0 | else if (PyLong_Check(w) && |
161 | 0 | (PyTuple_Check(v) || PyFrozenSet_Check(v) || |
162 | 0 | PyUnicode_Check(v) || PyBytes_Check(v))) |
163 | 0 | { |
164 | 0 | return safe_multiply(w, v); |
165 | 0 | } |
166 | | |
167 | 0 | return PyNumber_Multiply(v, w); |
168 | 0 | } |
169 | | |
170 | | static PyObject * |
171 | | safe_power(PyObject *v, PyObject *w) |
172 | 0 | { |
173 | 0 | if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) { |
174 | 0 | size_t vbits = _PyLong_NumBits(v); |
175 | 0 | size_t wbits = PyLong_AsSize_t(w); |
176 | 0 | if (vbits == (size_t)-1 || wbits == (size_t)-1) { |
177 | 0 | return NULL; |
178 | 0 | } |
179 | 0 | if (vbits > MAX_INT_SIZE / wbits) { |
180 | 0 | return NULL; |
181 | 0 | } |
182 | 0 | } |
183 | | |
184 | 0 | return PyNumber_Power(v, w, Py_None); |
185 | 0 | } |
186 | | |
187 | | static PyObject * |
188 | | safe_lshift(PyObject *v, PyObject *w) |
189 | 0 | { |
190 | 0 | if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) { |
191 | 0 | size_t vbits = _PyLong_NumBits(v); |
192 | 0 | size_t wbits = PyLong_AsSize_t(w); |
193 | 0 | if (vbits == (size_t)-1 || wbits == (size_t)-1) { |
194 | 0 | return NULL; |
195 | 0 | } |
196 | 0 | if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) { |
197 | 0 | return NULL; |
198 | 0 | } |
199 | 0 | } |
200 | | |
201 | 0 | return PyNumber_Lshift(v, w); |
202 | 0 | } |
203 | | |
204 | | static PyObject * |
205 | | safe_mod(PyObject *v, PyObject *w) |
206 | 0 | { |
207 | 0 | if (PyUnicode_Check(v) || PyBytes_Check(v)) { |
208 | 0 | return NULL; |
209 | 0 | } |
210 | | |
211 | 0 | return PyNumber_Remainder(v, w); |
212 | 0 | } |
213 | | |
214 | | static int |
215 | | fold_binop(expr_ty node, PyArena *arena, int optimize) |
216 | 12 | { |
217 | 12 | expr_ty lhs, rhs; |
218 | 12 | lhs = node->v.BinOp.left; |
219 | 12 | rhs = node->v.BinOp.right; |
220 | 12 | if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) { |
221 | 12 | return 1; |
222 | 12 | } |
223 | | |
224 | 0 | PyObject *lv = lhs->v.Constant.value; |
225 | 0 | PyObject *rv = rhs->v.Constant.value; |
226 | 0 | PyObject *newval; |
227 | |
|
228 | 0 | switch (node->v.BinOp.op) { |
229 | 0 | case Add: |
230 | 0 | newval = PyNumber_Add(lv, rv); |
231 | 0 | break; |
232 | 0 | case Sub: |
233 | 0 | newval = PyNumber_Subtract(lv, rv); |
234 | 0 | break; |
235 | 0 | case Mult: |
236 | 0 | newval = safe_multiply(lv, rv); |
237 | 0 | break; |
238 | 0 | case Div: |
239 | 0 | newval = PyNumber_TrueDivide(lv, rv); |
240 | 0 | break; |
241 | 0 | case FloorDiv: |
242 | 0 | newval = PyNumber_FloorDivide(lv, rv); |
243 | 0 | break; |
244 | 0 | case Mod: |
245 | 0 | newval = safe_mod(lv, rv); |
246 | 0 | break; |
247 | 0 | case Pow: |
248 | 0 | newval = safe_power(lv, rv); |
249 | 0 | break; |
250 | 0 | case LShift: |
251 | 0 | newval = safe_lshift(lv, rv); |
252 | 0 | break; |
253 | 0 | case RShift: |
254 | 0 | newval = PyNumber_Rshift(lv, rv); |
255 | 0 | break; |
256 | 0 | case BitOr: |
257 | 0 | newval = PyNumber_Or(lv, rv); |
258 | 0 | break; |
259 | 0 | case BitXor: |
260 | 0 | newval = PyNumber_Xor(lv, rv); |
261 | 0 | break; |
262 | 0 | case BitAnd: |
263 | 0 | newval = PyNumber_And(lv, rv); |
264 | 0 | break; |
265 | 0 | default: // Unknown operator |
266 | 0 | return 1; |
267 | 0 | } |
268 | | |
269 | 0 | return make_const(node, newval, arena); |
270 | 0 | } |
271 | | |
272 | | static PyObject* |
273 | | make_const_tuple(asdl_seq *elts) |
274 | 14 | { |
275 | 18 | for (int i = 0; i < asdl_seq_LEN(elts); i++) { |
276 | 16 | expr_ty e = (expr_ty)asdl_seq_GET(elts, i); |
277 | 16 | if (e->kind != Constant_kind) { |
278 | 12 | return NULL; |
279 | 12 | } |
280 | 16 | } |
281 | | |
282 | 2 | PyObject *newval = PyTuple_New(asdl_seq_LEN(elts)); |
283 | 2 | if (newval == NULL) { |
284 | 0 | return NULL; |
285 | 0 | } |
286 | | |
287 | 6 | for (int i = 0; i < asdl_seq_LEN(elts); i++) { |
288 | 4 | expr_ty e = (expr_ty)asdl_seq_GET(elts, i); |
289 | 4 | PyObject *v = e->v.Constant.value; |
290 | 4 | Py_INCREF(v); |
291 | 4 | PyTuple_SET_ITEM(newval, i, v); |
292 | 4 | } |
293 | 2 | return newval; |
294 | 2 | } |
295 | | |
296 | | static int |
297 | | fold_tuple(expr_ty node, PyArena *arena, int optimize) |
298 | 24 | { |
299 | 24 | PyObject *newval; |
300 | | |
301 | 24 | if (node->v.Tuple.ctx != Load) |
302 | 10 | return 1; |
303 | | |
304 | 14 | newval = make_const_tuple(node->v.Tuple.elts); |
305 | 14 | return make_const(node, newval, arena); |
306 | 24 | } |
307 | | |
308 | | static int |
309 | | fold_subscr(expr_ty node, PyArena *arena, int optimize) |
310 | 14 | { |
311 | 14 | PyObject *newval; |
312 | 14 | expr_ty arg, idx; |
313 | 14 | slice_ty slice; |
314 | | |
315 | 14 | arg = node->v.Subscript.value; |
316 | 14 | slice = node->v.Subscript.slice; |
317 | 14 | if (node->v.Subscript.ctx != Load || |
318 | 14 | arg->kind != Constant_kind || |
319 | | /* TODO: handle other types of slices */ |
320 | 14 | slice->kind != Index_kind || |
321 | 14 | slice->v.Index.value->kind != Constant_kind) |
322 | 14 | { |
323 | 14 | return 1; |
324 | 14 | } |
325 | | |
326 | 0 | idx = slice->v.Index.value; |
327 | 0 | newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value); |
328 | 0 | return make_const(node, newval, arena); |
329 | 14 | } |
330 | | |
331 | | /* Change literal list or set of constants into constant |
332 | | tuple or frozenset respectively. Change literal list of |
333 | | non-constants into tuple. |
334 | | Used for right operand of "in" and "not in" tests and for iterable |
335 | | in "for" loop and comprehensions. |
336 | | */ |
337 | | static int |
338 | | fold_iter(expr_ty arg, PyArena *arena, int optimize) |
339 | 18 | { |
340 | 18 | PyObject *newval; |
341 | 18 | if (arg->kind == List_kind) { |
342 | | /* First change a list into tuple. */ |
343 | 0 | asdl_seq *elts = arg->v.List.elts; |
344 | 0 | Py_ssize_t n = asdl_seq_LEN(elts); |
345 | 0 | for (Py_ssize_t i = 0; i < n; i++) { |
346 | 0 | expr_ty e = (expr_ty)asdl_seq_GET(elts, i); |
347 | 0 | if (e->kind == Starred_kind) { |
348 | 0 | return 1; |
349 | 0 | } |
350 | 0 | } |
351 | 0 | expr_context_ty ctx = arg->v.List.ctx; |
352 | 0 | arg->kind = Tuple_kind; |
353 | 0 | arg->v.Tuple.elts = elts; |
354 | 0 | arg->v.Tuple.ctx = ctx; |
355 | | /* Try to create a constant tuple. */ |
356 | 0 | newval = make_const_tuple(elts); |
357 | 0 | } |
358 | 18 | else if (arg->kind == Set_kind) { |
359 | 0 | newval = make_const_tuple(arg->v.Set.elts); |
360 | 0 | if (newval) { |
361 | 0 | Py_SETREF(newval, PyFrozenSet_New(newval)); |
362 | 0 | } |
363 | 0 | } |
364 | 18 | else { |
365 | 18 | return 1; |
366 | 18 | } |
367 | 0 | return make_const(arg, newval, arena); |
368 | 18 | } |
369 | | |
370 | | static int |
371 | | fold_compare(expr_ty node, PyArena *arena, int optimize) |
372 | 24 | { |
373 | 24 | asdl_int_seq *ops; |
374 | 24 | asdl_seq *args; |
375 | 24 | Py_ssize_t i; |
376 | | |
377 | 24 | ops = node->v.Compare.ops; |
378 | 24 | args = node->v.Compare.comparators; |
379 | | /* TODO: optimize cases with literal arguments. */ |
380 | | /* Change literal list or set in 'in' or 'not in' into |
381 | | tuple or frozenset respectively. */ |
382 | 24 | i = asdl_seq_LEN(ops) - 1; |
383 | 24 | int op = asdl_seq_GET(ops, i); |
384 | 24 | if (op == In || op == NotIn) { |
385 | 10 | if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, optimize)) { |
386 | 0 | return 0; |
387 | 0 | } |
388 | 10 | } |
389 | 24 | return 1; |
390 | 24 | } |
391 | | |
392 | | static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_); |
393 | | static int astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_); |
394 | | static int astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_); |
395 | | static int astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_); |
396 | | static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_); |
397 | | static int astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_); |
398 | | static int astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_); |
399 | | static int astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_); |
400 | | static int astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_); |
401 | | static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_); |
402 | | #define CALL(FUNC, TYPE, ARG) \ |
403 | 438 | if (!FUNC((ARG), ctx_, optimize_)) \ |
404 | 438 | return 0; |
405 | | |
406 | | #define CALL_OPT(FUNC, TYPE, ARG) \ |
407 | 75 | if ((ARG) != NULL && !FUNC((ARG), ctx_, optimize_)) \ |
408 | 75 | return 0; |
409 | | |
410 | 438 | #define CALL_SEQ(FUNC, TYPE, ARG) { \ |
411 | 438 | int i; \ |
412 | 438 | asdl_seq *seq = (ARG); /* avoid variable capture */ \ |
413 | 848 | for (i = 0; i < asdl_seq_LEN(seq); i++) { \ |
414 | 410 | TYPE elt = (TYPE)asdl_seq_GET(seq, i); \ |
415 | 410 | if (elt != NULL && !FUNC(elt, ctx_, optimize_)) \ |
416 | 410 | return 0; \ |
417 | 410 | } \ |
418 | 438 | } |
419 | | |
420 | | #define CALL_INT_SEQ(FUNC, TYPE, ARG) { \ |
421 | | int i; \ |
422 | | asdl_int_seq *seq = (ARG); /* avoid variable capture */ \ |
423 | | for (i = 0; i < asdl_seq_LEN(seq); i++) { \ |
424 | | TYPE elt = (TYPE)asdl_seq_GET(seq, i); \ |
425 | | if (!FUNC(elt, ctx_, optimize_)) \ |
426 | | return 0; \ |
427 | | } \ |
428 | | } |
429 | | |
430 | | static int |
431 | | astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_) |
432 | 20 | { |
433 | 20 | int docstring = _PyAST_GetDocString(stmts) != NULL; |
434 | 20 | CALL_SEQ(astfold_stmt, stmt_ty, stmts); |
435 | 20 | if (!docstring && _PyAST_GetDocString(stmts) != NULL) { |
436 | 0 | stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); |
437 | 0 | asdl_seq *values = _Py_asdl_seq_new(1, ctx_); |
438 | 0 | if (!values) { |
439 | 0 | return 0; |
440 | 0 | } |
441 | 0 | asdl_seq_SET(values, 0, st->v.Expr.value); |
442 | 0 | expr_ty expr = JoinedStr(values, st->lineno, st->col_offset, |
443 | 0 | st->end_lineno, st->end_col_offset, ctx_); |
444 | 0 | if (!expr) { |
445 | 0 | return 0; |
446 | 0 | } |
447 | 0 | st->v.Expr.value = expr; |
448 | 0 | } |
449 | 20 | return 1; |
450 | 20 | } |
451 | | |
452 | | static int |
453 | | astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_) |
454 | 16 | { |
455 | 16 | switch (node_->kind) { |
456 | 16 | case Module_kind: |
457 | 16 | CALL(astfold_body, asdl_seq, node_->v.Module.body); |
458 | 16 | break; |
459 | 0 | case Interactive_kind: |
460 | 0 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body); |
461 | 0 | break; |
462 | 0 | case Expression_kind: |
463 | 0 | CALL(astfold_expr, expr_ty, node_->v.Expression.body); |
464 | 0 | break; |
465 | 0 | case Suite_kind: |
466 | 0 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Suite.body); |
467 | 0 | break; |
468 | 0 | default: |
469 | 0 | break; |
470 | 16 | } |
471 | 16 | return 1; |
472 | 16 | } |
473 | | |
474 | | static int |
475 | | astfold_expr(expr_ty node_, PyArena *ctx_, int optimize_) |
476 | 583 | { |
477 | 583 | switch (node_->kind) { |
478 | 0 | case BoolOp_kind: |
479 | 0 | CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values); |
480 | 0 | break; |
481 | 12 | case BinOp_kind: |
482 | 12 | CALL(astfold_expr, expr_ty, node_->v.BinOp.left); |
483 | 12 | CALL(astfold_expr, expr_ty, node_->v.BinOp.right); |
484 | 12 | CALL(fold_binop, expr_ty, node_); |
485 | 12 | break; |
486 | 0 | case UnaryOp_kind: |
487 | 0 | CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand); |
488 | 0 | CALL(fold_unaryop, expr_ty, node_); |
489 | 0 | break; |
490 | 2 | case Lambda_kind: |
491 | 2 | CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args); |
492 | 2 | CALL(astfold_expr, expr_ty, node_->v.Lambda.body); |
493 | 2 | break; |
494 | 0 | case IfExp_kind: |
495 | 0 | CALL(astfold_expr, expr_ty, node_->v.IfExp.test); |
496 | 0 | CALL(astfold_expr, expr_ty, node_->v.IfExp.body); |
497 | 0 | CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse); |
498 | 0 | break; |
499 | 6 | case Dict_kind: |
500 | 6 | CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys); |
501 | 6 | CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values); |
502 | 6 | break; |
503 | 0 | case Set_kind: |
504 | 0 | CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts); |
505 | 0 | break; |
506 | 0 | case ListComp_kind: |
507 | 0 | CALL(astfold_expr, expr_ty, node_->v.ListComp.elt); |
508 | 0 | CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators); |
509 | 0 | break; |
510 | 0 | case SetComp_kind: |
511 | 0 | CALL(astfold_expr, expr_ty, node_->v.SetComp.elt); |
512 | 0 | CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators); |
513 | 0 | break; |
514 | 0 | case DictComp_kind: |
515 | 0 | CALL(astfold_expr, expr_ty, node_->v.DictComp.key); |
516 | 0 | CALL(astfold_expr, expr_ty, node_->v.DictComp.value); |
517 | 0 | CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators); |
518 | 0 | break; |
519 | 0 | case GeneratorExp_kind: |
520 | 0 | CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt); |
521 | 0 | CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators); |
522 | 0 | break; |
523 | 0 | case Await_kind: |
524 | 0 | CALL(astfold_expr, expr_ty, node_->v.Await.value); |
525 | 0 | break; |
526 | 0 | case Yield_kind: |
527 | 0 | CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value); |
528 | 0 | break; |
529 | 0 | case YieldFrom_kind: |
530 | 0 | CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value); |
531 | 0 | break; |
532 | 24 | case Compare_kind: |
533 | 24 | CALL(astfold_expr, expr_ty, node_->v.Compare.left); |
534 | 24 | CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators); |
535 | 24 | CALL(fold_compare, expr_ty, node_); |
536 | 24 | break; |
537 | 80 | case Call_kind: |
538 | 80 | CALL(astfold_expr, expr_ty, node_->v.Call.func); |
539 | 80 | CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args); |
540 | 80 | CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords); |
541 | 80 | break; |
542 | 0 | case FormattedValue_kind: |
543 | 0 | CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value); |
544 | 0 | CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec); |
545 | 0 | break; |
546 | 0 | case JoinedStr_kind: |
547 | 0 | CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values); |
548 | 0 | break; |
549 | 60 | case Attribute_kind: |
550 | 60 | CALL(astfold_expr, expr_ty, node_->v.Attribute.value); |
551 | 60 | break; |
552 | 14 | case Subscript_kind: |
553 | 14 | CALL(astfold_expr, expr_ty, node_->v.Subscript.value); |
554 | 14 | CALL(astfold_slice, slice_ty, node_->v.Subscript.slice); |
555 | 14 | CALL(fold_subscr, expr_ty, node_); |
556 | 14 | break; |
557 | 0 | case Starred_kind: |
558 | 0 | CALL(astfold_expr, expr_ty, node_->v.Starred.value); |
559 | 0 | break; |
560 | 4 | case List_kind: |
561 | 4 | CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts); |
562 | 4 | break; |
563 | 24 | case Tuple_kind: |
564 | 24 | CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts); |
565 | 24 | CALL(fold_tuple, expr_ty, node_); |
566 | 24 | break; |
567 | 295 | case Name_kind: |
568 | 295 | if (_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) { |
569 | 0 | return make_const(node_, PyBool_FromLong(!optimize_), ctx_); |
570 | 0 | } |
571 | 295 | break; |
572 | 295 | default: |
573 | 62 | break; |
574 | 583 | } |
575 | 583 | return 1; |
576 | 583 | } |
577 | | |
578 | | static int |
579 | | astfold_slice(slice_ty node_, PyArena *ctx_, int optimize_) |
580 | 14 | { |
581 | 14 | switch (node_->kind) { |
582 | 2 | case Slice_kind: |
583 | 2 | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower); |
584 | 2 | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper); |
585 | 2 | CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step); |
586 | 2 | break; |
587 | 0 | case ExtSlice_kind: |
588 | 0 | CALL_SEQ(astfold_slice, slice_ty, node_->v.ExtSlice.dims); |
589 | 0 | break; |
590 | 12 | case Index_kind: |
591 | 12 | CALL(astfold_expr, expr_ty, node_->v.Index.value); |
592 | 12 | break; |
593 | 0 | default: |
594 | 0 | break; |
595 | 14 | } |
596 | 14 | return 1; |
597 | 14 | } |
598 | | |
599 | | static int |
600 | | astfold_keyword(keyword_ty node_, PyArena *ctx_, int optimize_) |
601 | 0 | { |
602 | 0 | CALL(astfold_expr, expr_ty, node_->value); |
603 | 0 | return 1; |
604 | 0 | } |
605 | | |
606 | | static int |
607 | | astfold_comprehension(comprehension_ty node_, PyArena *ctx_, int optimize_) |
608 | 0 | { |
609 | 0 | CALL(astfold_expr, expr_ty, node_->target); |
610 | 0 | CALL(astfold_expr, expr_ty, node_->iter); |
611 | 0 | CALL_SEQ(astfold_expr, expr_ty, node_->ifs); |
612 | |
|
613 | 0 | CALL(fold_iter, expr_ty, node_->iter); |
614 | 0 | return 1; |
615 | 0 | } |
616 | | |
617 | | static int |
618 | | astfold_arguments(arguments_ty node_, PyArena *ctx_, int optimize_) |
619 | 6 | { |
620 | 6 | CALL_SEQ(astfold_arg, arg_ty, node_->posonlyargs); |
621 | 6 | CALL_SEQ(astfold_arg, arg_ty, node_->args); |
622 | 6 | CALL_OPT(astfold_arg, arg_ty, node_->vararg); |
623 | 6 | CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs); |
624 | 6 | CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults); |
625 | 6 | CALL_OPT(astfold_arg, arg_ty, node_->kwarg); |
626 | 6 | CALL_SEQ(astfold_expr, expr_ty, node_->defaults); |
627 | 6 | return 1; |
628 | 6 | } |
629 | | |
630 | | static int |
631 | | astfold_arg(arg_ty node_, PyArena *ctx_, int optimize_) |
632 | 17 | { |
633 | 17 | CALL_OPT(astfold_expr, expr_ty, node_->annotation); |
634 | 17 | return 1; |
635 | 17 | } |
636 | | |
637 | | static int |
638 | | astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_) |
639 | 140 | { |
640 | 140 | switch (node_->kind) { |
641 | 4 | case FunctionDef_kind: |
642 | 4 | CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args); |
643 | 4 | CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body); |
644 | 4 | CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list); |
645 | 4 | CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns); |
646 | 4 | break; |
647 | 0 | case AsyncFunctionDef_kind: |
648 | 0 | CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args); |
649 | 0 | CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body); |
650 | 0 | CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list); |
651 | 0 | CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns); |
652 | 0 | break; |
653 | 0 | case ClassDef_kind: |
654 | 0 | CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases); |
655 | 0 | CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords); |
656 | 0 | CALL(astfold_body, asdl_seq, node_->v.ClassDef.body); |
657 | 0 | CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list); |
658 | 0 | break; |
659 | 6 | case Return_kind: |
660 | 6 | CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value); |
661 | 6 | break; |
662 | 2 | case Delete_kind: |
663 | 2 | CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets); |
664 | 2 | break; |
665 | 34 | case Assign_kind: |
666 | 34 | CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets); |
667 | 34 | CALL(astfold_expr, expr_ty, node_->v.Assign.value); |
668 | 34 | break; |
669 | 0 | case AugAssign_kind: |
670 | 0 | CALL(astfold_expr, expr_ty, node_->v.AugAssign.target); |
671 | 0 | CALL(astfold_expr, expr_ty, node_->v.AugAssign.value); |
672 | 0 | break; |
673 | 0 | case AnnAssign_kind: |
674 | 0 | CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target); |
675 | 0 | CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation); |
676 | 0 | CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value); |
677 | 0 | break; |
678 | 8 | case For_kind: |
679 | 8 | CALL(astfold_expr, expr_ty, node_->v.For.target); |
680 | 8 | CALL(astfold_expr, expr_ty, node_->v.For.iter); |
681 | 8 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body); |
682 | 8 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse); |
683 | | |
684 | 8 | CALL(fold_iter, expr_ty, node_->v.For.iter); |
685 | 8 | break; |
686 | 0 | case AsyncFor_kind: |
687 | 0 | CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target); |
688 | 0 | CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter); |
689 | 0 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body); |
690 | 0 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse); |
691 | 0 | break; |
692 | 0 | case While_kind: |
693 | 0 | CALL(astfold_expr, expr_ty, node_->v.While.test); |
694 | 0 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body); |
695 | 0 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse); |
696 | 0 | break; |
697 | 8 | case If_kind: |
698 | 8 | CALL(astfold_expr, expr_ty, node_->v.If.test); |
699 | 8 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body); |
700 | 8 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse); |
701 | 8 | break; |
702 | 0 | case With_kind: |
703 | 0 | CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items); |
704 | 0 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body); |
705 | 0 | break; |
706 | 0 | case AsyncWith_kind: |
707 | 0 | CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items); |
708 | 0 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body); |
709 | 0 | break; |
710 | 2 | case Raise_kind: |
711 | 2 | CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc); |
712 | 2 | CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause); |
713 | 2 | break; |
714 | 18 | case Try_kind: |
715 | 18 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body); |
716 | 18 | CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers); |
717 | 18 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse); |
718 | 18 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody); |
719 | 18 | break; |
720 | 6 | case Assert_kind: |
721 | 6 | CALL(astfold_expr, expr_ty, node_->v.Assert.test); |
722 | 6 | CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg); |
723 | 6 | break; |
724 | 36 | case Expr_kind: |
725 | 36 | CALL(astfold_expr, expr_ty, node_->v.Expr.value); |
726 | 36 | break; |
727 | 16 | default: |
728 | 16 | break; |
729 | 140 | } |
730 | 140 | return 1; |
731 | 140 | } |
732 | | |
733 | | static int |
734 | | astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int optimize_) |
735 | 20 | { |
736 | 20 | switch (node_->kind) { |
737 | 20 | case ExceptHandler_kind: |
738 | 20 | CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type); |
739 | 20 | CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body); |
740 | 20 | break; |
741 | 0 | default: |
742 | 0 | break; |
743 | 20 | } |
744 | 20 | return 1; |
745 | 20 | } |
746 | | |
747 | | static int |
748 | | astfold_withitem(withitem_ty node_, PyArena *ctx_, int optimize_) |
749 | 0 | { |
750 | 0 | CALL(astfold_expr, expr_ty, node_->context_expr); |
751 | 0 | CALL_OPT(astfold_expr, expr_ty, node_->optional_vars); |
752 | 0 | return 1; |
753 | 0 | } |
754 | | |
755 | | #undef CALL |
756 | | #undef CALL_OPT |
757 | | #undef CALL_SEQ |
758 | | #undef CALL_INT_SEQ |
759 | | |
760 | | int |
761 | | _PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize) |
762 | 16 | { |
763 | 16 | int ret = astfold_mod(mod, arena, optimize); |
764 | 16 | assert(ret || PyErr_Occurred()); |
765 | 16 | return ret; |
766 | 16 | } |