Skip to content

Context

context

Context dataclass

Contains structures for operations/attributes registration.

Source code in xdsl/context.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
@dataclass
class Context:
    """Contains structures for operations/attributes registration."""

    allow_unregistered: bool = field(default=False)

    _loaded_dialects: dict[str, Dialect] = field(default_factory=dict[str, Dialect])
    _loaded_ops: dict[str, type[Operation]] = field(
        default_factory=dict[str, type[Operation]]
    )
    _loaded_attrs: dict[str, type[Attribute]] = field(
        default_factory=dict[str, type[Attribute]]
    )
    _loaded_types: dict[str, type[TypeAttribute]] = field(
        default_factory=dict[str, type[TypeAttribute]]
    )
    _registered_dialects: dict[str, Callable[[], Dialect]] = field(
        default_factory=dict[str, Callable[[], Dialect]]
    )
    """
    A dictionary of all registered dialects that are not yet loaded. This is used to
    only load the respective Python files when the dialect is actually used.
    """

    def clone(self) -> "Context":
        return Context(
            self.allow_unregistered,
            self._loaded_dialects.copy(),
            self._loaded_ops.copy(),
            self._loaded_attrs.copy(),
            self._loaded_types.copy(),
            self._registered_dialects.copy(),
        )

    @property
    def loaded_ops(self) -> "Iterable[type[Operation]]":
        """
        Returns all the loaded operations. Not valid across mutations of this object.
        """
        return self._loaded_ops.values()

    @property
    def loaded_attrs(self) -> "Iterable[type[Attribute]]":
        """
        Returns all the loaded attributes. Not valid across mutations of this object.
        """
        return self._loaded_attrs.values()

    @property
    def loaded_types(self) -> Iterable[type[TypeAttribute]]:
        """
        Returns all the loaded types. Not valid across mutations of this object.
        """
        return self._loaded_types.values()

    @property
    def loaded_dialects(self) -> "Iterable[Dialect]":
        """
        Returns all the loaded attributes. Not valid across mutations of this object.
        """
        return self._loaded_dialects.values()

    @property
    def registered_dialect_names(self) -> Iterable[str]:
        """
        Returns the names of all registered dialects. Not valid across mutations of this object.
        """
        return self._registered_dialects.keys()

    def register_dialect(
        self, name: str, dialect_factory: "Callable[[], Dialect]"
    ) -> None:
        """
        Register a dialect without loading it. The dialect is only loaded in the context
        when an operation or attribute of that dialect is parsed, or when explicitely
        requested with `load_registered_dialect`.
        """
        if name in self._registered_dialects:
            raise AlreadyRegisteredConstructException(
                f"'{name}' dialect is already registered"
            )
        self._registered_dialects[name] = dialect_factory

    def load_registered_dialect(self, name: str) -> None:
        """Load a dialect that is already registered in the context."""
        if name not in self._registered_dialects:
            raise UnregisteredConstructException(f"'{name}' dialect is not registered")
        dialect = self._registered_dialects[name]()
        self._loaded_dialects[dialect.name] = dialect

        for op in dialect.operations:
            self.load_op(op)

        for attr in dialect.attributes:
            self.load_attr_or_type(attr)

    def load_dialect(self, dialect: "Dialect"):
        """
        Load a dialect. Operation and Attribute names should be unique.
        If the dialect is already registered in the context, use
        `load_registered_dialect` instead.
        """
        if dialect.name in self._registered_dialects:
            raise AlreadyRegisteredConstructException(
                f"'{dialect.name}' dialect is already registered, use 'load_registered_dialect' instead"
            )
        self.register_dialect(dialect.name, lambda: dialect)
        self.load_registered_dialect(dialect.name)

    def load_op(self, op: "type[Operation]") -> None:
        """Load an operation definition. Operation names should be unique."""
        if op.name in self._loaded_ops:
            raise AlreadyRegisteredConstructException(
                f"Operation {op.name} has already been loaded"
            )
        self._loaded_ops[op.name] = op

    def load_attr_or_type(self, attr: type[Attribute]) -> None:
        """
        Load an attribute or type definition.
        Attribute or type names should be unique, but an attribute may have the same
        name as a type.
        """
        if issubclass(attr, TypeAttribute):
            if attr.name in self._loaded_types:
                raise AlreadyRegisteredConstructException(
                    f"Type {attr.name} has already been loaded"
                )
            self._loaded_types[attr.name] = attr
        else:
            if attr.name in self._loaded_attrs:
                raise AlreadyRegisteredConstructException(
                    f"Attribute {attr.name} has already been loaded"
                )
            self._loaded_attrs[attr.name] = attr

    def _get_known_op(self, name: str) -> "type[Operation] | None":
        if name in self._loaded_ops:
            return self._loaded_ops[name]
        if "." in name:
            dialect_name, _ = Dialect.split_name(name)
            if (
                dialect_name in self._registered_dialects
                and dialect_name not in self._loaded_dialects
            ):
                self.load_registered_dialect(dialect_name)
                return self._get_known_op(name)

    def get_optional_op(
        self, name: str, *, dialect_stack: Sequence[str] = ()
    ) -> "type[Operation] | None":
        """
        Get an operation class from its name if it exists or is contained in one of the
        dialects in the dialect stack.
        If the operation is not registered, return None unless unregistered operations
        are allowed in the context, in which case return an UnregisteredOp.
        """
        # Check if the name is known.
        if op_type := self._get_known_op(name):
            return op_type

        # Check appending each dialect in the dialect stack.
        for dialect_name in reversed(dialect_stack):
            dialect_and_name = f"{dialect_name}.{name}"
            if op_type := self._get_known_op(dialect_and_name):
                return op_type

        # If the context allows unregistered operations then create an UnregisteredOp
        if self.allow_unregistered:
            from xdsl.dialects.builtin import UnregisteredOp

            op_type = UnregisteredOp.with_name(name)
            self._loaded_ops[name] = op_type
            return op_type

    def get_op(
        self, name: str, *, dialect_stack: Sequence[str] = ()
    ) -> "type[Operation]":
        """
        Get an operation class from its name if it exists or is contained in one of the
        dialects in the dialect stack.
        If the operation is not registered, raise an exception unless unregistered
        operations are allowed in the context, in which case return an UnregisteredOp.
        """
        if op_type := self.get_optional_op(name, dialect_stack=dialect_stack):
            return op_type
        raise UnregisteredConstructException(f"Operation {name} is not registered")

    def get_optional_type(self, name: str) -> type[TypeAttribute] | None:
        """
        Get a type definition from its name if it exists.
        If the type is not registered, return None unless unregistered types
        are allowed in the context, in which case return an UnregisteredAttr.
        """
        # If the type is already loaded, returns it.
        if name in self._loaded_types:
            return self._loaded_types[name]

        # Otherwise, check if the type dialect is registered.
        dialect_name, _ = Dialect.split_name(name)
        if (dialect_name in self._registered_dialects) and (
            dialect_name not in self._loaded_dialects
        ):
            self.load_registered_dialect(dialect_name)
            return self.get_optional_type(name)

        # If the dialect is unregistered, but the context allows unregistered
        # dialects, return an UnregisteredAttr.
        if self.allow_unregistered:
            from xdsl.dialects.builtin import UnregisteredAttr

            attr_type = UnregisteredAttr.with_name_and_type(name, True)
            assert issubclass(attr_type, TypeAttribute)
            self._loaded_types[name] = attr_type
            return attr_type

    def get_type(self, name: str) -> type[TypeAttribute]:
        """
        Get a type definition from its name.
        If the type is not registered, raise an exception unless unregistered
        types are allowed in the context, in which case return an UnregisteredAttr.
        """
        if attr_type := self.get_optional_type(name):
            return attr_type
        raise UnregisteredConstructException(f"Type {name} is not registered")

    def get_optional_attr(
        self,
        name: str,
    ) -> "type[Attribute] | None":
        """
        Get an attribute class from its name if it exists.
        If the attribute is not registered, return None unless unregistered attributes
        are allowed in the context, in which case return an UnregisteredAttr.
        """
        # If the attribute is already loaded, returns it.
        if name in self._loaded_attrs:
            return self._loaded_attrs[name]

        # Otherwise, check if the attribute dialect is registered.
        dialect_name, _ = Dialect.split_name(name)
        if (
            dialect_name in self._registered_dialects
            and dialect_name not in self._loaded_dialects
        ):
            self.load_registered_dialect(dialect_name)
            return self.get_optional_attr(name)

        # If the dialect is unregistered, but the context allows unregistered
        # attributes, return an UnregisteredOp.
        if self.allow_unregistered:
            from xdsl.dialects.builtin import UnregisteredAttr

            attr_type = UnregisteredAttr.with_name_and_type(name, False)
            self._loaded_attrs[name] = attr_type
            return attr_type

        return None

    def get_attr(
        self,
        name: str,
    ) -> "type[Attribute]":
        """
        Get an attribute class from its name.
        If the attribute is not registered, raise an exception unless unregistered
        attributes are allowed in the context, in which case return an UnregisteredAttr.
        """
        if attr_type := self.get_optional_attr(name):
            return attr_type
        raise UnregisteredConstructException(f"Attribute {name} is not registered")

    def get_dialect(self, name: str) -> "Dialect":
        if (dialect := self.get_optional_dialect(name)) is None:
            raise UnregisteredConstructException(f"Dialect {name} is not registered")
        return dialect

    def get_optional_dialect(self, name: str) -> "Dialect | None":
        """
        Get a dialect from its name if it exists.
        If the dialect is not registered, return None.
        """
        if name in self._registered_dialects and name not in self._loaded_dialects:
            self.load_registered_dialect(name)

        if name in self._loaded_dialects:
            return self._loaded_dialects[name]

        return None

