Return the constant value of an expression for supported operations. Among other things, support int arithmetic and string concatenation. For example, the expression 3 + 5 has the constant value 8. Also bind simple references to final constants defined in the current module (cu
(expr: Expression, cur_mod_id: str)
| 25 | |
| 26 | |
| 27 | def constant_fold_expr(expr: Expression, cur_mod_id: str) -> ConstantValue | None: |
| 28 | """Return the constant value of an expression for supported operations. |
| 29 | |
| 30 | Among other things, support int arithmetic and string |
| 31 | concatenation. For example, the expression 3 + 5 has the constant |
| 32 | value 8. |
| 33 | |
| 34 | Also bind simple references to final constants defined in the |
| 35 | current module (cur_mod_id). Binding to references is best effort |
| 36 | -- we don't bind references to other modules. Mypyc trusts these |
| 37 | to be correct in compiled modules, so that it can replace a |
| 38 | constant expression (or a reference to one) with the statically |
| 39 | computed value. We don't want to infer constant values based on |
| 40 | stubs, in particular, as these might not match the implementation |
| 41 | (due to version skew, for example). |
| 42 | |
| 43 | Return None if unsuccessful. |
| 44 | """ |
| 45 | if isinstance(expr, IntExpr): |
| 46 | return expr.value |
| 47 | if isinstance(expr, StrExpr): |
| 48 | return expr.value |
| 49 | if isinstance(expr, FloatExpr): |
| 50 | return expr.value |
| 51 | if isinstance(expr, ComplexExpr): |
| 52 | return expr.value |
| 53 | elif isinstance(expr, NameExpr): |
| 54 | if expr.name == "True": |
| 55 | return True |
| 56 | elif expr.name == "False": |
| 57 | return False |
| 58 | node = expr.node |
| 59 | if ( |
| 60 | isinstance(node, Var) |
| 61 | and node.is_final |
| 62 | and node.fullname.rsplit(".", 1)[0] == cur_mod_id |
| 63 | ): |
| 64 | value = node.final_value |
| 65 | if isinstance(value, (CONST_TYPES)): |
| 66 | return value |
| 67 | elif isinstance(expr, OpExpr): |
| 68 | left = constant_fold_expr(expr.left, cur_mod_id) |
| 69 | right = constant_fold_expr(expr.right, cur_mod_id) |
| 70 | if left is not None and right is not None: |
| 71 | return constant_fold_binary_op(expr.op, left, right) |
| 72 | elif isinstance(expr, UnaryExpr): |
| 73 | value = constant_fold_expr(expr.expr, cur_mod_id) |
| 74 | if value is not None: |
| 75 | return constant_fold_unary_op(expr.op, value) |
| 76 | return None |
| 77 | |
| 78 | |
| 79 | def constant_fold_binary_op( |
no test coverage detected
searching dependent graphs…