Repository: xdslproject/xdsl
Pull request #4418: dialects: (builtin) Add `get_complex_values` and `create_from_complex` to `DenseIntOrFPElementsAttr`
Author: login: erick-xanadu
Labels: name: dialects
description: Changes on the dialects
Created: 2025-05-16T19:31:53Z | Merged: 2025-05-21T19:47:25Z

Adds `get_complex_values` and `create_from_complex` to `DenseIntOrFPElementsAttr`.


Diff:
diff --git a/tests/dialects/test_builtin.py b/tests/dialects/test_builtin.py
index b0a9c5367a..d64e9b90a9 100644
--- a/tests/dialects/test_builtin.py
+++ b/tests/dialects/test_builtin.py
@@ -477,6 +477,32 @@ def test_DenseIntOrFPElementsAttr_values():
         FloatAttr(4.0, f32),
     )
 
+    complex_f32 = ComplexType(f32)
+    complex_f32_attr = DenseIntOrFPElementsAttr.create_dense_complex(
+        TensorType(complex_f32, [2]),
+        [(1.0, 2.0), (3.0, 4.0)],
+    )
+    assert tuple(complex_f32_attr.get_complex_values()) == ((1.0, 2.0), (3.0, 4.0))
+    assert tuple(complex_f32_attr.get_values()) == ((1.0, 2.0), (3.0, 4.0))
+    assert tuple(complex_f32_attr.iter_values()) == ((1.0, 2.0), (3.0, 4.0))
+    with pytest.raises(NotImplementedError):
+        complex_f32_attr.get_attrs()
+    with pytest.raises(NotImplementedError):
+        complex_f32_attr.iter_attrs()
+
+    complex_i32 = ComplexType(i32)
+    complex_i32_attr = DenseIntOrFPElementsAttr.create_dense_complex(
+        TensorType(complex_i32, [2]),
+        [(1, 2), (3, 4)],
+    )
+    assert tuple(complex_i32_attr.get_complex_values()) == ((1, 2), (3, 4))
+    assert tuple(complex_i32_attr.get_values()) == ((1, 2), (3, 4))
+    assert tuple(complex_i32_attr.iter_values()) == ((1, 2), (3, 4))
+    with pytest.raises(NotImplementedError):
+        complex_i32_attr.get_attrs()
+    with pytest.raises(NotImplementedError):
+        complex_i32_attr.iter_attrs()
+
 
 @pytest.mark.parametrize(
     "ref,expected",
diff --git a/xdsl/dialects/builtin.py b/xdsl/dialects/builtin.py
index 2647048484..431857646e 100644
--- a/xdsl/dialects/builtin.py
+++ b/xdsl/dialects/builtin.py
@@ -1018,27 +1018,30 @@ def unpack(
         return tuple(FloatAttr(value, type) for value in type.unpack(buffer, num))
 
 
-ComplexElementT = TypeVar(
-    "ComplexElementT", bound=IntegerType | AnyFloat, default=IntegerType | AnyFloat
+ComplexElementCovT = TypeVar(
+    "ComplexElementCovT",
+    bound=IntegerType | AnyFloat,
+    default=IntegerType | AnyFloat,
+    covariant=True,
 )
 
 
 @irdl_attr_definition
 class ComplexType(
-    Generic[ComplexElementT],
+    Generic[ComplexElementCovT],
     PackableType[tuple[float, float] | tuple[int, int]],
     ParametrizedAttribute,
     BuiltinAttribute,
-    ContainerType[ComplexElementT],
+    ContainerType[ComplexElementCovT],
     TypeAttribute,
 ):
     name = "complex"
-    element_type: ParameterDef[ComplexElementT]
+    element_type: ParameterDef[ComplexElementCovT]
 
-    def __init__(self, element_type: ComplexElementT):
+    def __init__(self, element_type: ComplexElementCovT):
         super().__init__([element_type])
 
-    def get_element_type(self) -> ComplexElementT:
+    def get_element_type(self) -> ComplexElementCovT:
         return self.element_type
 
     @property
@@ -2156,7 +2159,7 @@ def get_element_type(self) -> _UnrankedMemRefTypeElems:
     VectorType[AttributeCovT] | TensorType[AttributeCovT] | MemRefType[AttributeCovT]
 )
 
-AnyDenseElement: TypeAlias = IntegerType | IndexType | AnyFloat
+AnyDenseElement: TypeAlias = IntegerType | IndexType | AnyFloat | ComplexType
 DenseElementCovT = TypeVar(
     "DenseElementCovT", bound=AnyDenseElement, default=AnyDenseElement, covariant=True
 )
@@ -2287,6 +2290,27 @@ def create_dense_float(
 
         return DenseIntOrFPElementsAttr([type, BytesAttr(type.element_type.pack(data))])
 
+    @overload
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[_IntegerTypeInvT]],
+        data: Sequence[tuple[int, int]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[_IntegerTypeInvT]]: ...
+
+    @overload
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[_FloatAttrTypeInvT]],
+        data: Sequence[tuple[float, float]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[_FloatAttrTypeInvT]]: ...
+
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[ComplexElementCovT]],
+        data: Sequence[tuple[float, float]] | Sequence[tuple[int, int]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[ComplexElementCovT]]:
+        return DenseIntOrFPElementsAttr([type, BytesAttr(type.element_type.pack(data))])
+
     @overload
     @staticmethod
     def from_list(
@@ -2394,7 +2418,14 @@ def tensor_from_list(
                 TensorType(data_type, shape), new_data
             )
 
-    def iter_values(self) -> Iterator[int] | Iterator[float]:
+    def iter_values(
+        self,
+    ) -> (
+        Iterator[int]
+        | Iterator[float]
+        | Iterator[tuple[int, int]]
+        | Iterator[tuple[float, float]]
+    ):
         """
         Return an iterator over all the values of the elements in this DenseIntOrFPElementsAttr
         """
@@ -2418,7 +2449,25 @@ def get_float_values(self) -> Sequence[float]:
         assert isinstance(el_type, AnyFloat), el_type
         return el_type.unpack(self.data.data, len(self))
 
-    def get_values(self) -> Sequence[int] | Sequence[float]:
+    def get_complex_values(
+        self,
+    ) -> Sequence[tuple[int, int]] | Sequence[tuple[float, float]]:
+        """
+        Return all the values of the elements in this DenseIntOrFPElementsAttr,
+        checking that the elements are complex.
+        """
+        el_type = self.get_element_type()
+        assert isinstance(el_type, ComplexType), el_type
+        return el_type.unpack(self.data.data, len(self))
+
+    def get_values(
+        self,
+    ) -> (
+        Sequence[int]
+        | Sequence[float]
+        | Sequence[tuple[int, int]]
+        | Sequence[tuple[float, float]]
+    ):
         """
         Return all the values of the elements in this DenseIntOrFPElementsAttr
         """
@@ -2431,8 +2480,9 @@ def iter_attrs(self) -> Iterator[IntegerAttr] | Iterator[FloatAttr]:
         """
         if isinstance(eltype := self.get_element_type(), IntegerType | IndexType):
             return IntegerAttr.iter_unpack(eltype, self.data.data)
-        else:
+        elif isinstance(eltype, AnyFloat):
             return FloatAttr.iter_unpack(eltype, self.data.data)
+        raise NotImplementedError()
 
     def get_attrs(self) -> Sequence[IntegerAttr] | Sequence[FloatAttr]:
         """
@@ -2441,8 +2491,9 @@ def get_attrs(self) -> Sequence[IntegerAttr] | Sequence[FloatAttr]:
         """
         if isinstance(eltype := self.get_element_type(), IntegerType | IndexType):
             return IntegerAttr.unpack(eltype, self.data.data, len(self))
-        else:
+        elif isinstance(eltype, AnyFloat):
             return FloatAttr.unpack(eltype, self.data.data, len(self))
+        raise NotImplementedError()
 
     def is_splat(self) -> bool:
         """
@@ -2457,16 +2508,23 @@ def parse_with_type(parser: AttrParser, type: Attribute) -> TypedAttribute:
         assert isa(type, RankedStructure[AnyDenseElement])
         return parser.parse_dense_int_or_fp_elements_attr(type)
 
-    def _print_one_elem(self, val: int | float, printer: Printer):
+    def _print_one_elem(
+        self, val: int | float | tuple[int, int] | tuple[float, float], printer: Printer
+    ):
         if isinstance(val, int):
             element_type = cast(IntegerType | IndexType, self.get_element_type())
             element_type.print_value_without_type(val, printer)
-        else:  # float
+        elif isinstance(val, float):
             printer.print_float(val, cast(AnyFloat, self.get_element_type()))
+        else:
+            raise NotImplementedError("Next PR")
 
     def _print_dense_list(
         self,
-        array: Sequence[int] | Sequence[float],
+        array: Sequence[int]
+        | Sequence[float]
+        | Sequence[tuple[int, int]]
+        | Sequence[tuple[float, float]],
         shape: Sequence[int],
         printer: Printer,
     ):
diff --git a/xdsl/parser/attribute_parser.py b/xdsl/parser/attribute_parser.py
index f1e9c61982..170e1abb29 100644
--- a/xdsl/parser/attribute_parser.py
+++ b/xdsl/parser/attribute_parser.py
@@ -978,7 +978,14 @@ def to_float(self, parser: AttrParser) -> float:
             """
             return float(self.value)
 
-        def to_type(self, parser: AttrParser, type: AnyFloat | IntegerType | IndexType):
+        def to_type(
+            self,
+            parser: AttrParser,
+            type: AnyFloat | IntegerType | IndexType | ComplexType,
+        ):
+            if isinstance(type, ComplexType):
+                raise NotImplementedError("Implemented in follow up PR")
+
             if isinstance(type, AnyFloat):
                 return self.to_float(parser)
 
diff --git a/xdsl/printer.py b/xdsl/printer.py
index 66707ae66e..8480b32e3d 100644
--- a/xdsl/printer.py
+++ b/xdsl/printer.py
@@ -19,7 +19,7 @@
     BFloat16Type,
     BoolAttr,
     BytesAttr,
-    ComplexElementT,
+    ComplexElementCovT,
     ComplexType,
     DenseArrayBase,
     DenseResourceAttr,
@@ -343,7 +343,7 @@ def print_float_attr(self, attribute: FloatAttr):
         self.print_float(attribute.value.data, attribute.type)
 
     def print_complex_float(
-        self, value: tuple[float, float], type: ComplexType[ComplexElementT]
+        self, value: tuple[float, float], type: ComplexType[ComplexElementCovT]
     ):
         assert isinstance(type.element_type, AnyFloat)
         self.print_string("(")
@@ -354,7 +354,7 @@ def print_complex_float(
         self.print_string(")")
 
     def print_complex_int(
-        self, value: tuple[int, int], type: ComplexType[ComplexElementT]
+        self, value: tuple[int, int], type: ComplexType[ComplexElementCovT]
     ):
         assert isinstance(type.element_type, IntegerType)
         self.print_string("(")
@@ -367,7 +367,7 @@ def print_complex_int(
     def print_complex(
         self,
         value: tuple[float, float] | tuple[int, int],
-        type: ComplexType[ComplexElementT],
+        type: ComplexType[ComplexElementCovT],
     ):
         if isinstance(type.element_type, IntegerType):
             assert isa(value, tuple[int, int])


Reviews:
user: login: erick-xanadu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T20:49:58Z
user: login: erick-xanadu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T20:51:23Z
user: login: superlopuh
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-21T07:41:30Z
user: login: superlopuh
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-21T07:43:05Z
user: login: superlopuh
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-21T07:49:00Z
user: login: alexarice
body: This looks good to me, thanks for splitting things up. Left a couple of small comments.
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-21T09:43:43Z
user: login: erick-xanadu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T13:06:57Z
user: login: alexarice
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T13:08:51Z
user: login: erick-xanadu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T13:10:29Z
user: login: erick-xanadu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T13:11:11Z
user: login: erick-xanadu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T13:17:02Z
user: login: erick-xanadu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T13:17:35Z
user: login: erick-xanadu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T13:17:58Z
user: login: alexarice
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-21T13:20:04Z
user: login: superlopuh
body: beautiful
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-21T14:29:34Z

Review comments:
diff_hunk: @@ -976,12 +985,50 @@ def to_float(self, parser: AttrParser) -> float:
             Convert the element to a float value. Raises an error if the type
             is compatible.
             """
+            if isinstance(self.value, tuple):
+                raise NotImplementedError()
             return float(self.value)
 
-        def to_type(self, parser: AttrParser, type: AnyFloat | IntegerType | IndexType):
+        def to_complex(
+            self, parser: AttrParser, type: ComplexType
+        ) -> tuple[float, float] | tuple[int, int]:
+            if isinstance(self.value, int) and isinstance(
+                type.element_type, IntegerType
+            ):
+                return (self.value, 0)
+            elif isinstance(self.value, int) and isinstance(
+                type.element_type, AnyFloat
+            ):
+                return (float(self.value), 0.0)
+            elif isinstance(self.value, float) and isinstance(
+                type.element_type, AnyFloat
+            ):
+                return (self.value, 0.0)
+            elif isinstance(self.value, float) and isinstance(
+                type.element_type, IntegerType
+            ):
+                return (int(self.value), 0)
path: xdsl/parser/attribute_parser.py
user: login: erick-xanadu
body: These should not be reachable from the normal execution, but technically one could instantiate a `_TensorLiteralElement(true, 1, span)` and call `to_complex`. In my view, we could delete them.
created_at: 2025-05-16T20:49:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1007,7 +1054,18 @@ def _parse_optional_int_or_float(
         minus_token = self._parse_optional_token(MLIRTokenKind.MINUS)
         is_negative = minus_token is not None
 
-        if self._current_token.kind == MLIRTokenKind.INTEGER_LIT:
+        if self._current_token.kind == MLIRTokenKind.BARE_IDENT and not is_negative:
+            if self._current_token.text == "true":
+                token = self._consume_token(MLIRTokenKind.BARE_IDENT)
+                value = 1
+            elif self._current_token.text == "false":
+                token = self._consume_token(MLIRTokenKind.BARE_IDENT)
+                value = 0
+            else:
+                self._resume_from(pos)
+                return None
path: xdsl/parser/attribute_parser.py
user: login: erick-xanadu
body: This change makes it so we can also parse `tensor<...xi1>`
created_at: 2025-05-16T20:51:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1019,7 +1024,10 @@ def unpack(
 
 
 ComplexElementT = TypeVar(
-    "ComplexElementT", bound=IntegerType | AnyFloat, default=IntegerType | AnyFloat
+    "ComplexElementT",
+    bound=IntegerType | AnyFloat,
+    default=IntegerType | AnyFloat,
+    covariant=True,
 )
path: xdsl/dialects/builtin.py
user: login: superlopuh
body: We use a naming convention that would suggest either renaming this to `ComplexElementCovT` or adding a new one below, your call
created_at: 2025-05-21T07:41:30Z
author_association: MEMBER
diff_hunk: @@ -2287,6 +2295,34 @@ def create_dense_float(
 
         return DenseIntOrFPElementsAttr([type, BytesAttr(type.element_type.pack(data))])
 
+    @overload
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[_IntegerTypeInvT]],
+        data: Sequence[tuple[int, int]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[_IntegerTypeInvT]]: ...
+
+    @overload
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[_FloatAttrTypeInvT]],
+        data: Sequence[tuple[float, float]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[_FloatAttrTypeInvT]]: ...
+
+    @overload
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[ComplexElementT]],
+        data: Sequence[tuple[float, float]] | Sequence[tuple[int, int]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[ComplexElementT]]: ...
path: xdsl/dialects/builtin.py
user: login: superlopuh
body: Do we need this overload?
created_at: 2025-05-21T07:43:04Z
author_association: MEMBER
diff_hunk: @@ -2398,7 +2434,11 @@ def iter_values(self) -> Iterator[int] | Iterator[float]:
         """
         Return an iterator over all the values of the elements in this DenseIntOrFPElementsAttr
         """
-        return self.get_element_type().iter_unpack(self.data.data)
+        if isinstance(
+            eltype := self.get_element_type(), IntegerType | IndexType | AnyFloat
+        ):
+            return eltype.iter_unpack(self.data.data)
+        raise NotImplementedError()
path: xdsl/dialects/builtin.py
user: login: superlopuh
body: why not implement this?
created_at: 2025-05-21T07:49:00Z
author_association: MEMBER
diff_hunk: @@ -647,6 +647,11 @@ def format(self) -> str:
 AnySignlessIntegerType: TypeAlias = Annotated[IntegerType, SignlessIntegerConstraint]
 """Type alias constrained to signless IntegerType."""
 
+_IntegerType = TypeVar(
path: xdsl/dialects/builtin.py
user: login: alexarice
body: ```suggestion
_IntegerTypeCovT = TypeVar(
```
We should document this somewhere, but in the xDSL meeting we decided to try to end every typevar namewith `InvT` `CovT` or `ContrT`
created_at: 2025-05-21T09:38:27Z
author_association: COLLABORATOR
diff_hunk: @@ -978,7 +978,14 @@ def to_float(self, parser: AttrParser) -> float:
             """
             return float(self.value)
 
-        def to_type(self, parser: AttrParser, type: AnyFloat | IntegerType | IndexType):
+        def to_type(
path: xdsl/parser/attribute_parser.py
user: login: alexarice
body: This looks like it should be in the next PR?
created_at: 2025-05-21T09:40:51Z
author_association: COLLABORATOR
diff_hunk: @@ -2457,16 +2517,23 @@ def parse_with_type(parser: AttrParser, type: Attribute) -> TypedAttribute:
         assert isa(type, RankedStructure[AnyDenseElement])
         return parser.parse_dense_int_or_fp_elements_attr(type)
 
-    def _print_one_elem(self, val: int | float, printer: Printer):
+    def _print_one_elem(
path: xdsl/dialects/builtin.py
user: login: alexarice
body: Same with this, is this meant to be in this PR?
created_at: 2025-05-21T09:41:08Z
author_association: COLLABORATOR
diff_hunk: @@ -2398,7 +2434,11 @@ def iter_values(self) -> Iterator[int] | Iterator[float]:
         """
         Return an iterator over all the values of the elements in this DenseIntOrFPElementsAttr
         """
-        return self.get_element_type().iter_unpack(self.data.data)
+        if isinstance(
+            eltype := self.get_element_type(), IntegerType | IndexType | AnyFloat
+        ):
+            return eltype.iter_unpack(self.data.data)
+        raise NotImplementedError()
path: xdsl/dialects/builtin.py
user: login: alexarice
body: I agree, shouldn't this be the same as the others?
created_at: 2025-05-21T09:43:06Z
author_association: COLLABORATOR
diff_hunk: @@ -2457,16 +2517,23 @@ def parse_with_type(parser: AttrParser, type: Attribute) -> TypedAttribute:
         assert isa(type, RankedStructure[AnyDenseElement])
         return parser.parse_dense_int_or_fp_elements_attr(type)
 
-    def _print_one_elem(self, val: int | float, printer: Printer):
+    def _print_one_elem(
path: xdsl/dialects/builtin.py
user: login: erick-xanadu
body: No, I believe this change is necessary here for pyright. If I don't have this change, then:

```python
    def print_without_type(self, printer: Printer):
        printer.print_string("dense<")
        data = self.get_values()                               # <---  data could be tuple[int, int] | tuple[float, float]
        shape = self.get_shape() if self.shape_is_complete else (len(data),)
        assert shape is not None, "If shape is complete, then it cannot be None"
        if len(data) == 0:
            pass
        elif self.is_splat():
            self._print_one_elem(data[0], printer)     # <--- flows here
        elif len(self) > 100:
            printer.print('"', "0x", self.data.data.hex().upper(), '"')
        else:
            self._print_dense_list(data, shape, printer)   # <---- and here which also flows to print_one_elem
        printer.print_string(">")
```

Otherwise, we need some other pyright ignore comments. Let me know what you think.
created_at: 2025-05-21T13:06:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2457,16 +2517,23 @@ def parse_with_type(parser: AttrParser, type: Attribute) -> TypedAttribute:
         assert isa(type, RankedStructure[AnyDenseElement])
         return parser.parse_dense_int_or_fp_elements_attr(type)
 
-    def _print_one_elem(self, val: int | float, printer: Printer):
+    def _print_one_elem(
path: xdsl/dialects/builtin.py
user: login: alexarice
body: Fair enough, I guess it's just a choice of where to put the `NotImplementedError` so here is fine.
created_at: 2025-05-21T13:08:51Z
author_association: COLLABORATOR
diff_hunk: @@ -978,7 +978,14 @@ def to_float(self, parser: AttrParser) -> float:
             """
             return float(self.value)
 
-        def to_type(self, parser: AttrParser, type: AnyFloat | IntegerType | IndexType):
+        def to_type(
path: xdsl/parser/attribute_parser.py
user: login: erick-xanadu
body: No. We need this change here again for pyright because:

```python
    def parse_dense_int_or_fp_elements_attr(
        self, type: RankedStructure[AnyDenseElement] | None # AnyDenseElement now includes ComplexType
    ) -> DenseIntOrFPElementsAttr:

            # ... snip ...

            # Tensor literal case
            dense_values, shape = dense_contents
            data_values = [
                # type.element_type may be ComplexType
                value.to_type(self, type.element_type) for value in dense_values 
            ]
            # Elements from _parse_tensor_literal need to be converted to values.

```
created_at: 2025-05-21T13:10:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1019,7 +1024,10 @@ def unpack(
 
 
 ComplexElementT = TypeVar(
-    "ComplexElementT", bound=IntegerType | AnyFloat, default=IntegerType | AnyFloat
+    "ComplexElementT",
+    bound=IntegerType | AnyFloat,
+    default=IntegerType | AnyFloat,
+    covariant=True,
 )
path: xdsl/dialects/builtin.py
user: login: erick-xanadu
body: https://github.com/xdslproject/xdsl/pull/4418/commits/cac044163589200cb49fba3994c02dc7df971f1d
created_at: 2025-05-21T13:11:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -647,6 +647,11 @@ def format(self) -> str:
 AnySignlessIntegerType: TypeAlias = Annotated[IntegerType, SignlessIntegerConstraint]
 """Type alias constrained to signless IntegerType."""
 
+_IntegerType = TypeVar(
path: xdsl/dialects/builtin.py
user: login: erick-xanadu
body: https://github.com/xdslproject/xdsl/pull/4418/commits/b6f5d62cd3fbbc92b8942900abd53d54aae0a379 I think this CovT is used in the next. For this PR it is unused.
created_at: 2025-05-21T13:17:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2287,6 +2295,34 @@ def create_dense_float(
 
         return DenseIntOrFPElementsAttr([type, BytesAttr(type.element_type.pack(data))])
 
+    @overload
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[_IntegerTypeInvT]],
+        data: Sequence[tuple[int, int]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[_IntegerTypeInvT]]: ...
+
+    @overload
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[_FloatAttrTypeInvT]],
+        data: Sequence[tuple[float, float]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[_FloatAttrTypeInvT]]: ...
+
+    @overload
+    @staticmethod
+    def create_dense_complex(
+        type: RankedStructure[ComplexType[ComplexElementT]],
+        data: Sequence[tuple[float, float]] | Sequence[tuple[int, int]],
+    ) -> DenseIntOrFPElementsAttr[ComplexType[ComplexElementT]]: ...
path: xdsl/dialects/builtin.py
user: login: erick-xanadu
body: Not any more! Thanks: https://github.com/xdslproject/xdsl/pull/4418/commits/c045cd36a7e995fd07857e9668c25da386f5e105
created_at: 2025-05-21T13:17:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2398,7 +2434,11 @@ def iter_values(self) -> Iterator[int] | Iterator[float]:
         """
         Return an iterator over all the values of the elements in this DenseIntOrFPElementsAttr
         """
-        return self.get_element_type().iter_unpack(self.data.data)
+        if isinstance(
+            eltype := self.get_element_type(), IntegerType | IndexType | AnyFloat
+        ):
+            return eltype.iter_unpack(self.data.data)
+        raise NotImplementedError()
path: xdsl/dialects/builtin.py
user: login: erick-xanadu
body: https://github.com/xdslproject/xdsl/pull/4418/commits/c44746e9a8e545c13f8c03824bc39eafe201163f
created_at: 2025-05-21T13:17:58Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-05-16T20:12:16Z
body: ## [Codecov](https://app.codecov.io/gh/xdslproject/xdsl/pull/4418?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=xdslproject) Report
:x: Patch coverage is `54.54545%` with `15 lines` in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 89.18%. Comparing base ([`5e44784`](https://app.codecov.io/gh/xdslproject/xdsl/commit/5e44784f56a4019e51b3c59a580242b07a6107a3?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=xdslproject)) to head ([`b6f5d62`](https://app.codecov.io/gh/xdslproject/xdsl/commit/b6f5d62cd3fbbc92b8942900abd53d54aae0a379?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=xdslproject)).
:warning: Report is 583 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/xdslproject/xdsl/pull/4418?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=xdslproject) | Patch % | Lines |
|---|---|---|
| [xdsl/dialects/builtin.py](https://app.codecov.io/gh/xdslproject/xdsl/pull/4418?src=pr&el=tree&filepath=xdsl%2Fdialects%2Fbuiltin.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=xdslproject#diff-eGRzbC9kaWFsZWN0cy9idWlsdGluLnB5) | 51.61% | [12 Missing and 3 partials :warning: ](https://app.codecov.io/gh/xdslproject/xdsl/pull/4418?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=xdslproject) |

<details><summary>Additional details and impacted files</summary>



```diff
@@            Coverage Diff             @@
##             main    #4418      +/-   ##
==========================================
+ Coverage   89.13%   89.18%   +0.05%     
==========================================
  Files         336      339       +3     
  Lines       45650    45873     +223     
  Branches     5611     5624      +13     
==========================================
+ Hits        40691    40913     +222     
- Misses       3561     3563       +2     
+ Partials     1398     1397       -1     
```
</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/xdslproject/xdsl/pull/4418?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=xdslproject).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=xdslproject).
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: superlopuh
created_at: 2025-05-18T19:40:51Z
body: I'm confused about your question and this PR. Are these exactly the same changes? Feels like we could've discussed this on Zulip or on the other PR, but I'm happy to answer here if that's easier. I was thinking of reviewing changes to `builtin.py` separately from the parser, since one strictly depends on the other, so remove everything that's actually to do with printing and parsing from this one, and add tests for the changes in initializers.
author_association: MEMBER
user: login: erick-xanadu
created_at: 2025-05-20T18:50:09Z
body: @superlopuh thanks for the clarification, I have kept the changes minimal here to only the builtin dialect. 
author_association: CONTRIBUTOR