Skip to content

Commit 4ddbe19

Browse files
committed
[mypyc] Improve support for frozenset
1 parent d4e7a81 commit 4ddbe19

File tree

11 files changed

+675
-4
lines changed

11 files changed

+675
-4
lines changed

mypyc/codegen/emit.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
is_dict_rprimitive,
3636
is_fixed_width_rtype,
3737
is_float_rprimitive,
38+
is_frozenset_rprimitive,
3839
is_int16_rprimitive,
3940
is_int32_rprimitive,
4041
is_int64_rprimitive,
@@ -613,6 +614,7 @@ def emit_cast(
613614
is_list_rprimitive(typ)
614615
or is_dict_rprimitive(typ)
615616
or is_set_rprimitive(typ)
617+
or is_frozenset_rprimitive(typ)
616618
or is_str_rprimitive(typ)
617619
or is_range_rprimitive(typ)
618620
or is_float_rprimitive(typ)
@@ -629,6 +631,8 @@ def emit_cast(
629631
prefix = "PyDict"
630632
elif is_set_rprimitive(typ):
631633
prefix = "PySet"
634+
elif is_frozenset_rprimitive(typ):
635+
prefix = "PyFrozenSet"
632636
elif is_str_rprimitive(typ):
633637
prefix = "PyUnicode"
634638
elif is_range_rprimitive(typ):

mypyc/doc/frozenset_operations.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
.. _set-ops:
2+
3+
Native frozenset operations
4+
======================
5+
6+
These ``frozenset`` operations have fast, optimized implementations. Other
7+
frozenset operations use generic implementations that are often slower.
8+
9+
Construction
10+
------------
11+
12+
Construct empty frozenset:
13+
14+
* ``frozenset()``
15+
16+
Construct frozenset from iterable:
17+
18+
* ``frozenset(x: Iterable)``
19+
20+
21+
Operators
22+
---------
23+
24+
* ``item in s``
25+
26+
Functions
27+
---------
28+
29+
* ``len(s: set)``

mypyc/doc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ generate fast code.
4141
dict_operations
4242
set_operations
4343
tuple_operations
44+
frozenset_operations
4445

4546
.. toctree::
4647
:maxdepth: 2

mypyc/ir/rtypes.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,11 @@ def __hash__(self) -> int:
461461
# Python set object (or an instance of a subclass of set).
462462
set_rprimitive: Final = RPrimitive("builtins.set", is_unboxed=False, is_refcounted=True)
463463

464+
# Python frozenset object (or an instance of a subclass of frozenset).
465+
frozenset_rprimitive: Final = RPrimitive(
466+
"builtins.frozenset", is_unboxed=False, is_refcounted=True
467+
)
468+
464469
# Python str object. At the C layer, str is referred to as unicode
465470
# (PyUnicode).
466471
str_rprimitive: Final = RPrimitive("builtins.str", is_unboxed=False, is_refcounted=True)
@@ -565,6 +570,10 @@ def is_set_rprimitive(rtype: RType) -> bool:
565570
return isinstance(rtype, RPrimitive) and rtype.name == "builtins.set"
566571

567572

573+
def is_frozenset_rprimitive(rtype: RType) -> bool:
574+
return isinstance(rtype, RPrimitive) and rtype.name == "builtins.frozenset"
575+
576+
568577
def is_str_rprimitive(rtype: RType) -> bool:
569578
return isinstance(rtype, RPrimitive) and rtype.name == "builtins.str"
570579

mypyc/irbuild/ll_builder.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
is_dict_rprimitive,
102102
is_fixed_width_rtype,
103103
is_float_rprimitive,
104+
is_frozenset_rprimitive,
104105
is_int16_rprimitive,
105106
is_int32_rprimitive,
106107
is_int64_rprimitive,
@@ -2225,7 +2226,7 @@ def builtin_len(self, val: Value, line: int, use_pyssize_t: bool = False) -> Val
22252226
size_value = None
22262227
if is_list_rprimitive(typ) or is_tuple_rprimitive(typ) or is_bytes_rprimitive(typ):
22272228
size_value = self.primitive_op(var_object_size, [val], line)
2228-
elif is_set_rprimitive(typ):
2229+
elif is_set_rprimitive(typ) or is_frozenset_rprimitive(typ):
22292230
elem_address = self.add(GetElementPtr(val, PySetObject, "used"))
22302231
size_value = self.add(LoadMem(c_pyssize_t_rprimitive, elem_address))
22312232
self.add(KeepAlive([val]))

mypyc/irbuild/mapper.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
bytes_rprimitive,
3434
dict_rprimitive,
3535
float_rprimitive,
36+
frozenset_rprimitive,
3637
int16_rprimitive,
3738
int32_rprimitive,
3839
int64_rprimitive,
@@ -89,6 +90,8 @@ def type_to_rtype(self, typ: Type | None) -> RType:
8990
return dict_rprimitive
9091
elif typ.type.fullname == "builtins.set":
9192
return set_rprimitive
93+
elif typ.type.fullname == "builtins.frozenset":
94+
return frozenset_rprimitive
9295
elif typ.type.fullname == "builtins.tuple":
9396
return tuple_rprimitive # Varying-length tuple
9497
elif typ.type.fullname == "builtins.range":

mypyc/primitives/set_ops.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Primitive set (and frozenset) ops."""
1+
"""Primitive set and frozenset ops."""
22

33
from __future__ import annotations
44

@@ -7,6 +7,7 @@
77
bit_rprimitive,
88
bool_rprimitive,
99
c_int_rprimitive,
10+
frozenset_rprimitive,
1011
object_rprimitive,
1112
pointer_rprimitive,
1213
set_rprimitive,
@@ -44,11 +45,21 @@
4445
error_kind=ERR_MAGIC,
4546
)
4647

48+
# Construct an empty frozenset
49+
function_op(
50+
name="builtins.frozenset",
51+
arg_types=[],
52+
return_type=frozenset_rprimitive,
53+
c_function_name="PyFrozenSet_New",
54+
error_kind=ERR_MAGIC,
55+
extra_int_constants=[(0, pointer_rprimitive)],
56+
)
57+
4758
# frozenset(obj)
4859
function_op(
4960
name="builtins.frozenset",
5061
arg_types=[object_rprimitive],
51-
return_type=object_rprimitive,
62+
return_type=frozenset_rprimitive,
5263
c_function_name="PyFrozenSet_New",
5364
error_kind=ERR_MAGIC,
5465
)
@@ -64,6 +75,17 @@
6475
ordering=[1, 0],
6576
)
6677

78+
# item in frozenset
79+
binary_op(
80+
name="in",
81+
arg_types=[object_rprimitive, frozenset_rprimitive],
82+
return_type=c_int_rprimitive,
83+
c_function_name="PySet_Contains",
84+
error_kind=ERR_NEG_INT,
85+
truncated_type=bool_rprimitive,
86+
ordering=[1, 0],
87+
)
88+
6789
# set.remove(obj)
6890
method_op(
6991
name="remove",

0 commit comments

Comments
 (0)