Skip to content

Commit 34373e3

Browse files
[mypyc] feat: use get_expr_length_value in translate_len (#20074)
Currently, `translate_len` can determine the length of an RTuple at compile time This PR extends this capability to all expressions supported by `get_expr_length_value` This will constant fold the code example displayed in mypyc/mypyc#1152 without waiting for the implementation of #19886 which has a few steps ahead of it Before: ```python def extend_and_specialize(items: list[dict[str, Any]]) -> None: types: Final[dict[str, Any]] = {i["name"]: i for i in items} types.update( { k[len("https://w3id.org/cwl/salad#") :]: v for k, v in types.items() if k.startswith("https://w3id.org/cwl/salad#") } ) ``` After: ```python def extend_and_specialize(items: list[dict[str, Any]]) -> None: types: Final[dict[str, Any]] = {i["name"]: i for i in items} types.update( { k[27 : ]: v for k, v in types.items() if k.startswith("https://w3id.org/cwl/salad#") } ) ``` Even after #19986, this will also work for some situations that constant folding cannot handle but `get_expr_length` can.
1 parent 1cea058 commit 34373e3

File tree

2 files changed

+16
-10
lines changed

2 files changed

+16
-10
lines changed

mypyc/irbuild/specialize.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
is_int64_rprimitive,
7171
is_int_rprimitive,
7272
is_list_rprimitive,
73+
is_sequence_rprimitive,
7374
is_uint8_rprimitive,
7475
list_rprimitive,
7576
object_rprimitive,
@@ -81,6 +82,7 @@
8182
from mypyc.irbuild.constant_fold import constant_fold_expr
8283
from mypyc.irbuild.for_helpers import (
8384
comprehension_helper,
85+
get_expr_length_value,
8486
sequence_from_generator_preallocate_helper,
8587
translate_list_comprehension,
8688
translate_set_comprehension,
@@ -222,17 +224,11 @@ def translate_len(builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Value
222224
if len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]:
223225
arg = expr.args[0]
224226
expr_rtype = builder.node_type(arg)
225-
if isinstance(expr_rtype, RTuple):
226-
# len() of fixed-length tuple can be trivially determined
227-
# statically, though we still need to evaluate it.
228-
builder.accept(arg)
229-
return Integer(len(expr_rtype.types))
227+
# NOTE (?) I'm not sure if my handling of can_borrow is correct here
228+
obj = builder.accept(arg, can_borrow=is_list_rprimitive(expr_rtype))
229+
if is_sequence_rprimitive(expr_rtype) or isinstance(expr_rtype, RTuple):
230+
return get_expr_length_value(builder, arg, obj, expr.line, use_pyssize_t=False)
230231
else:
231-
if is_list_rprimitive(builder.node_type(arg)):
232-
borrow = True
233-
else:
234-
borrow = False
235-
obj = builder.accept(arg, can_borrow=borrow)
236232
return builder.builtin_len(obj, expr.line)
237233
return None
238234

mypyc/test-data/irbuild-basic.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3799,3 +3799,13 @@ L0:
37993799
r2.__mypyc_env__ = r0; r3 = is_error
38003800
wrapper = r2
38013801
return wrapper
3802+
3803+
[case testStaticLength]
3804+
def get_length() -> int:
3805+
return len("https://w3id.org/cwl/salad#")
3806+
[out]
3807+
def get_length():
3808+
r0 :: str
3809+
L0:
3810+
r0 = 'https://w3id.org/cwl/salad#'
3811+
return 54

0 commit comments

Comments
 (0)