allow_unregistered: bool = field(default=False) class-attribute instance-attribute

loaded_ops: Iterable[type[Operation]] property

Returns all the loaded operations. Not valid across mutations of this object.

loaded_attrs: Iterable[type[Attribute]] property

Returns all the loaded attributes. Not valid across mutations of this object.

loaded_types: Iterable[type[TypeAttribute]] property

Returns all the loaded types. Not valid across mutations of this object.

loaded_dialects: Iterable[Dialect] property

Returns all the loaded attributes. Not valid across mutations of this object.

registered_dialect_names: Iterable[str] property

Returns the names of all registered dialects. Not valid across mutations of this object.

__init__(allow_unregistered: bool = False, _loaded_dialects: dict[str, Dialect] = dict[str, Dialect](), _loaded_ops: dict[str, type[Operation]] = dict[str, type[Operation]](), _loaded_attrs: dict[str, type[Attribute]] = dict[str, type[Attribute]](), _loaded_types: dict[str, type[TypeAttribute]] = dict[str, type[TypeAttribute]](), _registered_dialects: dict[str, Callable[[], Dialect]] = dict[str, Callable[[], Dialect]]()) -> None

clone() -> Context

Source code in xdsl/context.py
35
36
37
38
39
40
41
42
43
def clone(self) -> "Context":
    return Context(
        self.allow_unregistered,
        self._loaded_dialects.copy(),
        self._loaded_ops.copy(),
        self._loaded_attrs.copy(),
        self._loaded_types.copy(),
        self._registered_dialects.copy(),
    )

