Skip to content

Commit ad2cd9c

Browse files
[mypyc] feat: extend get_expr_len to try constant_fold_expr
get_expr_len currently support StrExpr, BytesExpr, and string-type Final values constant_fold_expr already has the code to parse values from all of these, so we can deduplicate code by using it It's able to parse a few more Expressions than our existing implementation, and allows get_expr_length to automatically benefit from future constant-folding enhancements
1 parent 19697af commit ad2cd9c

File tree

1 file changed

+8
-14
lines changed

1 file changed

+8
-14
lines changed

mypyc/irbuild/for_helpers.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
short_int_rprimitive,
6666
)
6767
from mypyc.irbuild.builder import IRBuilder
68+
from mypyc.irbuild.constant_fold import constant_fold_expr
6869
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
6970
from mypyc.irbuild.targets import AssignmentTarget, AssignmentTargetTuple
7071
from mypyc.primitives.dict_ops import (
@@ -1180,26 +1181,19 @@ def gen_cleanup(self) -> None:
11801181
gen.gen_cleanup()
11811182

11821183

1183-
def get_expr_length(expr: Expression) -> int | None:
1184-
if isinstance(expr, (StrExpr, BytesExpr)):
1185-
return len(expr.value)
1184+
def get_expr_length(builder: IRBuilder, expr: Expression) -> int | None:
1185+
folded = constant_fold_expr(builder, expr)
1186+
if isinstance(folded, (str, bytes)):
1187+
return len(folded)
11861188
elif isinstance(expr, (ListExpr, TupleExpr)):
11871189
# if there are no star expressions, or we know the length of them,
11881190
# we know the length of the expression
1189-
stars = [get_expr_length(i) for i in expr.items if isinstance(i, StarExpr)]
1191+
stars = [get_expr_length(builder, i) for i in expr.items if isinstance(i, StarExpr)]
11901192
if None not in stars:
11911193
other = sum(not isinstance(i, StarExpr) for i in expr.items)
11921194
return other + sum(stars) # type: ignore [arg-type]
11931195
elif isinstance(expr, StarExpr):
1194-
return get_expr_length(expr.expr)
1195-
elif (
1196-
isinstance(expr, RefExpr)
1197-
and isinstance(expr.node, Var)
1198-
and expr.node.is_final
1199-
and isinstance(expr.node.final_value, str)
1200-
and expr.node.has_explicit_value
1201-
):
1202-
return len(expr.node.final_value)
1196+
return get_expr_length(builder, expr.expr)
12031197
# TODO: extend this, passing length of listcomp and genexp should have worthwhile
12041198
# performance boost and can be (sometimes) figured out pretty easily. set and dict
12051199
# comps *can* be done as well but will need special logic to consider the possibility
@@ -1212,7 +1206,7 @@ def get_expr_length_value(
12121206
) -> Value:
12131207
rtype = builder.node_type(expr)
12141208
assert is_sequence_rprimitive(rtype), rtype
1215-
length = get_expr_length(expr)
1209+
length = get_expr_length(builder, expr)
12161210
if length is None:
12171211
# We cannot compute the length at compile time, so we will fetch it.
12181212
return builder.builder.builtin_len(expr_reg, line, use_pyssize_t=use_pyssize_t)

0 commit comments

Comments
 (0)