17
17
StrExpr ,
18
18
UnaryExpr ,
19
19
Var ,
20
+ CallExpr ,
21
+ MemberExpr ,
22
+ ListExpr ,
20
23
)
21
24
22
25
# All possible result types of constant folding
@@ -73,6 +76,23 @@ def constant_fold_expr(expr: Expression, cur_mod_id: str) -> ConstantValue | Non
73
76
value = constant_fold_expr (expr .expr , cur_mod_id )
74
77
if value is not None :
75
78
return constant_fold_unary_op (expr .op , value )
79
+ # --- f-string constant folding ---
80
+ elif (
81
+ isinstance (expr , CallExpr )
82
+ and isinstance (callee := expr .callee , MemberExpr )
83
+ and isinstance (callee .expr , StrExpr )
84
+ and callee .expr .value == ""
85
+ and callee .name == "join"
86
+ and len (args := expr .args ) == 1
87
+ and isinstance (arg := args [0 ], ListExpr )
88
+ ):
89
+ folded_items = []
90
+ for item in arg .items :
91
+ val = constant_fold_expr (item , cur_mod_id )
92
+ if not isinstance (val , str ):
93
+ return None
94
+ folded_items .append (val )
95
+ return "" .join (folded_items )
76
96
return None
77
97
78
98
@@ -185,3 +205,7 @@ def constant_fold_unary_op(op: str, value: ConstantValue) -> int | float | None:
185
205
elif op == "+" and isinstance (value , (int , float )):
186
206
return value
187
207
return None
208
+
209
+
210
+ def is_f_string_expr (expr : Expression ) -> TypeGuard [CallExpr ]:
211
+
0 commit comments