register_dialect(name: str, dialect_factory: Callable[[], Dialect]) -> None

Register a dialect without loading it. The dialect is only loaded in the context when an operation or attribute of that dialect is parsed, or when explicitely requested with load_registered_dialect.

Source code in xdsl/context.py
80
81
82
83
84
85
86
87
88
89
90
91
92
def register_dialect(
    self, name: str, dialect_factory: "Callable[[], Dialect]"
) -> None:
    """
    Register a dialect without loading it. The dialect is only loaded in the context
    when an operation or attribute of that dialect is parsed, or when explicitely
    requested with `load_registered_dialect`.
    """
    if name in self._registered_dialects:
        raise AlreadyRegisteredConstructException(
            f"'{name}' dialect is already registered"
        )
    self._registered_dialects[name] = dialect_factory

load_registered_dialect(name: str) -> None

Load a dialect that is already registered in the context.

Source code in xdsl/context.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def load_registered_dialect(self, name: str) -> None:
    """Load a dialect that is already registered in the context."""
    if name not in self._registered_dialects:
        raise UnregisteredConstructException(f"'{name}' dialect is not registered")
    dialect = self._registered_dialects[name]()
    self._loaded_dialects[dialect.name] = dialect

    for op in dialect.operations:
        self.load_op(op)

    for attr in dialect.attributes:
        self.load_attr_or_type(attr)

load_dialect(dialect: Dialect)

Load a dialect. Operation and Attribute names should be unique. If the dialect is already registered in the context, use load_registered_dialect instead.

