• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# coding=utf-8
2#
3# Copyright (c) 2025 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16"""Defines the types for declarations."""
17
18from abc import ABCMeta, abstractmethod
19from collections.abc import Iterable
20from dataclasses import dataclass, field
21from typing import TYPE_CHECKING, Any, Generic, Protocol, TypeVar
22
23from typing_extensions import override
24
25from taihe.semantics.format import PrettyFormatter
26from taihe.semantics.types import (
27    EnumType,
28    IfaceType,
29    StructType,
30    UnionType,
31    UserType,
32)
33from taihe.utils.exceptions import DeclRedefError
34from taihe.utils.sources import SourceLocation
35
36if TYPE_CHECKING:
37    from taihe.semantics.types import Type
38    from taihe.semantics.visitor import DeclVisitor
39
40
41#############
42# Attribute #
43#############
44
45
46@dataclass
47class AttrItemDecl:
48    """Represents an attribute item."""
49
50    loc: SourceLocation | None
51    name: str
52
53    args: list[Any] = field(default_factory=list[Any])
54    kwargs: dict[str, Any] = field(default_factory=dict[str, Any])
55
56
57################
58# Declarations #
59################
60
61
62class DeclProtocol(Protocol):
63    def _accept(self, v: "DeclVisitor[Any]") -> Any:
64        ...
65
66
67class Decl(metaclass=ABCMeta):
68    """Represents any declaration."""
69
70    loc: SourceLocation | None
71
72    attrs: dict[str, list[AttrItemDecl]]
73
74    def __init__(
75        self,
76        loc: SourceLocation | None,
77    ):
78        self.loc = loc
79        self.attrs = {}
80
81    def __repr__(self) -> str:
82        return f"<{self.__class__.__qualname__} {self.description}>"
83
84    @property
85    @abstractmethod
86    def description(self) -> str:
87        """Human-readable description of this declaration."""
88
89    @property
90    @abstractmethod
91    def parent_pkg(self) -> "PackageDecl":
92        """Return the parent package of this declaration."""
93
94    def add_attr(self, i: AttrItemDecl):
95        self.attrs.setdefault(i.name, []).append(i)
96
97    def get_all_attrs(self, name: str) -> Iterable[AttrItemDecl]:
98        return self.attrs.get(name, [])
99
100    def get_last_attr(self, name: str) -> AttrItemDecl | None:
101        return self.attrs.get(name, [None])[-1]
102
103    @abstractmethod
104    def _accept(self, v: "DeclVisitor[Any]") -> Any:
105        """Accept a visitor."""
106
107
108class NamedDecl(Decl, metaclass=ABCMeta):
109    """Represents a declaration with a name."""
110
111    name: str
112
113    def __init__(
114        self,
115        loc: SourceLocation | None,
116        name: str,
117    ):
118        super().__init__(loc)
119        self.name = name
120
121
122T = TypeVar("T", bound=Decl)
123
124
125class DeclWithParent(Decl, Generic[T], metaclass=ABCMeta):
126    _node_parent: T | None = None
127
128    @property
129    @override
130    def parent_pkg(self) -> "PackageDecl":
131        pass
132        return self._node_parent.parent_pkg
133
134    def set_parent(self, parent: T):
135        self._node_parent = parent
136
137
138class NamedDeclWithParent(NamedDecl, Generic[T], metaclass=ABCMeta):
139    _node_parent: T | None = None
140
141    @property
142    @override
143    def parent_pkg(self) -> "PackageDecl":
144        pass
145        return self._node_parent.parent_pkg
146
147    def set_parent(self, parent: T):
148        self._node_parent = parent
149
150
151###################
152# Type References #
153###################
154
155
156class TypeRefDecl(DeclWithParent[Decl], metaclass=ABCMeta):
157    """Repersents a reference to a `Type`.
158
159    Each user of a `Type` must be encapsulated in a `TypeRefDecl`.
160    Also, `TypeRefDecl` is NOT a `TypeDecl`.
161    In other words, `TypeRefDecl` is a pointer, instead of a declaration.
162
163    For example:
164    ```
165    struct Foo { ... }      // `Foo` is a `TypeDecl`.
166
167    fn func(foo: Foo);      // `Foo` is `TypeRefDecl(ty=UserType(ty_decl=TypeDecl('Foo')))`.
168    fn func(foo: BadType);  // `BadType` is `TypeRefDecl(ty=None)`.
169    ```
170    """
171
172    is_resolved: bool = False
173    """Whether this type reference is resolved."""
174
175    maybe_resolved_ty: "Type | None" = None
176    """The resolved type, if any.
177
178    This field is `None` either if the type reference is not resolved yet,
179    or if the type reference is invalid.
180    """
181
182    def __init__(
183        self,
184        loc: SourceLocation | None,
185    ):
186        super().__init__(loc)
187
188    @property
189    @override
190    def description(self) -> str:
191        return f"type reference {self.text}"
192
193    @property
194    def resolved_ty(self) -> "Type":
195        pass
196        return self.maybe_resolved_ty
197
198    @property
199    def text(self) -> str:
200        return PrettyFormatter().get_type_ref_decl(self)
201
202
203class ParamDecl(NamedDeclWithParent[Decl]):
204    ty_ref: TypeRefDecl
205
206    def __init__(
207        self,
208        loc: SourceLocation | None,
209        name: str,
210        ty_ref: TypeRefDecl,
211    ):
212        super().__init__(loc, name)
213        self.ty_ref = ty_ref
214        ty_ref.set_parent(self)
215
216    @property
217    @override
218    def description(self) -> str:
219        return f"parameter {self.name}"
220
221    @override
222    def _accept(self, v: "DeclVisitor[T]") -> Any:
223        return v.visit_param_decl(self)
224
225
226class ShortTypeRefDecl(TypeRefDecl):
227    symbol: str
228
229    def __init__(
230        self,
231        loc: SourceLocation | None,
232        symbol: str,
233    ):
234        super().__init__(loc)
235        self.symbol = symbol
236
237    @override
238    def _accept(self, v: "DeclVisitor[T]") -> Any:
239        return v.visit_short_type_ref_decl(self)
240
241
242class LongTypeRefDecl(TypeRefDecl):
243    pkname: str
244    symbol: str
245
246    def __init__(
247        self,
248        loc: SourceLocation | None,
249        pkname: str,
250        symbol: str,
251    ):
252        super().__init__(loc)
253        self.pkname = pkname
254        self.symbol = symbol
255
256    @override
257    def _accept(self, v: "DeclVisitor[T]") -> Any:
258        return v.visit_long_type_ref_decl(self)
259
260
261class GenericTypeRefDecl(TypeRefDecl):
262    symbol: str
263    args_ty_ref: list[TypeRefDecl]
264
265    def __init__(
266        self,
267        loc: SourceLocation | None,
268        symbol: str,
269    ):
270        super().__init__(loc)
271        self.symbol = symbol
272        self.args_ty_ref = []
273
274    def add_arg_ty_ref(self, p: TypeRefDecl):
275        self.args_ty_ref.append(p)
276        p.set_parent(self)
277
278    @override
279    def _accept(self, v: "DeclVisitor[T]") -> Any:
280        return v.visit_generic_type_ref_decl(self)
281
282
283class CallbackTypeRefDecl(TypeRefDecl):
284    params: list[ParamDecl]
285    return_ty_ref: TypeRefDecl | None
286
287    def __init__(
288        self,
289        loc: SourceLocation | None,
290        return_ty_ref: TypeRefDecl | None = None,
291    ):
292        super().__init__(loc)
293        self.params = []
294        self.return_ty_ref = return_ty_ref
295        if return_ty_ref:
296            return_ty_ref.set_parent(self)
297
298    @override
299    def _accept(self, v: "DeclVisitor[T]") -> Any:
300        return v.visit_callback_type_ref_decl(self)
301
302    def add_param(self, p: ParamDecl):
303        self.params.append(p)
304        p.set_parent(self)
305
306
307#####################
308# Import References #
309#####################
310
311
312class PackageRefDecl(DeclWithParent[Decl]):
313    symbol: str
314
315    is_resolved: bool = False
316    """Whether this package reference is resolved."""
317
318    maybe_resolved_pkg: "PackageDecl | None" = None
319    """The resolved package, if any.
320
321    This field is `None` either if the package reference is not resolved yet,
322    or if the package reference is invalid.
323    """
324
325    def __init__(
326        self,
327        loc: SourceLocation | None,
328        symbol: str,
329    ):
330        super().__init__(loc)
331        self.symbol = symbol
332
333    @property
334    @override
335    def description(self) -> str:
336        return f"package reference {self.symbol}"
337
338    @property
339    def resolved_pkg(self) -> "PackageDecl":
340        pass
341        return self.maybe_resolved_pkg
342
343    @override
344    def _accept(self, v: "DeclVisitor[T]") -> Any:
345        return v.visit_package_ref_decl(self)
346
347
348class DeclarationRefDecl(DeclWithParent[Decl]):
349    symbol: str
350
351    pkg_ref: PackageRefDecl
352
353    is_resolved: bool = False
354    """Whether this declaration reference is resolved."""
355
356    maybe_resolved_decl: "PackageLevelDecl | None" = None
357    """The resolved declaration, if any.
358
359    This field is `None` either if the declaration reference is not resolved yet,
360    or if the declaration reference is invalid.
361    """
362
363    def __init__(
364        self,
365        loc: SourceLocation | None,
366        symbol: str,
367        pkg_ref: PackageRefDecl,
368    ):
369        super().__init__(loc)
370        self.symbol = symbol
371        self.pkg_ref = pkg_ref
372        pkg_ref.set_parent(self)
373
374    @property
375    @override
376    def description(self) -> str:
377        return f"type reference {self.symbol}"
378
379    @property
380    def resolved_decl(self) -> "PackageLevelDecl":
381        pass
382        return self.maybe_resolved_decl
383
384    @override
385    def _accept(self, v: "DeclVisitor[T]") -> Any:
386        return v.visit_declaration_ref_decl(self)
387
388
389#######################
390# Import Declarations #
391#######################
392
393
394class ImportDecl(NamedDeclWithParent["PackageDecl"], metaclass=ABCMeta):
395    """Represents a package or declaration import.
396
397    Invariant: the `name` field in base class `Decl` always represents actual name of imports.
398
399    For example:
400
401    ```
402    >>> use foo;
403    PackageImportDecl(name='foo', pkg_ref=PackageRefDecl(name='foo'))
404
405    >>> use foo as bar;
406    PackageImportDecl(name='bar', pkg_ref=PackageRefDecl(name='foo'))
407
408    >>> from foo use Bar;
409    DeclarationImportDecl(
410        name='Bar',
411        decl_ref=DeclarationRefDecl(name='Bar', pkg_ref=PackageRefDecl(name='foo')),
412    )
413
414    >>> from foo use Bar as Baz;
415    DeclarationImportDecl(
416        name='Baz',
417        decl_ref=DeclarationRefDecl(name='Bar', pkg_ref=PackageRefDecl(name='foo')),
418    )
419    ```
420    """
421
422
423class PackageImportDecl(ImportDecl):
424    pkg_ref: PackageRefDecl
425
426    def __init__(
427        self,
428        pkg_ref: PackageRefDecl,
429        *,
430        loc: SourceLocation | None = None,
431        name: str = "",
432    ):
433        super().__init__(
434            name=name or pkg_ref.symbol,
435            loc=loc or pkg_ref.loc,
436        )
437        self.pkg_ref = pkg_ref
438        pkg_ref.set_parent(self)
439
440    @property
441    @override
442    def description(self) -> str:
443        return f"package import {self.name}"
444
445    def is_alias(self) -> bool:
446        return self.name != self.pkg_ref.symbol
447
448    @override
449    def _accept(self, v: "DeclVisitor[T]") -> Any:
450        return v.visit_package_import_decl(self)
451
452
453class DeclarationImportDecl(ImportDecl):
454    decl_ref: DeclarationRefDecl
455
456    def __init__(
457        self,
458        decl_ref: DeclarationRefDecl,
459        *,
460        loc: SourceLocation | None = None,
461        name: str = "",
462    ):
463        super().__init__(
464            name=name or decl_ref.symbol,
465            loc=loc or decl_ref.loc,
466        )
467        self.decl_ref = decl_ref
468        decl_ref.set_parent(self)
469
470    @property
471    @override
472    def description(self) -> str:
473        return f"declaration import {self.name}"
474
475    def is_alias(self) -> bool:
476        return self.name != self.decl_ref.symbol
477
478    @override
479    def _accept(self, v: "DeclVisitor[T]") -> Any:
480        return v.visit_decl_import_decl(self)
481
482
483############################
484# Field Level Declarations #
485############################
486
487
488class EnumItemDecl(NamedDeclWithParent["EnumDecl"]):
489    value: int | float | str | bool | None
490
491    def __init__(
492        self,
493        loc: SourceLocation | None,
494        name: str,
495        value: int | float | str | bool | None = None,
496    ):
497        super().__init__(loc, name)
498        self.value = value
499
500    @property
501    @override
502    def description(self):
503        return f"enum item {self.name}"
504
505    @property
506    def parent_enum(self) -> "EnumDecl":
507        pass
508        return self._node_parent
509
510    @override
511    def _accept(self, v: "DeclVisitor[T]") -> Any:
512        return v.visit_enum_item_decl(self)
513
514
515class UnionFieldDecl(NamedDeclWithParent["UnionDecl"]):
516    ty_ref: TypeRefDecl | None
517
518    def __init__(
519        self,
520        loc: SourceLocation | None,
521        name: str,
522        ty_ref: TypeRefDecl | None = None,
523    ):
524        super().__init__(loc, name)
525        self.ty_ref = ty_ref
526        if ty_ref:
527            ty_ref.set_parent(self)
528
529    @property
530    @override
531    def description(self) -> str:
532        return f"union field {self.name}"
533
534    @property
535    def parent_union(self) -> "UnionDecl":
536        pass
537        return self._node_parent
538
539    @override
540    def _accept(self, v: "DeclVisitor[T]") -> Any:
541        return v.visit_union_field_decl(self)
542
543
544class StructFieldDecl(NamedDeclWithParent["StructDecl"]):
545    ty_ref: TypeRefDecl
546
547    def __init__(
548        self,
549        loc: SourceLocation | None,
550        name: str,
551        ty_ref: TypeRefDecl,
552    ):
553        super().__init__(loc, name)
554        self.ty_ref = ty_ref
555        ty_ref.set_parent(self)
556
557    @property
558    @override
559    def description(self) -> str:
560        return f"struct field {self.name}"
561
562    @property
563    def parent_struct(self) -> "StructDecl":
564        pass
565        return self._node_parent
566
567    @override
568    def _accept(self, v: "DeclVisitor[T]") -> Any:
569        return v.visit_struct_field_decl(self)
570
571
572class IfaceParentDecl(DeclWithParent["IfaceDecl"]):
573    ty_ref: TypeRefDecl
574
575    def __init__(
576        self,
577        loc: SourceLocation | None,
578        ty_ref: TypeRefDecl,
579    ):
580        super().__init__(loc)
581        self.ty_ref = ty_ref
582        ty_ref.set_parent(self)
583
584    @property
585    @override
586    def description(self) -> str:
587        return f"interface parent ({self.ty_ref.description})"
588
589    @property
590    def parent_iface(self) -> "IfaceDecl":
591        pass
592        return self._node_parent
593
594    @override
595    def _accept(self, v: "DeclVisitor[T]") -> Any:
596        return v.visit_iface_parent_decl(self)
597
598
599class IfaceMethodDecl(NamedDeclWithParent["IfaceDecl"]):
600    params: list[ParamDecl]
601    return_ty_ref: TypeRefDecl | None
602
603    def __init__(
604        self,
605        loc: SourceLocation | None,
606        name: str,
607        return_ty_ref: TypeRefDecl | None = None,
608    ):
609        super().__init__(loc, name)
610        self.params = []
611        self.return_ty_ref = return_ty_ref
612        if return_ty_ref:
613            return_ty_ref.set_parent(self)
614
615    @property
616    @override
617    def description(self) -> str:
618        return f"interface method {self.name}"
619
620    @property
621    def parent_iface(self) -> "IfaceDecl":
622        pass
623        return self._node_parent
624
625    def add_param(self, p: ParamDecl):
626        self.params.append(p)
627        p.set_parent(self)
628
629    @override
630    def _accept(self, v: "DeclVisitor[T]") -> Any:
631        return v.visit_iface_func_decl(self)
632
633
634##############################
635# Package Level Declarations #
636##############################
637
638
639class PackageLevelDecl(NamedDeclWithParent["PackageDecl"], metaclass=ABCMeta):
640    @property
641    def full_name(self):
642        return f"{self.parent_pkg.name}.{self.name}"
643
644
645class GlobFuncDecl(PackageLevelDecl):
646    params: list[ParamDecl]
647    return_ty_ref: TypeRefDecl | None
648
649    def __init__(
650        self,
651        loc: SourceLocation | None,
652        name: str,
653        return_ty_ref: TypeRefDecl | None = None,
654    ):
655        super().__init__(loc, name)
656        self.params = []
657        self.return_ty_ref = return_ty_ref
658        if return_ty_ref:
659            return_ty_ref.set_parent(self)
660
661    @property
662    @override
663    def description(self) -> str:
664        return f"function {self.name}"
665
666    def add_param(self, p: ParamDecl):
667        self.params.append(p)
668        p.set_parent(self)
669
670    @override
671    def _accept(self, v: "DeclVisitor[T]") -> Any:
672        return v.visit_glob_func_decl(self)
673
674
675#####################
676# Type Declarations #
677#####################
678
679
680class TypeDecl(PackageLevelDecl, metaclass=ABCMeta):
681    @abstractmethod
682    def as_type(self, ty_ref: TypeRefDecl) -> UserType:
683        """Return the type decalaration as type."""
684
685
686class EnumDecl(TypeDecl):
687    items: list[EnumItemDecl]
688    ty_ref: TypeRefDecl
689
690    def __init__(
691        self,
692        loc: SourceLocation | None,
693        name: str,
694        ty_ref: TypeRefDecl,
695    ):
696        super().__init__(loc, name)
697        self.items = []
698        self.ty_ref = ty_ref
699        ty_ref.set_parent(self)
700
701    @property
702    @override
703    def description(self) -> str:
704        return f"enum {self.name}"
705
706    def add_item(self, i: EnumItemDecl):
707        self.items.append(i)
708        i.set_parent(self)
709
710    @override
711    def as_type(self, ty_ref: TypeRefDecl) -> EnumType:
712        return EnumType(ty_ref, self)
713
714    @override
715    def _accept(self, v: "DeclVisitor[T]") -> Any:
716        return v.visit_enum_decl(self)
717
718
719class UnionDecl(TypeDecl):
720    fields: list[UnionFieldDecl]
721
722    def __init__(self, loc: SourceLocation | None, name: str):
723        super().__init__(loc, name)
724        self.fields = []
725
726    @property
727    @override
728    def description(self) -> str:
729        return f"union {self.name}"
730
731    def add_field(self, f: UnionFieldDecl):
732        self.fields.append(f)
733        f.set_parent(self)
734
735    @override
736    def as_type(self, ty_ref: TypeRefDecl) -> UnionType:
737        return UnionType(ty_ref, self)
738
739    @override
740    def _accept(self, v: "DeclVisitor[T]") -> Any:
741        return v.visit_union_decl(self)
742
743
744class StructDecl(TypeDecl):
745    fields: list[StructFieldDecl]
746
747    def __init__(self, loc: SourceLocation | None, name: str):
748        super().__init__(loc, name)
749        self.fields = []
750
751    @property
752    @override
753    def description(self) -> str:
754        return f"struct {self.name}"
755
756    def add_field(self, f: StructFieldDecl):
757        self.fields.append(f)
758        f.set_parent(self)
759
760    @override
761    def as_type(self, ty_ref: TypeRefDecl) -> StructType:
762        return StructType(ty_ref, self)
763
764    @override
765    def _accept(self, v: "DeclVisitor[T]") -> Any:
766        return v.visit_struct_decl(self)
767
768
769class IfaceDecl(TypeDecl):
770    methods: list[IfaceMethodDecl]
771    parents: list[IfaceParentDecl]
772
773    def __init__(self, loc: SourceLocation | None, name: str):
774        super().__init__(loc, name)
775        self.methods = []
776        self.parents = []
777
778    @property
779    @override
780    def description(self) -> str:
781        return f"interface {self.name}"
782
783    def add_method(self, f: IfaceMethodDecl):
784        self.methods.append(f)
785        f.set_parent(self)
786
787    def add_parent(self, p: IfaceParentDecl):
788        self.parents.append(p)
789        p.set_parent(self)
790
791    @override
792    def as_type(self, ty_ref: TypeRefDecl) -> IfaceType:
793        return IfaceType(ty_ref, self)
794
795    @override
796    def _accept(self, v: "DeclVisitor[T]") -> Any:
797        return v.visit_iface_decl(self)
798
799
800######################
801# The main container #
802######################
803
804
805class PackageDecl(NamedDecl):
806    """A collection of named identities sharing the same scope."""
807
808    _node_parent: "PackageGroup | None" = None
809
810    # Imports
811    _pkg_import_dict: dict[str, PackageImportDecl]
812    _decl_import_dict: dict[str, DeclarationImportDecl]
813
814    # Symbols
815    _declaration_dict: dict[str, PackageLevelDecl]
816
817    # Things that the package contains.
818    functions: list[GlobFuncDecl]
819    structs: list[StructDecl]
820    unions: list[UnionDecl]
821    interfaces: list[IfaceDecl]
822    enums: list[EnumDecl]
823
824    def __init__(self, name: str, loc: SourceLocation | None):
825        super().__init__(loc, name)
826
827        self._pkg_import_dict = {}
828        self._decl_import_dict = {}
829
830        self._declaration_dict = {}
831
832        self.functions = []
833        self.structs = []
834        self.unions = []
835        self.interfaces = []
836        self.enums = []
837
838    @property
839    @override
840    def description(self) -> str:
841        return f"package {self.name}"
842
843    @property
844    @override
845    def parent_pkg(self) -> "PackageDecl":
846        return self
847
848    @property
849    def parent_group(self) -> "PackageGroup":
850        pass
851        return self._node_parent
852
853    @property
854    def segments(self) -> list[str]:
855        return self.name.split(".")
856
857    @property
858    def pkg_imports(self) -> Iterable[PackageImportDecl]:
859        return self._pkg_import_dict.values()
860
861    @property
862    def decl_imports(self) -> Iterable[DeclarationImportDecl]:
863        return self._decl_import_dict.values()
864
865    @property
866    def declarations(self) -> Iterable[PackageLevelDecl]:
867        return self._declaration_dict.values()
868
869    def set_group(self, group: "PackageGroup"):
870        self._node_parent = group
871
872    def lookup(self, name: str) -> PackageLevelDecl | None:
873        return self._declaration_dict.get(name)
874
875    def lookup_pkg_import(self, name: str) -> PackageImportDecl | None:
876        return self._pkg_import_dict.get(name)
877
878    def lookup_decl_import(self, name: str) -> DeclarationImportDecl | None:
879        return self._decl_import_dict.get(name)
880
881    def add_import(self, i: ImportDecl):
882        if isinstance(i, DeclarationImportDecl):
883            self.add_decl_import(i)
884        elif isinstance(i, PackageImportDecl):
885            self.add_pkg_import(i)
886        else:
887            raise NotImplementedError(f"unexpected import {i.description}")
888
889    def add_decl_import(self, i: DeclarationImportDecl):
890        if (prev := self._decl_import_dict.setdefault(i.name, i)) != i:
891            raise DeclRedefError(prev, i)
892        i.set_parent(self)
893
894    def add_pkg_import(self, i: PackageImportDecl):
895        if (prev := self._pkg_import_dict.setdefault(i.name, i)) != i:
896            raise DeclRedefError(prev, i)
897        i.set_parent(self)
898
899    def add_declaration(self, d: PackageLevelDecl):
900        if isinstance(d, GlobFuncDecl):
901            self.add_function(d)
902        elif isinstance(d, StructDecl):
903            self.add_struct(d)
904        elif isinstance(d, UnionDecl):
905            self.add_union(d)
906        elif isinstance(d, IfaceDecl):
907            self.add_interface(d)
908        elif isinstance(d, EnumDecl):
909            self.add_enum(d)
910        else:
911            raise NotImplementedError(f"unexpected declaration {d.description}")
912
913    def add_function(self, f: GlobFuncDecl):
914        self._register_to_decl(f)
915        self.functions.append(f)
916        f.set_parent(self)
917
918    def add_enum(self, e: EnumDecl):
919        self._register_to_decl(e)
920        self.enums.append(e)
921        e.set_parent(self)
922
923    def add_struct(self, s: StructDecl):
924        self._register_to_decl(s)
925        self.structs.append(s)
926        s.set_parent(self)
927
928    def add_union(self, u: UnionDecl):
929        self._register_to_decl(u)
930        self.unions.append(u)
931        u.set_parent(self)
932
933    def add_interface(self, i: IfaceDecl):
934        self._register_to_decl(i)
935        self.interfaces.append(i)
936        i.set_parent(self)
937
938    def _register_to_decl(self, d: PackageLevelDecl):
939        if (prev := self._declaration_dict.setdefault(d.name, d)) != d:
940            raise DeclRedefError(prev, d)
941
942    @override
943    def _accept(self, v: "DeclVisitor[T]") -> Any:
944        return v.visit_package_decl(self)
945
946
947class PackageGroup:
948    """Stores all known packages for a compilation instance."""
949
950    _package_dict: dict[str, PackageDecl]
951
952    def __init__(self):
953        super().__init__()
954        self._package_dict = {}
955
956    def __repr__(self) -> str:
957        packages_str = ", ".join(repr(x) for x in self._package_dict)
958        return f"{self.__class__.__qualname__}({packages_str})"
959
960    @property
961    def packages(self) -> Iterable[PackageDecl]:
962        return self._package_dict.values()
963
964    def lookup(self, name: str) -> PackageDecl | None:
965        return self._package_dict.get(name)
966
967    def add(self, d: PackageDecl):
968        if (prev := self._package_dict.setdefault(d.name, d)) != d:
969            raise DeclRedefError(prev, d)
970        d.set_group(self)
971
972    def _accept(self, v: "DeclVisitor[T]"):
973        return v.visit_package_group(self)