Source code in xdsl/context.py
107
108
109
110
111
112
113
114
115
116
117
118
def load_dialect(self, dialect: "Dialect"):
    """
    Load a dialect. Operation and Attribute names should be unique.
    If the dialect is already registered in the context, use
    `load_registered_dialect` instead.
    """
    if dialect.name in self._registered_dialects:
        raise AlreadyRegisteredConstructException(
            f"'{dialect.name}' dialect is already registered, use 'load_registered_dialect' instead"
        )
    self.register_dialect(dialect.name, lambda: dialect)
    self.load_registered_dialect(dialect.name)

load_op(op: type[Operation]) -> None

Load an operation definition. Operation names should be unique.

Source code in xdsl/context.py
120
121
122
123
124
125
126
def load_op(self, op: "type[Operation]") -> None:
    """Load an operation definition. Operation names should be unique."""
    if op.name in self._loaded_ops:
        raise AlreadyRegisteredConstructException(
            f"Operation {op.name} has already been loaded"
        )
    self._loaded_ops[op.name] = op

load_attr_or_type(attr: type[Attribute]) -> None

Load an attribute or type definition. Attribute or type names should be unique, but an attribute may have the same name as a type.

Source code in xdsl/context.py
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
def load_attr_or_type(self, attr: type[Attribute]) -> None:
    """
    Load an attribute or type definition.
    Attribute or type names should be unique, but an attribute may have the same
    name as a type.
    """
    if issubclass(attr, TypeAttribute):
        if attr.name in self._loaded_types:
            raise AlreadyRegisteredConstructException(
                f"Type {attr.name} has already been loaded"
            )
        self._loaded_types[attr.name] = attr
    else:
        if attr.name in self._loaded_attrs:
            raise AlreadyRegisteredConstructException(
                f"Attribute {attr.name} has already been loaded"
            )
        self._loaded_attrs[attr.name] = attr

get_optional_op(name: str, *, dialect_stack: Sequence[str] = ()) -> type[Operation] | None

Get an operation class from its name if it exists or is contained in one of the dialects in the dialect stack. If the operation is not registered, return None unless unregistered operations are allowed in the context, in which case return an UnregisteredOp.

Source code in xdsl/context.py
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
def get_optional_op(
    self, name: str, *, dialect_stack: Sequence[str] = ()
) -> "type[Operation] | None":
    """
    Get an operation class from its name if it exists or is contained in one of the
    dialects in the dialect stack.
    If the operation is not registered, return None unless unregistered operations
    are allowed in the context, in which case return an UnregisteredOp.
    """
    # Check if the name is known.
    if op_type := self._get_known_op(name):
        return op_type

    # Check appending each dialect in the dialect stack.
    for dialect_name in reversed(dialect_stack):
        dialect_and_name = f"{dialect_name}.{name}"
        if op_type := self._get_known_op(dialect_and_name):
            return op_type

    # If the context allows unregistered operations then create an UnregisteredOp
    if self.allow_unregistered:
        from xdsl.dialects.builtin import UnregisteredOp

        op_type = UnregisteredOp.with_name(name)
        self._loaded_ops[name] = op_type
        return op_type

get_op(name: str, *, dialect_stack: Sequence[str] = ()) -> type[Operation]

Get an operation class from its name if it exists or is contained in one of the dialects in the dialect stack. If the operation is not registered, raise an exception unless unregistered operations are allowed in the context, in which case return an UnregisteredOp.

Source code in xdsl/context.py
186
187
188
189
190
191
192
193
194
195
196
197
def get_op(
    self, name: str, *, dialect_stack: Sequence[str] = ()
) -> "type[Operation]":
    """
    Get an operation class from its name if it exists or is contained in one of the
    dialects in the dialect stack.
    If the operation is not registered, raise an exception unless unregistered
    operations are allowed in the context, in which case return an UnregisteredOp.
    """
    if op_type := self.get_optional_op(name, dialect_stack=dialect_stack):
        return op_type
    raise UnregisteredConstructException(f"Operation {name} is not registered")

get_optional_type(name: str) -> type[TypeAttribute] | None

Get a type definition from its name if it exists. If the type is not registered, return None unless unregistered types are allowed in the context, in which case return an UnregisteredAttr.

Source code in xdsl/context.py
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
def get_optional_type(self, name: str) -> type[TypeAttribute] | None:
    """
    Get a type definition from its name if it exists.
    If the type is not registered, return None unless unregistered types
    are allowed in the context, in which case return an UnregisteredAttr.
    """
    # If the type is already loaded, returns it.
    if name in self._loaded_types:
        return self._loaded_types[name]

    # Otherwise, check if the type dialect is registered.
    dialect_name, _ = Dialect.split_name(name)
    if (dialect_name in self._registered_dialects) and (
        dialect_name not in self._loaded_dialects
    ):
        self.load_registered_dialect(dialect_name)
        return self.get_optional_type(name)

    # If the dialect is unregistered, but the context allows unregistered
    # dialects, return an UnregisteredAttr.
    if self.allow_unregistered:
        from xdsl.dialects.builtin import UnregisteredAttr

        attr_type = UnregisteredAttr.with_name_and_type(name, True)
        assert issubclass(attr_type, TypeAttribute)
        self._loaded_types[name] = attr_type
        return attr_type

get_type(name: str) -> type[TypeAttribute]

Get a type definition from its name. If the type is not registered, raise an exception unless unregistered types are allowed in the context, in which case return an UnregisteredAttr.

Source code in xdsl/context.py
227
228
229
230
231
232
233
234
235
def get_type(self, name: str) -> type[TypeAttribute]:
    """
    Get a type definition from its name.
    If the type is not registered, raise an exception unless unregistered
    types are allowed in the context, in which case return an UnregisteredAttr.
    """
    if attr_type := self.get_optional_type(name):
        return attr_type
    raise UnregisteredConstructException(f"Type {name} is not registered")

get_optional_attr(name: str) -> type[Attribute] | None

Get an attribute class from its name if it exists. If the attribute is not registered, return None unless unregistered attributes are allowed in the context, in which case return an UnregisteredAttr.

Source code in xdsl/context.py
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
def get_optional_attr(
    self,
    name: str,
) -> "type[Attribute] | None":
    """
    Get an attribute class from its name if it exists.
    If the attribute is not registered, return None unless unregistered attributes
    are allowed in the context, in which case return an UnregisteredAttr.
    """
    # If the attribute is already loaded, returns it.
    if name in self._loaded_attrs:
        return self._loaded_attrs[name]

    # Otherwise, check if the attribute dialect is registered.
    dialect_name, _ = Dialect.split_name(name)
    if (
        dialect_name in self._registered_dialects
        and dialect_name not in self._loaded_dialects
    ):
        self.load_registered_dialect(dialect_name)
        return self.get_optional_attr(name)

    # If the dialect is unregistered, but the context allows unregistered
    # attributes, return an UnregisteredOp.
    if self.allow_unregistered:
        from xdsl.dialects.builtin import UnregisteredAttr

        attr_type = UnregisteredAttr.with_name_and_type(name, False)
        self._loaded_attrs[name] = attr_type
        return attr_type

    return None

get_attr(name: str) -> type[Attribute]

Get an attribute class from its name. If the attribute is not registered, raise an exception unless unregistered attributes are allowed in the context, in which case return an UnregisteredAttr.

Source code in xdsl/context.py
270
271
272
273
274
275
276
277
278
279
280
281
def get_attr(
    self,
    name: str,
) -> "type[Attribute]":
    """
    Get an attribute class from its name.
    If the attribute is not registered, raise an exception unless unregistered
    attributes are allowed in the context, in which case return an UnregisteredAttr.
    """
    if attr_type := self.get_optional_attr(name):
        return attr_type
    raise UnregisteredConstructException(f"Attribute {name} is not registered")

get_dialect(name: str) -> Dialect

Source code in xdsl/context.py
283
284
285
286
def get_dialect(self, name: str) -> "Dialect":
    if (dialect := self.get_optional_dialect(name)) is None:
        raise UnregisteredConstructException(f"Dialect {name} is not registered")
    return dialect

get_optional_dialect(name: str) -> Dialect | None

Get a dialect from its name if it exists. If the dialect is not registered, return None.

Source code in xdsl/context.py
288
289
290
291
292
293
294
295
296
297
298
299
def get_optional_dialect(self, name: str) -> "Dialect | None":
    """
    Get a dialect from its name if it exists.
    If the dialect is not registered, return None.
    """
    if name in self._registered_dialects and name not in self._loaded_dialects:
        self.load_registered_dialect(name)

    if name in self._loaded_dialects:
        return self._loaded_dialects[name]

    return None