diff --git a/doc/DataStructure/CompileOrderGraph.rst b/doc/DataStructure/CompileOrderGraph.rst index 01e29142e..42adda4e0 100644 --- a/doc/DataStructure/CompileOrderGraph.rst +++ b/doc/DataStructure/CompileOrderGraph.rst @@ -1,4 +1,4 @@ -.. _datastruct:compileorder: +.. _datastruct:compileordergraph: Compile Order Graph ################### diff --git a/doc/DataStructure/DependencyGraph.rst b/doc/DataStructure/DependencyGraph.rst index b974ff0c9..46b58426d 100644 --- a/doc/DataStructure/DependencyGraph.rst +++ b/doc/DataStructure/DependencyGraph.rst @@ -1,4 +1,4 @@ -.. _datastruct:dependgraph: +.. _datastruct:dependencygraph: Dependency Graph ################ diff --git a/doc/DataStructure/HierarchyGraph.rst b/doc/DataStructure/HierarchyGraph.rst index 0d8a7d1f8..002c0d726 100644 --- a/doc/DataStructure/HierarchyGraph.rst +++ b/doc/DataStructure/HierarchyGraph.rst @@ -1,4 +1,4 @@ -.. _datastruct:dependgraph: +.. _datastruct:hierarchygraph: Hierarchy Graph ############### diff --git a/doc/Dependency.rst b/doc/Dependency.rst index e4c2a37bc..dedf6ac14 100644 --- a/doc/Dependency.rst +++ b/doc/Dependency.rst @@ -51,7 +51,7 @@ the mandatory dependencies too. +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ | **Package** | **Version** | **License** | **Dependencies** | +=====================================================================+=============+========================================================================================+======================+ -| `pytest `__ | ≥8.2 | `MIT `__ | *Not yet evaluated.* | +| `pytest `__ | ≥8.2 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ | `pytest-cov `__ | ≥5.0 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ diff --git a/doc/Doc-License.rst b/doc/Doc-License.rst index 1258fbc2c..5267d5d47 100644 --- a/doc/Doc-License.rst +++ b/doc/Doc-License.rst @@ -17,7 +17,7 @@ licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. -.. topic:: Using Creative Commons Public Licenses +.. rubric:: Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of diff --git a/doc/LanguageModel/index.rst b/doc/LanguageModel/index.rst index 76ef60f50..608f351b0 100644 --- a/doc/LanguageModel/index.rst +++ b/doc/LanguageModel/index.rst @@ -3,7 +3,7 @@ VHDL Language Model ################### -.. topic:: Design Goal +.. rubric:: Design Goal * Clearly named classes that model the semantics of VHDL. * All language constructs (statements, declarations, specifications, …) have diff --git a/doc/_static/css/override.css b/doc/_static/css/override.css index 5f36fec2f..cbc891d86 100644 --- a/doc/_static/css/override.css +++ b/doc/_static/css/override.css @@ -39,6 +39,10 @@ section > p, text-align: justify } +p.rubric { + text-decoration: underline +} + /* wyrm overrides */ .wy-menu-vertical header, .wy-menu-vertical p.caption { diff --git a/doc/pyVHDLModel/index.rst b/doc/pyVHDLModel/index.rst deleted file mode 100644 index b3e0c4cfb..000000000 --- a/doc/pyVHDLModel/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -Python Class Reference -###################### - -Reference of all packages and modules: - -.. toctree:: - - pyVHDLModel diff --git a/pyVHDLModel/Association.py b/pyVHDLModel/Association.py index 7927cbf24..fc06eee46 100644 --- a/pyVHDLModel/Association.py +++ b/pyVHDLModel/Association.py @@ -36,7 +36,7 @@ """ from typing import Optional as Nullable, Union -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyVHDLModel.Base import ModelEntity from pyVHDLModel.Symbol import Symbol @@ -62,7 +62,7 @@ class AssociationItem(ModelEntity): _formal: Nullable[Symbol] _actual: ExpressionUnion - def __init__(self, actual: ExpressionUnion, formal: Nullable[Symbol] = None): + def __init__(self, actual: ExpressionUnion, formal: Nullable[Symbol] = None) -> None: super().__init__() self._formal = formal @@ -72,11 +72,11 @@ def __init__(self, actual: ExpressionUnion, formal: Nullable[Symbol] = None): self._actual = actual # actual._parent = self # FIXME: actual is provided as None - @property + @readonly def Formal(self) -> Nullable[Symbol]: # TODO: can also be a conversion function !! return self._formal - @property + @readonly def Actual(self) -> ExpressionUnion: return self._actual diff --git a/pyVHDLModel/Base.py b/pyVHDLModel/Base.py index 4a90fd0e6..b09a3572f 100644 --- a/pyVHDLModel/Base.py +++ b/pyVHDLModel/Base.py @@ -37,7 +37,7 @@ from enum import unique, Enum from typing import Type, Tuple, Iterable, Optional as Nullable, Union, cast -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType @@ -109,11 +109,15 @@ class ModelEntity(metaclass=ExtendedType, slots=True): _parent: 'ModelEntity' #: Reference to a parent entity in the model. - def __init__(self) -> None: - """Initializes a VHDL model entity.""" - self._parent = None + def __init__(self, parent: Nullable["ModelEntity"] = None) -> None: + """ + Initializes a VHDL model entity. - @property + :param parent: The parent model entity of this entity. + """ + self._parent = parent + + @readonly def Parent(self) -> 'ModelEntity': """ Returns a reference to the parent entity. @@ -142,7 +146,7 @@ class NamedEntityMixin(metaclass=ExtendedType, mixin=True): _identifier: str #: The identifier of a model entity. _normalizedIdentifier: str #: The normalized (lower case) identifier of a model entity. - def __init__(self, identifier: str): + def __init__(self, identifier: str) -> None: """ Initializes a named entity. @@ -151,7 +155,7 @@ def __init__(self, identifier: str): self._identifier = identifier self._normalizedIdentifier = identifier.lower() - @property + @readonly def Identifier(self) -> str: """ Returns a model entity's identifier (name). @@ -160,7 +164,7 @@ def Identifier(self) -> str: """ return self._identifier - @property + @readonly def NormalizedIdentifier(self) -> str: """ Returns a model entity's normalized identifier (lower case name). @@ -183,7 +187,7 @@ class MultipleNamedEntityMixin(metaclass=ExtendedType, mixin=True): _identifiers: Tuple[str] #: A list of identifiers. _normalizedIdentifiers: Tuple[str] #: A list of normalized (lower case) identifiers. - def __init__(self, identifiers: Iterable[str]): + def __init__(self, identifiers: Iterable[str]) -> None: """ Initializes a multiple-named entity. @@ -192,7 +196,7 @@ def __init__(self, identifiers: Iterable[str]): self._identifiers = tuple(identifiers) self._normalizedIdentifiers = tuple([identifier.lower() for identifier in identifiers]) - @property + @readonly def Identifiers(self) -> Tuple[str]: """ Returns a model entity's tuple of identifiers (names). @@ -201,7 +205,7 @@ def Identifiers(self) -> Tuple[str]: """ return self._identifiers - @property + @readonly def NormalizedIdentifiers(self) -> Tuple[str]: """ Returns a model entity's tuple of normalized identifiers (lower case names). @@ -222,7 +226,7 @@ class LabeledEntityMixin(metaclass=ExtendedType, mixin=True): _label: Nullable[str] #: The label of a model entity. _normalizedLabel: Nullable[str] #: The normalized (lower case) label of a model entity. - def __init__(self, label: Nullable[str]): + def __init__(self, label: Nullable[str]) -> None: """ Initializes a labeled entity. @@ -231,7 +235,7 @@ def __init__(self, label: Nullable[str]): self._label = label self._normalizedLabel = label.lower() if label is not None else None - @property + @readonly def Label(self) -> Nullable[str]: """ Returns a model entity's label. @@ -240,7 +244,7 @@ def Label(self) -> Nullable[str]: """ return self._label - @property + @readonly def NormalizedLabel(self) -> Nullable[str]: """ Returns a model entity's normalized (lower case) label. @@ -261,7 +265,7 @@ class DocumentedEntityMixin(metaclass=ExtendedType, mixin=True): _documentation: Nullable[str] #: The associated documentation of a model entity. - def __init__(self, documentation: Nullable[str]): + def __init__(self, documentation: Nullable[str]) -> None: """ Initializes a documented entity. @@ -269,7 +273,7 @@ def __init__(self, documentation: Nullable[str]): """ self._documentation = documentation - @property + @readonly def Documentation(self) -> Nullable[str]: """ Returns a model entity's associated documentation. @@ -306,7 +310,7 @@ def __init__(self) -> None: @export class ConditionalBranchMixin(BranchMixin, ConditionalMixin, mixin=True): """A ``BaseBranch`` is a mixin-class for all branch statements with a condition.""" - def __init__(self, condition: ExpressionUnion): + def __init__(self, condition: ExpressionUnion) -> None: super().__init__() ConditionalMixin.__init__(self, condition) @@ -355,7 +359,7 @@ def Severity(self) -> Nullable[ExpressionUnion]: class AssertStatementMixin(ReportStatementMixin, ConditionalMixin, mixin=True): """A ``MixinAssertStatement`` is a mixin-class for all assert statements.""" - def __init__(self, condition: ExpressionUnion, message: Nullable[ExpressionUnion] = None, severity: Nullable[ExpressionUnion] = None): + def __init__(self, condition: ExpressionUnion, message: Nullable[ExpressionUnion] = None, severity: Nullable[ExpressionUnion] = None) -> None: super().__init__(message, severity) ConditionalMixin.__init__(self, condition) @@ -385,8 +389,8 @@ class Range(ModelEntity): _rightBound: ExpressionUnion _direction: Direction - def __init__(self, leftBound: ExpressionUnion, rightBound: ExpressionUnion, direction: Direction): - super().__init__() + def __init__(self, leftBound: ExpressionUnion, rightBound: ExpressionUnion, direction: Direction, parent: ModelEntity = None) -> None: + super().__init__(parent) self._leftBound = leftBound leftBound._parent = self @@ -417,8 +421,8 @@ class WaveformElement(ModelEntity): _expression: ExpressionUnion _after: ExpressionUnion - def __init__(self, expression: ExpressionUnion, after: Nullable[ExpressionUnion] = None): - super().__init__() + def __init__(self, expression: ExpressionUnion, after: Nullable[ExpressionUnion] = None, parent: ModelEntity = None) -> None: + super().__init__(parent) self._expression = expression expression._parent = self diff --git a/pyVHDLModel/Common.py b/pyVHDLModel/Common.py index daaf7b5d1..c9ce2042a 100644 --- a/pyVHDLModel/Common.py +++ b/pyVHDLModel/Common.py @@ -36,7 +36,7 @@ """ from typing import List, Iterable, Union, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyVHDLModel.Base import ModelEntity, LabeledEntityMixin @@ -60,8 +60,8 @@ class Statement(ModelEntity, LabeledEntityMixin): """ A ``Statement`` is a base-class for all statements. """ - def __init__(self, label: Nullable[str] = None) -> None: - super().__init__() + def __init__(self, label: Nullable[str] = None, parent=None) -> None: + super().__init__(parent) LabeledEntityMixin.__init__(self, label) @@ -70,7 +70,7 @@ class ProcedureCallMixin(metaclass=ExtendedType, mixin=True): _procedure: Symbol # TODO: implement a ProcedureSymbol _parameterMappings: List[ParameterAssociationItem] - def __init__(self, procedureName: Symbol, parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None): + def __init__(self, procedureName: Symbol, parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None) -> None: self._procedure = procedureName procedureName._parent = self @@ -81,7 +81,7 @@ def __init__(self, procedureName: Symbol, parameterMappings: Nullable[Iterable[P self._parameterMappings.append(parameterMapping) parameterMapping._parent = self - @property + @readonly def Procedure(self) -> Symbol: return self._procedure @@ -96,7 +96,7 @@ class AssignmentMixin(metaclass=ExtendedType, mixin=True): _target: Symbol - def __init__(self, target: Symbol): + def __init__(self, target: Symbol) -> None: self._target = target target._parent = self @@ -117,7 +117,7 @@ class VariableAssignmentMixin(AssignmentMixin, mixin=True): # FIXME: move to sequential? _expression: ExpressionUnion - def __init__(self, target: Symbol, expression: ExpressionUnion): + def __init__(self, target: Symbol, expression: ExpressionUnion) -> None: super().__init__(target) self._expression = expression diff --git a/pyVHDLModel/Concurrent.py b/pyVHDLModel/Concurrent.py index 92e9236f7..3b5abde65 100644 --- a/pyVHDLModel/Concurrent.py +++ b/pyVHDLModel/Concurrent.py @@ -36,7 +36,7 @@ """ from typing import List, Dict, Union, Iterable, Generator, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyVHDLModel.Base import ModelEntity, LabeledEntityMixin, DocumentedEntityMixin, Range, BaseChoice, BaseCase, IfBranchMixin @@ -84,7 +84,7 @@ class ConcurrentStatementsMixin(metaclass=ExtendedType, mixin=True): _generates: Dict[str, 'GenerateStatement'] _hierarchy: Dict[str, Union['ConcurrentBlockStatement', 'GenerateStatement']] - def __init__(self, statements: Nullable[Iterable[ConcurrentStatement]] = None): + def __init__(self, statements: Nullable[Iterable[ConcurrentStatement]] = None) -> None: self._statements = [] self._instantiations = {} @@ -97,7 +97,7 @@ def __init__(self, statements: Nullable[Iterable[ConcurrentStatement]] = None): self._statements.append(statement) statement._parent = self - @property + @readonly def Statements(self) -> List[ConcurrentStatement]: return self._statements @@ -133,8 +133,14 @@ class Instantiation(ConcurrentStatement): _genericAssociations: List[AssociationItem] _portAssociations: List[AssociationItem] - def __init__(self, label: str, genericAssociations: Nullable[Iterable[AssociationItem]] = None, portAssociations: Nullable[Iterable[AssociationItem]] = None): - super().__init__(label) + def __init__( + self, + label: str, + genericAssociations: Nullable[Iterable[AssociationItem]] = None, + portAssociations: Nullable[Iterable[AssociationItem]] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) # TODO: extract to mixin self._genericAssociations = [] @@ -150,7 +156,7 @@ def __init__(self, label: str, genericAssociations: Nullable[Iterable[Associatio self._portAssociations.append(association) association._parent = self - @property + @readonly def GenericAssociations(self) -> List[AssociationItem]: return self._genericAssociations @@ -173,8 +179,15 @@ class ComponentInstantiation(Instantiation): _component: ComponentInstantiationSymbol - def __init__(self, label: str, componentSymbol: ComponentInstantiationSymbol, genericAssociations: Nullable[Iterable[AssociationItem]] = None, portAssociations: Nullable[Iterable[AssociationItem]] = None): - super().__init__(label, genericAssociations, portAssociations) + def __init__( + self, + label: str, + componentSymbol: ComponentInstantiationSymbol, + genericAssociations: Nullable[Iterable[AssociationItem]] = None, + portAssociations: Nullable[Iterable[AssociationItem]] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, genericAssociations, portAssociations, parent) self._component = componentSymbol componentSymbol._parent = self @@ -199,8 +212,16 @@ class EntityInstantiation(Instantiation): _entity: EntityInstantiationSymbol _architecture: ArchitectureSymbol - def __init__(self, label: str, entitySymbol: EntityInstantiationSymbol, architectureSymbol: Nullable[ArchitectureSymbol] = None, genericAssociations: Nullable[Iterable[AssociationItem]] = None, portAssociations: Nullable[Iterable[AssociationItem]] = None): - super().__init__(label, genericAssociations, portAssociations) + def __init__( + self, + label: str, + entitySymbol: EntityInstantiationSymbol, + architectureSymbol: Nullable[ArchitectureSymbol] = None, + genericAssociations: Nullable[Iterable[AssociationItem]] = None, + portAssociations: Nullable[Iterable[AssociationItem]] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, genericAssociations, portAssociations, parent) self._entity = entitySymbol entitySymbol._parent = self @@ -232,8 +253,15 @@ class ConfigurationInstantiation(Instantiation): _configuration: ConfigurationInstantiationSymbol - def __init__(self, label: str, configurationSymbol: ConfigurationInstantiationSymbol, genericAssociations: Nullable[Iterable[AssociationItem]] = None, portAssociations: Nullable[Iterable[AssociationItem]] = None): - super().__init__(label, genericAssociations, portAssociations) + def __init__( + self, + label: str, + configurationSymbol: ConfigurationInstantiationSymbol, + genericAssociations: Nullable[Iterable[AssociationItem]] = None, + portAssociations: Nullable[Iterable[AssociationItem]] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, genericAssociations, portAssociations, parent) self._configuration = configurationSymbol configurationSymbol._parent = self @@ -267,9 +295,10 @@ def __init__( declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[SequentialStatement]] = None, sensitivityList: Nullable[Iterable[Name]] = None, - documentation: Nullable[str] = None - ): - super().__init__(label) + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) SequentialDeclarationsMixin.__init__(self, declaredItems) SequentialStatementsMixin.__init__(self, statements) DocumentedEntityMixin.__init__(self, documentation) @@ -289,8 +318,14 @@ def SensitivityList(self) -> List[Name]: @export class ConcurrentProcedureCall(ConcurrentStatement, ProcedureCallMixin): - def __init__(self, label: str, procedureName: Name, parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None): - super().__init__(label) + def __init__( + self, + label: str, + procedureName: Name, + parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) ProcedureCallMixin.__init__(self, procedureName, parameterMappings) @@ -304,9 +339,10 @@ def __init__( portItems: Nullable[Iterable[PortInterfaceItemMixin]] = None, declaredItems: Nullable[Iterable] = None, statements: Iterable['ConcurrentStatement'] = None, - documentation: Nullable[str] = None - ): - super().__init__(label) + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) BlockStatementMixin.__init__(self) LabeledEntityMixin.__init__(self, label) ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) @@ -342,8 +378,14 @@ class GenerateBranch(ModelEntity, ConcurrentDeclarationRegionMixin, ConcurrentSt _namespace: Namespace - def __init__(self, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None): - super().__init__() + def __init__( + self, + declaredItems: Nullable[Iterable] = None, + statements: Nullable[Iterable[ConcurrentStatement]] = None, + alternativeLabel: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(parent) ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) ConcurrentStatementsMixin.__init__(self, statements) @@ -381,8 +423,15 @@ class IfGenerateBranch(GenerateBranch, IfBranchMixin): end generate; """ - def __init__(self, condition: ExpressionUnion, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None): - super().__init__(declaredItems, statements, alternativeLabel) + def __init__( + self, + condition: ExpressionUnion, + declaredItems: Nullable[Iterable] = None, + statements: Nullable[Iterable[ConcurrentStatement]] = None, + alternativeLabel: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(declaredItems, statements, alternativeLabel, parent) IfBranchMixin.__init__(self, condition) @@ -406,8 +455,15 @@ class ElsifGenerateBranch(GenerateBranch, ElsifBranchMixin): end generate; """ - def __init__(self, condition: ExpressionUnion, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None): - super().__init__(declaredItems, statements, alternativeLabel) + def __init__( + self, + condition: ExpressionUnion, + declaredItems: Nullable[Iterable] = None, + statements: Nullable[Iterable[ConcurrentStatement]] = None, + alternativeLabel: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(declaredItems, statements, alternativeLabel, parent) ElsifBranchMixin.__init__(self, condition) @@ -431,8 +487,14 @@ class ElseGenerateBranch(GenerateBranch, ElseBranchMixin): end generate; """ - def __init__(self, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None): - super().__init__(declaredItems, statements, alternativeLabel) + def __init__( + self, + declaredItems: Nullable[Iterable] = None, + statements: Nullable[Iterable[ConcurrentStatement]] = None, + alternativeLabel: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(declaredItems, statements, alternativeLabel, parent) ElseBranchMixin.__init__(self) @@ -450,8 +512,12 @@ class GenerateStatement(ConcurrentStatement): _namespace: Namespace - def __init__(self, label: Nullable[str] = None) -> None: - super().__init__(label) + def __init__( + self, + label: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) self._namespace = Namespace(self._normalizedLabel) @@ -493,8 +559,15 @@ class IfGenerateStatement(GenerateStatement): _elsifBranches: List[ElsifGenerateBranch] _elseBranch: Nullable[ElseGenerateBranch] - def __init__(self, label: str, ifBranch: IfGenerateBranch, elsifBranches: Nullable[Iterable[ElsifGenerateBranch]] = None, elseBranch: Nullable[ElseGenerateBranch] = None): - super().__init__(label) + def __init__( + self, + label: str, + ifBranch: IfGenerateBranch, + elsifBranches: Nullable[Iterable[ElsifGenerateBranch]] = None, + elseBranch: Nullable[ElseGenerateBranch] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) self._ifBranch = ifBranch ifBranch._parent = self @@ -547,8 +620,8 @@ class ConcurrentChoice(BaseChoice): class IndexedGenerateChoice(ConcurrentChoice): _expression: ExpressionUnion - def __init__(self, expression: ExpressionUnion): - super().__init__() + def __init__(self, expression: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(parent) self._expression = expression expression._parent = self @@ -565,8 +638,8 @@ def __str__(self) -> str: class RangedGenerateChoice(ConcurrentChoice): _range: 'Range' - def __init__(self, rng: 'Range'): - super().__init__() + def __init__(self, rng: 'Range', parent: ModelEntity = None) -> None: + super().__init__(parent) self._range = rng rng._parent = self @@ -581,8 +654,14 @@ def __str__(self) -> str: @export class ConcurrentCase(BaseCase, LabeledEntityMixin, ConcurrentDeclarationRegionMixin, ConcurrentStatementsMixin): - def __init__(self, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None): - super().__init__() + def __init__( + self, + declaredItems: Nullable[Iterable] = None, + statements: Nullable[Iterable[ConcurrentStatement]] = None, + alternativeLabel: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(parent) LabeledEntityMixin.__init__(self, alternativeLabel) ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) ConcurrentStatementsMixin.__init__(self, statements) @@ -592,8 +671,15 @@ def __init__(self, declaredItems: Nullable[Iterable] = None, statements: Nullabl class GenerateCase(ConcurrentCase): _choices: List[ConcurrentChoice] - def __init__(self, choices: Iterable[ConcurrentChoice], declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, alternativeLabel: Nullable[str] = None): - super().__init__(declaredItems, statements, alternativeLabel) + def __init__( + self, + choices: Iterable[ConcurrentChoice], + declaredItems: Nullable[Iterable] = None, + statements: Nullable[Iterable[ConcurrentStatement]] = None, + alternativeLabel: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(declaredItems, statements, alternativeLabel, parent) # TODO: move to parent or grandparent self._choices = [] @@ -639,8 +725,14 @@ class CaseGenerateStatement(GenerateStatement): _expression: ExpressionUnion _cases: List[GenerateCase] - def __init__(self, label: str, expression: ExpressionUnion, cases: Iterable[ConcurrentCase]): - super().__init__(label) + def __init__( + self, + label: str, + expression: ExpressionUnion, + cases: Iterable[ConcurrentCase], + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) self._expression = expression expression._parent = self @@ -686,8 +778,16 @@ class ForGenerateStatement(GenerateStatement, ConcurrentDeclarationRegionMixin, _loopIndex: str _range: Range - def __init__(self, label: str, loopIndex: str, rng: Range, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None): - super().__init__(label) + def __init__( + self, + label: str, + loopIndex: str, + rng: Range, + declaredItems: Nullable[Iterable] = None, + statements: Nullable[Iterable[ConcurrentStatement]] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) ConcurrentStatementsMixin.__init__(self, statements) @@ -727,8 +827,8 @@ class ConcurrentSignalAssignment(ConcurrentStatement, SignalAssignmentMixin): * :class:`~pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment` * :class:`~pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment` """ - def __init__(self, label: str, target: Name): - super().__init__(label) + def __init__(self, label: str, target: Name, parent: ModelEntity = None) -> None: + super().__init__(label, parent) SignalAssignmentMixin.__init__(self, target) @@ -736,8 +836,8 @@ def __init__(self, label: str, target: Name): class ConcurrentSimpleSignalAssignment(ConcurrentSignalAssignment): _waveform: List[WaveformElement] - def __init__(self, label: str, target: Name, waveform: Iterable[WaveformElement]): - super().__init__(label, target) + def __init__(self, label: str, target: Name, waveform: Iterable[WaveformElement], parent: ModelEntity = None) -> None: + super().__init__(label, target, parent) # TODO: extract to mixin self._waveform = [] @@ -753,18 +853,25 @@ def Waveform(self) -> List[WaveformElement]: @export class ConcurrentSelectedSignalAssignment(ConcurrentSignalAssignment): - def __init__(self, label: str, target: Name, expression: ExpressionUnion): - super().__init__(label, target) + def __init__(self, label: str, target: Name, expression: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(label, target, parent) @export class ConcurrentConditionalSignalAssignment(ConcurrentSignalAssignment): - def __init__(self, label: str, target: Name, expression: ExpressionUnion): - super().__init__(label, target) + def __init__(self, label: str, target: Name, expression: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(label, target, parent) @export class ConcurrentAssertStatement(ConcurrentStatement, AssertStatementMixin): - def __init__(self, condition: ExpressionUnion, message: ExpressionUnion, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None): - super().__init__(label) + def __init__( + self, + condition: ExpressionUnion, + message: ExpressionUnion, + severity: Nullable[ExpressionUnion] = None, + label: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) AssertStatementMixin.__init__(self, condition, message, severity) diff --git a/pyVHDLModel/Declaration.py b/pyVHDLModel/Declaration.py index f052aca6f..52dd9d92f 100644 --- a/pyVHDLModel/Declaration.py +++ b/pyVHDLModel/Declaration.py @@ -37,7 +37,7 @@ from enum import unique, Enum from typing import List, Iterable, Union, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, DocumentedEntityMixin from pyVHDLModel.Expression import BaseExpression, QualifiedExpression, FunctionCall, TypeConversion, Literal @@ -98,15 +98,21 @@ class Attribute(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): _subtype: Symbol - def __init__(self, identifier: str, subtype: Symbol, documentation: Nullable[str] = None): - super().__init__() + def __init__( + self, + identifier: str, + subtype: Symbol, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(parent) NamedEntityMixin.__init__(self, identifier) DocumentedEntityMixin.__init__(self, documentation) self._subtype = subtype subtype._parent = self - @property + @readonly def Subtype(self) -> None: return self._subtype @@ -128,8 +134,16 @@ class AttributeSpecification(ModelEntity, DocumentedEntityMixin): _entityClass: EntityClass _expression: ExpressionUnion - def __init__(self, identifiers: Iterable[Name], attribute: Name, entityClass: EntityClass, expression: ExpressionUnion, documentation: Nullable[str] = None): - super().__init__() + def __init__( + self, + identifiers: Iterable[Name], + attribute: Name, + entityClass: EntityClass, + expression: ExpressionUnion, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(parent) DocumentedEntityMixin.__init__(self, documentation) self._identifiers = [] # TODO: convert to dict @@ -145,19 +159,19 @@ def __init__(self, identifiers: Iterable[Name], attribute: Name, entityClass: En self._expression = expression expression._parent = self - @property + @readonly def Identifiers(self) -> List[Name]: return self._identifiers - @property + @readonly def Attribute(self) -> Name: return self._attribute - @property + @readonly def EntityClass(self) -> EntityClass: return self._entityClass - @property + @readonly def Expression(self) -> ExpressionUnion: return self._expression @@ -165,12 +179,12 @@ def Expression(self) -> ExpressionUnion: # TODO: move somewhere else @export class Alias(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): - def __init__(self, identifier: str, documentation: Nullable[str] = None): + def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: """ Initializes underlying ``BaseType``. :param identifier: Name of the type. """ - super().__init__() + super().__init__(parent) NamedEntityMixin.__init__(self, identifier) DocumentedEntityMixin.__init__(self, documentation) diff --git a/pyVHDLModel/DesignUnit.py b/pyVHDLModel/DesignUnit.py index 5dfb04128..a46f154d4 100644 --- a/pyVHDLModel/DesignUnit.py +++ b/pyVHDLModel/DesignUnit.py @@ -36,7 +36,7 @@ """ from typing import List, Dict, Union, Iterable, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyTooling.Graph import Vertex @@ -64,12 +64,12 @@ class Reference(ModelEntity): _symbols: List[Symbol] - def __init__(self, symbols: Iterable[Symbol]): - super().__init__() + def __init__(self, symbols: Iterable[Symbol], parent: ModelEntity = None) -> None: + super().__init__(parent) self._symbols = [s for s in symbols] - @property + @readonly def Symbols(self) -> List[Symbol]: return self._symbols @@ -86,7 +86,7 @@ class LibraryClause(Reference): library ieee; """ - @property + @readonly def Symbols(self) -> List[LibraryReferenceSymbol]: return self._symbols @@ -164,12 +164,12 @@ class DesignUnit(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): _referencedPackages: Dict[str, Dict[str, 'Package']] #: Referenced packages based on explicit use clauses or implicit inheritance _referencedContexts: Dict[str, 'Context'] #: Referenced contexts based on explicit context references or implicit inheritance - _dependencyVertex: Vertex[None, None, str, 'DesignUnit', None, None, None, None, None, None, None, None, None, None, None, None, None] #: The vertex in the dependency graph + _dependencyVertex: Vertex[None, None, str, 'DesignUnit', None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the dependency graph representing the design unit. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateDependencyGraph`. _hierarchyVertex: Vertex[None, None, str, 'DesignUnit', None, None, None, None, None, None, None, None, None, None, None, None, None] #: The vertex in the hierarchy graph _namespace: 'Namespace' - def __init__(self, identifier: str, contextItems: Nullable[Iterable[ContextUnion]] = None, documentation: Nullable[str] = None): + def __init__(self, identifier: str, contextItems: Nullable[Iterable[ContextUnion]] = None, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: """ Initializes a design unit. @@ -177,7 +177,7 @@ def __init__(self, identifier: str, contextItems: Nullable[Iterable[ContextUnion :param contextItems: A sequence of library, use or context clauses. :param documentation: Associated documentation of the design unit. """ - super().__init__() + super().__init__(parent) NamedEntityMixin.__init__(self, identifier) DocumentedEntityMixin.__init__(self, documentation) @@ -207,7 +207,7 @@ def __init__(self, identifier: str, contextItems: Nullable[Iterable[ContextUnion self._namespace = Namespace(self._normalizedIdentifier) - @property + @readonly def Document(self) -> 'Document': return self._parent @@ -340,8 +340,8 @@ class Context(PrimaryUnit): _references: List[ContextUnion] - def __init__(self, identifier: str, references: Nullable[Iterable[ContextUnion]] = None, documentation: Nullable[str] = None): - super().__init__(identifier, None, documentation) + def __init__(self, identifier: str, references: Nullable[Iterable[ContextUnion]] = None, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, None, documentation, parent) self._references = [] self._libraryReferences = [] @@ -399,8 +399,16 @@ class Package(PrimaryUnit, DesignUnitWithContextMixin, ConcurrentDeclarationRegi _deferredConstants: Dict[str, DeferredConstant] _components: Dict[str, 'Component'] - def __init__(self, identifier: str, contextItems: Nullable[Iterable[ContextUnion]] = None, genericItems: Nullable[Iterable[GenericInterfaceItemMixin]] = None, declaredItems: Nullable[Iterable] = None, documentation: Nullable[str] = None): - super().__init__(identifier, contextItems, documentation) + def __init__( + self, + identifier: str, + contextItems: Nullable[Iterable[ContextUnion]] = None, + genericItems: Nullable[Iterable[GenericInterfaceItemMixin]] = None, + declaredItems: Nullable[Iterable] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifier, contextItems, documentation, parent) DesignUnitWithContextMixin.__init__(self) ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) @@ -466,8 +474,15 @@ class PackageBody(SecondaryUnit, DesignUnitWithContextMixin, ConcurrentDeclarati _package: PackageSymbol - def __init__(self, packageSymbol: PackageSymbol, contextItems: Nullable[Iterable[ContextUnion]] = None, declaredItems: Nullable[Iterable] = None, documentation: Nullable[str] = None): - super().__init__(packageSymbol.Name.Identifier, contextItems, documentation) + def __init__( + self, + packageSymbol: PackageSymbol, + contextItems: Nullable[Iterable[ContextUnion]] = None, + declaredItems: Nullable[Iterable] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(packageSymbol.Name.Identifier, contextItems, documentation, parent) DesignUnitWithContextMixin.__init__(self) ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) @@ -523,9 +538,10 @@ def __init__( portItems: Nullable[Iterable[PortInterfaceItemMixin]] = None, declaredItems: Nullable[Iterable] = None, statements: Nullable[Iterable[ConcurrentStatement]] = None, - documentation: Nullable[str] = None - ): - super().__init__(identifier, contextItems, documentation) + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifier, contextItems, documentation, parent) DesignUnitWithContextMixin.__init__(self) ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) ConcurrentStatementsMixin.__init__(self, statements) @@ -591,8 +607,17 @@ class Architecture(SecondaryUnit, DesignUnitWithContextMixin, ConcurrentDeclarat _entity: EntitySymbol - def __init__(self, identifier: str, entity: EntitySymbol, contextItems: Nullable[Iterable[Context]] = None, declaredItems: Nullable[Iterable] = None, statements: Iterable['ConcurrentStatement'] = None, documentation: Nullable[str] = None): - super().__init__(identifier, contextItems, documentation) + def __init__( + self, + identifier: str, + entity: EntitySymbol, + contextItems: Nullable[Iterable[Context]] = None, + declaredItems: Nullable[Iterable] = None, + statements: Iterable['ConcurrentStatement'] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifier, contextItems, documentation, parent) DesignUnitWithContextMixin.__init__(self) ConcurrentDeclarationRegionMixin.__init__(self, declaredItems) ConcurrentStatementsMixin.__init__(self, statements) @@ -645,8 +670,15 @@ class Component(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): _entity: Nullable[Entity] - def __init__(self, identifier: str, genericItems: Nullable[Iterable[GenericInterfaceItemMixin]] = None, portItems: Nullable[Iterable[PortInterfaceItemMixin]] = None, documentation: Nullable[str] = None): - super().__init__() + def __init__( + self, + identifier: str, + genericItems: Nullable[Iterable[GenericInterfaceItemMixin]] = None, + portItems: Nullable[Iterable[PortInterfaceItemMixin]] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(parent) NamedEntityMixin.__init__(self, identifier) DocumentedEntityMixin.__init__(self, documentation) @@ -697,8 +729,14 @@ class Configuration(PrimaryUnit, DesignUnitWithContextMixin): end configuration; """ - def __init__(self, identifier: str, contextItems: Nullable[Iterable[Context]] = None, documentation: Nullable[str] = None): - super().__init__(identifier, contextItems, documentation) + def __init__( + self, + identifier: str, + contextItems: Nullable[Iterable[Context]] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifier, contextItems, documentation, parent) DesignUnitWithContextMixin.__init__(self) def __str__(self) -> str: diff --git a/pyVHDLModel/Exception.py b/pyVHDLModel/Exception.py index ce067a670..36cd8d4e0 100644 --- a/pyVHDLModel/Exception.py +++ b/pyVHDLModel/Exception.py @@ -38,7 +38,7 @@ from sys import version_info from typing import List -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyVHDLModel.Symbol import Symbol @@ -68,7 +68,7 @@ class LibraryExistsInDesignError(VHDLModelException): _library: 'Library' - def __init__(self, library: 'Library'): + def __init__(self, library: 'Library') -> None: """ Initializes the exception message based on given library object. @@ -77,7 +77,7 @@ def __init__(self, library: 'Library'): super().__init__(f"Library '{library.Identifier}' already exists in design.") self._library = library - @property + @readonly def Library(self) -> 'Library': return self._library @@ -92,7 +92,7 @@ class LibraryRegisteredToForeignDesignError(VHDLModelException): _library: 'Library' - def __init__(self, library: 'Library'): + def __init__(self, library: 'Library') -> None: """ Initializes the exception message based on given library object. @@ -101,7 +101,7 @@ def __init__(self, library: 'Library'): super().__init__(f"Library '{library.Identifier}' already registered in design '{library.Parent}'.") self._library = library - @property + @readonly def Library(self) -> 'Library': return self._library @@ -116,7 +116,7 @@ class LibraryNotRegisteredError(VHDLModelException): _library: 'Library' - def __init__(self, library: 'Library'): + def __init__(self, library: 'Library') -> None: """ Initializes the exception message based on given library object. @@ -125,7 +125,7 @@ def __init__(self, library: 'Library'): super().__init__(f"Library '{library.Identifier}' is not registered in the design.") self._library = library - @property + @readonly def Library(self) -> 'Library': return self._library @@ -141,7 +141,7 @@ class EntityExistsInLibraryError(VHDLModelException): _library: 'Library' _entity: 'Entity' - def __init__(self, entity: 'Entity', library: 'Library'): + def __init__(self, entity: 'Entity', library: 'Library') -> None: """ Initializes the exception message based on given entity and library objects. @@ -152,11 +152,11 @@ def __init__(self, entity: 'Entity', library: 'Library'): self._library = library self._entity = entity - @property + @readonly def Library(self) -> 'Library': return self._library - @property + @readonly def Entity(self) -> 'Entity': return self._entity @@ -173,7 +173,7 @@ class ArchitectureExistsInLibraryError(VHDLModelException): _entity: 'Entity' _architecture: 'Architecture' - def __init__(self, architecture: 'Architecture', entity: 'Entity', library: 'Library'): + def __init__(self, architecture: 'Architecture', entity: 'Entity', library: 'Library') -> None: """ Initializes the exception message based on given architecture, entity and library objects. @@ -186,15 +186,15 @@ def __init__(self, architecture: 'Architecture', entity: 'Entity', library: 'Lib self._entity = entity self._architecture = architecture - @property + @readonly def Library(self) -> 'Library': return self._library - @property + @readonly def Entity(self) -> 'Entity': return self._entity - @property + @readonly def Architecture(self) -> 'Architecture': return self._architecture @@ -210,7 +210,7 @@ class PackageExistsInLibraryError(VHDLModelException): _library: 'Library' _package: 'Package' - def __init__(self, package: 'Package', library: 'Library'): + def __init__(self, package: 'Package', library: 'Library') -> None: """ Initializes the exception message based on given package and library objects. @@ -221,11 +221,11 @@ def __init__(self, package: 'Package', library: 'Library'): self._library = library self._package = package - @property + @readonly def Library(self) -> 'Library': return self._library - @property + @readonly def Package(self) -> 'Package': return self._package @@ -241,7 +241,7 @@ class PackageBodyExistsError(VHDLModelException): _library: 'Library' _packageBody: 'PackageBody' - def __init__(self, packageBody: 'PackageBody', library: 'Library'): + def __init__(self, packageBody: 'PackageBody', library: 'Library') -> None: """ Initializes the exception message based on given package body and library objects. @@ -252,7 +252,7 @@ def __init__(self, packageBody: 'PackageBody', library: 'Library'): self._library = library self._packageBody = packageBody - @property + @readonly def Library(self) -> 'Library': return self._library @@ -272,7 +272,7 @@ class ConfigurationExistsInLibraryError(VHDLModelException): _library: 'Library' _configuration: 'Configuration' - def __init__(self, configuration: 'Configuration', library: 'Library'): + def __init__(self, configuration: 'Configuration', library: 'Library') -> None: """ Initializes the exception message based on given configuration and library objects. @@ -303,7 +303,7 @@ class ContextExistsInLibraryError(VHDLModelException): _library: 'Library' _context: 'Context' - def __init__(self, context: 'Context', library: 'Library'): + def __init__(self, context: 'Context', library: 'Library') -> None: """ Initializes the exception message based on given context and library objects. @@ -334,7 +334,7 @@ class ReferencedLibraryNotExistingError(VHDLModelException): _librarySymbol: Symbol _context: 'Context' - def __init__(self, context: 'Context', librarySymbol: Symbol): + def __init__(self, context: 'Context', librarySymbol: Symbol) -> None: """ Initializes the exception message based on given context and library objects. diff --git a/pyVHDLModel/Expression.py b/pyVHDLModel/Expression.py index 3b91c0c3d..4e1dc8fdc 100644 --- a/pyVHDLModel/Expression.py +++ b/pyVHDLModel/Expression.py @@ -36,7 +36,7 @@ """ from typing import Tuple, List, Iterable, Union -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyVHDLModel.Base import ModelEntity, Direction, Range from pyVHDLModel.Symbol import Symbol @@ -72,12 +72,12 @@ def __str__(self) -> str: class EnumerationLiteral(Literal): _value: str - def __init__(self, value: str): - super().__init__() + def __init__(self, value: str, parent: ModelEntity = None) -> None: + super().__init__(parent) self._value = value - @property + @readonly def Value(self) -> str: return self._value @@ -94,11 +94,11 @@ class NumericLiteral(Literal): class IntegerLiteral(NumericLiteral): _value: int - def __init__(self, value: int): + def __init__(self, value: int) -> None: super().__init__() self._value = value - @property + @readonly def Value(self) -> int: return self._value @@ -110,11 +110,11 @@ def __str__(self) -> str: class FloatingPointLiteral(NumericLiteral): _value: float - def __init__(self, value: float): + def __init__(self, value: float) -> None: super().__init__() self._value = value - @property + @readonly def Value(self) -> float: return self._value @@ -126,11 +126,11 @@ def __str__(self) -> str: class PhysicalLiteral(NumericLiteral): _unitName: str - def __init__(self, unitName: str): + def __init__(self, unitName: str) -> None: super().__init__() self._unitName = unitName - @property + @readonly def UnitName(self) -> str: return self._unitName @@ -142,11 +142,11 @@ def __str__(self) -> str: class PhysicalIntegerLiteral(PhysicalLiteral): _value: int - def __init__(self, value: int, unitName: str): + def __init__(self, value: int, unitName: str) -> None: super().__init__(unitName) self._value = value - @property + @readonly def Value(self) -> int: return self._value @@ -155,11 +155,11 @@ def Value(self) -> int: class PhysicalFloatingLiteral(PhysicalLiteral): _value: float - def __init__(self, value: float, unitName: str): + def __init__(self, value: float, unitName: str) -> None: super().__init__(unitName) self._value = value - @property + @readonly def Value(self) -> float: return self._value @@ -168,11 +168,11 @@ def Value(self) -> float: class CharacterLiteral(Literal): _value: str - def __init__(self, value: str): + def __init__(self, value: str) -> None: super().__init__() self._value = value - @property + @readonly def Value(self) -> str: return self._value @@ -184,11 +184,11 @@ def __str__(self) -> str: class StringLiteral(Literal): _value: str - def __init__(self, value: str): + def __init__(self, value: str) -> None: super().__init__() self._value = value - @property + @readonly def Value(self) -> str: return self._value @@ -200,11 +200,11 @@ def __str__(self) -> str: class BitStringLiteral(Literal): _value: str - def __init__(self, value: str): + def __init__(self, value: str) -> None: super().__init__() self._value = value - @property + @readonly def Value(self) -> str: return self._value @@ -216,7 +216,7 @@ def __str__(self) -> str: class ParenthesisExpression: #(Protocol): __slots__ = () # FIXME: use ExtendedType? - @property + @readonly def Operand(self) -> ExpressionUnion: return None @@ -228,13 +228,13 @@ class UnaryExpression(BaseExpression): _FORMAT: Tuple[str, str] _operand: ExpressionUnion - def __init__(self, operand: ExpressionUnion): - super().__init__() + def __init__(self, operand: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(parent) self._operand = operand # operand._parent = self # FIXME: operand is provided as None - @property + @readonly def Operand(self): return self._operand @@ -280,8 +280,8 @@ class BinaryExpression(BaseExpression): _leftOperand: ExpressionUnion _rightOperand: ExpressionUnion - def __init__(self, leftOperand: ExpressionUnion, rightOperand: ExpressionUnion): - super().__init__() + def __init__(self, leftOperand: ExpressionUnion, rightOperand: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(parent) self._leftOperand = leftOperand leftOperand._parent = self @@ -538,8 +538,8 @@ class QualifiedExpression(BaseExpression, ParenthesisExpression): _operand: ExpressionUnion _subtype: Symbol - def __init__(self, subtype: Symbol, operand: ExpressionUnion): - super().__init__() + def __init__(self, subtype: Symbol, operand: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(parent) self._operand = operand operand._parent = self @@ -568,8 +568,8 @@ class TernaryExpression(BaseExpression): _secondOperand: ExpressionUnion _thirdOperand: ExpressionUnion - def __init__(self) -> None: - super().__init__() + def __init__(self, parent: ModelEntity = None) -> None: + super().__init__(parent) # FIXME: parameters and initializers are missing !! @@ -616,8 +616,8 @@ class Allocation(BaseExpression): class SubtypeAllocation(Allocation): _subtype: Symbol - def __init__(self, subtype: Symbol): - super().__init__() + def __init__(self, subtype: Symbol, parent: ModelEntity = None) -> None: + super().__init__(parent) self._subtype = subtype subtype._parent = self @@ -634,8 +634,8 @@ def __str__(self) -> str: class QualifiedExpressionAllocation(Allocation): _qualifiedExpression: QualifiedExpression - def __init__(self, qualifiedExpression: QualifiedExpression): - super().__init__() + def __init__(self, qualifiedExpression: QualifiedExpression, parent: ModelEntity = None) -> None: + super().__init__(parent) self._qualifiedExpression = qualifiedExpression qualifiedExpression._parent = self @@ -654,8 +654,8 @@ class AggregateElement(ModelEntity): _expression: ExpressionUnion - def __init__(self, expression: ExpressionUnion): - super().__init__() + def __init__(self, expression: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(parent) self._expression = expression expression._parent = self @@ -675,8 +675,8 @@ def __str__(self) -> str: class IndexedAggregateElement(AggregateElement): _index: int - def __init__(self, index: ExpressionUnion, expression: ExpressionUnion): - super().__init__(expression) + def __init__(self, index: ExpressionUnion, expression: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(expression, parent) self._index = index @@ -692,8 +692,8 @@ def __str__(self) -> str: class RangedAggregateElement(AggregateElement): _range: Range - def __init__(self, rng: Range, expression: ExpressionUnion): - super().__init__(expression) + def __init__(self, rng: Range, expression: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(expression, parent) self._range = rng rng._parent = self @@ -710,8 +710,8 @@ def __str__(self) -> str: class NamedAggregateElement(AggregateElement): _name: Symbol - def __init__(self, name: Symbol, expression: ExpressionUnion): - super().__init__(expression) + def __init__(self, name: Symbol, expression: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(expression, parent) self._name = name name._parent = self @@ -739,8 +739,8 @@ def __str__(self) -> str: class Aggregate(BaseExpression): _elements: List[AggregateElement] - def __init__(self, elements: Iterable[AggregateElement]): - super().__init__() + def __init__(self, elements: Iterable[AggregateElement], parent: ModelEntity = None) -> None: + super().__init__(parent) self._elements = [] for element in elements: diff --git a/pyVHDLModel/Instantiation.py b/pyVHDLModel/Instantiation.py index a7ceab9f8..93cdf0c9e 100644 --- a/pyVHDLModel/Instantiation.py +++ b/pyVHDLModel/Instantiation.py @@ -36,7 +36,7 @@ """ from typing import List, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyVHDLModel.Base import ModelEntity @@ -82,8 +82,8 @@ class PackageInstantiation(PrimaryUnit, GenericInstantiationMixin): _packageReference: PackageReferenceSymbol _genericAssociations: List[GenericAssociationItem] - def __init__(self, identifier: str, uninstantiatedPackage: PackageReferenceSymbol, documentation: Nullable[str] = None): - super().__init__(identifier, documentation) + def __init__(self, identifier: str, uninstantiatedPackage: PackageReferenceSymbol, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, documentation, parent) GenericEntityInstantiationMixin.__init__(self) self._packageReference = uninstantiatedPackage @@ -92,10 +92,10 @@ def __init__(self, identifier: str, uninstantiatedPackage: PackageReferenceSymbo # TODO: extract to mixin self._genericAssociations = [] - @property + @readonly def PackageReference(self) -> PackageReferenceSymbol: return self._packageReference - @property + @readonly def GenericAssociations(self) -> List[GenericAssociationItem]: return self._genericAssociations diff --git a/pyVHDLModel/Interface.py b/pyVHDLModel/Interface.py index 015b185e3..3f74056af 100644 --- a/pyVHDLModel/Interface.py +++ b/pyVHDLModel/Interface.py @@ -36,11 +36,11 @@ """ from typing import Iterable, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyVHDLModel.Symbol import Symbol -from pyVHDLModel.Base import DocumentedEntityMixin, ExpressionUnion, Mode +from pyVHDLModel.Base import ModelEntity, DocumentedEntityMixin, ExpressionUnion, Mode from pyVHDLModel.Object import Constant, Signal, Variable, File from pyVHDLModel.Subprogram import Procedure, Function from pyVHDLModel.Type import Type @@ -60,10 +60,10 @@ class InterfaceItemWithModeMixin(metaclass=ExtendedType, mixin=True): _mode: Mode - def __init__(self, mode: Mode): + def __init__(self, mode: Mode) -> None: self._mode = mode - @property + @readonly def Mode(self) -> Mode: return self._mode @@ -77,7 +77,7 @@ class GenericInterfaceItemMixin(InterfaceItemMixin, mixin=True): class PortInterfaceItemMixin(InterfaceItemMixin, InterfaceItemWithModeMixin, mixin=True): """A ``PortInterfaceItem`` is a mixin class for all port interface items.""" - def __init__(self, mode: Mode): + def __init__(self, mode: Mode) -> None: super().__init__() InterfaceItemWithModeMixin.__init__(self, mode) @@ -89,16 +89,24 @@ class ParameterInterfaceItemMixin(InterfaceItemMixin, mixin=True): @export class GenericConstantInterfaceItem(Constant, GenericInterfaceItemMixin, InterfaceItemWithModeMixin): - def __init__(self, identifiers: Iterable[str], mode: Mode, subtype: Symbol, defaultExpression: Nullable[ExpressionUnion] = None, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, defaultExpression, documentation) + def __init__( + self, + identifiers: Iterable[str], + mode: Mode, + subtype: Symbol, + defaultExpression: Nullable[ExpressionUnion] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, defaultExpression, documentation, parent) GenericInterfaceItemMixin.__init__(self) InterfaceItemWithModeMixin.__init__(self, mode) @export class GenericTypeInterfaceItem(Type, GenericInterfaceItemMixin): - def __init__(self, identifier: str, documentation: Nullable[str] = None): - super().__init__(identifier, documentation) + def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, documentation, parent) GenericInterfaceItemMixin.__init__(self) @@ -109,58 +117,96 @@ class GenericSubprogramInterfaceItem(GenericInterfaceItemMixin): @export class GenericProcedureInterfaceItem(Procedure, GenericInterfaceItemMixin): - def __init__(self, identifier: str, documentation: Nullable[str] = None): - super().__init__(identifier, documentation) + def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, documentation, parent) GenericInterfaceItemMixin.__init__(self) @export class GenericFunctionInterfaceItem(Function, GenericInterfaceItemMixin): - def __init__(self, identifier: str, documentation: Nullable[str] = None): - super().__init__(identifier, documentation) + def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, documentation, parent) GenericInterfaceItemMixin.__init__(self) @export class GenericPackageInterfaceItem(GenericInterfaceItemMixin): - def __init__(self, identifier: str, documentation: Nullable[str] = None): - # super().__init__(identifier, documentation) + def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, documentation, parent) GenericInterfaceItemMixin.__init__(self) @export class PortSignalInterfaceItem(Signal, PortInterfaceItemMixin): - def __init__(self, identifiers: Iterable[str], mode: Mode, subtype: Symbol, defaultExpression: Nullable[ExpressionUnion] = None, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, defaultExpression, documentation) + def __init__( + self, + identifiers: Iterable[str], + mode: Mode, + subtype: Symbol, + defaultExpression: Nullable[ExpressionUnion] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, defaultExpression, documentation, parent) PortInterfaceItemMixin.__init__(self, mode) @export class ParameterConstantInterfaceItem(Constant, ParameterInterfaceItemMixin, InterfaceItemWithModeMixin): - def __init__(self, identifiers: Iterable[str], mode: Mode, subtype: Symbol, defaultExpression: Nullable[ExpressionUnion] = None, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, defaultExpression, documentation) + def __init__( + self, + identifiers: Iterable[str], + mode: Mode, + subtype: Symbol, + defaultExpression: Nullable[ExpressionUnion] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, defaultExpression, documentation, parent) ParameterInterfaceItemMixin.__init__(self) InterfaceItemWithModeMixin.__init__(self, mode) @export class ParameterVariableInterfaceItem(Variable, ParameterInterfaceItemMixin, InterfaceItemWithModeMixin): - def __init__(self, identifiers: Iterable[str], mode: Mode, subtype: Symbol, defaultExpression: Nullable[ExpressionUnion] = None, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, defaultExpression, documentation) + def __init__( + self, + identifiers: Iterable[str], + mode: Mode, + subtype: Symbol, + defaultExpression: Nullable[ExpressionUnion] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, defaultExpression, documentation, parent) ParameterInterfaceItemMixin.__init__(self) InterfaceItemWithModeMixin.__init__(self, mode) @export class ParameterSignalInterfaceItem(Signal, ParameterInterfaceItemMixin, InterfaceItemWithModeMixin): - def __init__(self, identifiers: Iterable[str], mode: Mode, subtype: Symbol, defaultExpression: Nullable[ExpressionUnion] = None, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, defaultExpression, documentation) + def __init__( + self, + identifiers: Iterable[str], + mode: Mode, + subtype: Symbol, + defaultExpression: Nullable[ExpressionUnion] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, defaultExpression, documentation, parent) ParameterInterfaceItemMixin.__init__(self) InterfaceItemWithModeMixin.__init__(self, mode) @export class ParameterFileInterfaceItem(File, ParameterInterfaceItemMixin): - def __init__(self, identifiers: Iterable[str], subtype: Symbol, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, documentation) + def __init__( + self, + identifiers: Iterable[str], + subtype: Symbol, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, documentation, parent) ParameterInterfaceItemMixin.__init__(self) diff --git a/pyVHDLModel/Name.py b/pyVHDLModel/Name.py index 920c009be..2f4e412c7 100644 --- a/pyVHDLModel/Name.py +++ b/pyVHDLModel/Name.py @@ -38,7 +38,7 @@ """ from typing import List, Iterable, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyVHDLModel.Base import ModelEntity, ExpressionUnion @@ -52,8 +52,8 @@ class Name(ModelEntity): _root: Nullable['Name'] # TODO: seams to be unused. There is no reverse linking, or? _prefix: Nullable['Name'] - def __init__(self, identifier: str, prefix: Nullable["Name"] = None): - super().__init__() + def __init__(self, identifier: str, prefix: Nullable["Name"] = None, parent: ModelEntity = None) -> None: + super().__init__(parent) self._identifier = identifier self._normalizedIdentifier = identifier.lower() @@ -65,7 +65,7 @@ def __init__(self, identifier: str, prefix: Nullable["Name"] = None): self._prefix = prefix self._root = prefix._root - @property + @readonly def Identifier(self) -> str: """ The identifier the name is referencing. @@ -74,7 +74,7 @@ def Identifier(self) -> str: """ return self._identifier - @property + @readonly def NormalizedIdentifier(self) -> str: """ The normalized identifier the name is referencing. @@ -83,7 +83,7 @@ def NormalizedIdentifier(self) -> str: """ return self._normalizedIdentifier - @property + @readonly def Root(self) -> 'Name': """ The root (left-most) element in a chain of names. @@ -94,7 +94,7 @@ def Root(self) -> 'Name': """ return self._root - @property + @readonly def Prefix(self) -> Nullable['Name']: """ The name's prefix in a chain of names. @@ -103,7 +103,7 @@ def Prefix(self) -> Nullable['Name']: """ return self._prefix - @property + @readonly def HasPrefix(self) -> bool: """ Returns true, if the name has a prefix. @@ -136,15 +136,15 @@ class SimpleName(Name): class ParenthesisName(Name): _associations: List - def __init__(self, prefix: Name, associations: Iterable): - super().__init__("", prefix) + def __init__(self, prefix: Name, associations: Iterable, parent: ModelEntity = None) -> None: + super().__init__("", prefix, parent) self._associations = [] for association in associations: self._associations.append(association) association._parent = self - @property + @readonly def Associations(self) -> List: return self._associations @@ -156,15 +156,15 @@ def __str__(self) -> str: class IndexedName(Name): _indices: List[ExpressionUnion] - def __init__(self, prefix: Name, indices: Iterable[ExpressionUnion]): - super().__init__("", prefix) + def __init__(self, prefix: Name, indices: Iterable[ExpressionUnion], parent: ModelEntity = None) -> None: + super().__init__("", prefix, parent) self._indices = [] for index in indices: self._indices.append(index) index._parent = self - @property + @readonly def Indices(self) -> List[ExpressionUnion]: return self._indices @@ -187,8 +187,8 @@ class SelectedName(Name): referenced by the selected name via the :attr:`~pyVHDLModel.Name.Prefix` property. """ - def __init__(self, identifier: str, prefix: Name): - super().__init__(identifier, prefix) + def __init__(self, identifier: str, prefix: Name, parent: ModelEntity = None) -> None: + super().__init__(identifier, prefix, parent) def __str__(self) -> str: return f"{self._prefix!s}.{self._identifier}" @@ -196,8 +196,8 @@ def __str__(self) -> str: @export class AttributeName(Name): - def __init__(self, identifier: str, prefix: Name): - super().__init__(identifier, prefix) + def __init__(self, identifier: str, prefix: Name, parent: ModelEntity = None) -> None: + super().__init__(identifier, prefix, parent) def __str__(self) -> str: return f"{self._prefix!s}'{self._identifier}" @@ -210,8 +210,8 @@ class AllName(SelectedName): Most likely this name is used in use-statements. """ - def __init__(self, prefix: Name): - super().__init__("all", prefix) # TODO: the case of 'ALL' is not preserved + def __init__(self, prefix: Name, parent: ModelEntity = None) -> None: + super().__init__("all", prefix, parent) # TODO: the case of 'ALL' is not preserved @export @@ -221,8 +221,8 @@ class OpenName(Name): Most likely this name is used in port associations. """ - def __init__(self) -> None: - super().__init__("open") # TODO: the case of 'ALL' is not preserved + def __init__(self, parent: ModelEntity = None) -> None: + super().__init__("open", parent) # TODO: the case of 'OPEN' is not preserved def __str__(self) -> str: return "open" diff --git a/pyVHDLModel/Namespace.py b/pyVHDLModel/Namespace.py index d9c829d92..e3248e41a 100644 --- a/pyVHDLModel/Namespace.py +++ b/pyVHDLModel/Namespace.py @@ -34,12 +34,13 @@ A helper class to implement namespaces and scopes. """ -from typing import TypeVar, Generic, Dict, Optional as Nullable +from typing import TypeVar, Generic, Dict, Optional as Nullable -from pyVHDLModel.Object import Obj, Signal, Constant, Variable +from pyTooling.Decorators import readonly -from pyVHDLModel.Symbol import ComponentInstantiationSymbol, Symbol, PossibleReference -from pyVHDLModel.Type import Subtype, FullType, BaseType +from pyVHDLModel.Object import Obj, Signal, Constant, Variable +from pyVHDLModel.Symbol import ComponentInstantiationSymbol, Symbol, PossibleReference +from pyVHDLModel.Type import Subtype, FullType, BaseType K = TypeVar("K") O = TypeVar("O") @@ -51,17 +52,17 @@ class Namespace(Generic[K, O]): _subNamespaces: Dict[str, 'Namespace'] _elements: Dict[K, O] - def __init__(self, name: str, parentNamespace: Nullable["Namespace"] = None): + def __init__(self, name: str, parentNamespace: Nullable["Namespace"] = None) -> None: self._name = name self._parentNamespace = parentNamespace self._subNamespaces = {} self._elements = {} - @property + @readonly def Name(self) -> str: return self._name - @property + @readonly def ParentNamespace(self) -> 'Namespace': return self._parentNamespace @@ -70,7 +71,7 @@ def ParentNamespace(self, value: 'Namespace'): self._parentNamespace = value value._subNamespaces[self._name] = self - @property + @readonly def SubNamespaces(self) -> Dict[str, 'Namespace']: return self._subNamespaces diff --git a/pyVHDLModel/Object.py b/pyVHDLModel/Object.py index 4b175f0e6..160cf1d1b 100644 --- a/pyVHDLModel/Object.py +++ b/pyVHDLModel/Object.py @@ -36,7 +36,7 @@ """ from typing import Iterable, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyTooling.Graph import Vertex @@ -62,8 +62,8 @@ class Obj(ModelEntity, MultipleNamedEntityMixin, DocumentedEntityMixin): _subtype: Symbol _objectVertex: Nullable[Vertex] - def __init__(self, identifiers: Iterable[str], subtype: Symbol, documentation: Nullable[str] = None): - super().__init__() + def __init__(self, identifiers: Iterable[str], subtype: Symbol, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(parent) MultipleNamedEntityMixin.__init__(self, identifiers) DocumentedEntityMixin.__init__(self, documentation) @@ -72,11 +72,11 @@ def __init__(self, identifiers: Iterable[str], subtype: Symbol, documentation: N self._objectVertex = None - @property + @readonly def Subtype(self) -> Symbol: return self._subtype - @property + @readonly def ObjectVertex(self) -> Nullable[Vertex]: return self._objectVertex @@ -97,7 +97,7 @@ def __init__(self, defaultExpression: Nullable[ExpressionUnion] = None) -> None: if defaultExpression is not None: defaultExpression._parent = self - @property + @readonly def DefaultExpression(self) -> Nullable[ExpressionUnion]: return self._defaultExpression @@ -123,8 +123,15 @@ class Constant(BaseConstant, WithDefaultExpressionMixin): constant BITS : positive := 8; """ - def __init__(self, identifiers: Iterable[str], subtype: Symbol, defaultExpression: Nullable[ExpressionUnion] = None, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, documentation) + def __init__( + self, + identifiers: Iterable[str], + subtype: Symbol, + defaultExpression: Nullable[ExpressionUnion] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, documentation, parent) WithDefaultExpressionMixin.__init__(self, defaultExpression) @@ -144,10 +151,16 @@ class DeferredConstant(BaseConstant): """ _constantReference: Nullable[Constant] - def __init__(self, identifiers: Iterable[str], subtype: Symbol, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, documentation) + def __init__( + self, + identifiers: Iterable[str], + subtype: Symbol, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, documentation, parent) - @property + @readonly def ConstantReference(self) -> Nullable[Constant]: return self._constantReference @@ -169,8 +182,15 @@ class Variable(Obj, WithDefaultExpressionMixin): variable result : natural := 0; """ - def __init__(self, identifiers: Iterable[str], subtype: Symbol, defaultExpression: Nullable[ExpressionUnion] = None, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, documentation) + def __init__( + self, + identifiers: Iterable[str], + subtype: Symbol, + defaultExpression: Nullable[ExpressionUnion] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, documentation, parent) WithDefaultExpressionMixin.__init__(self, defaultExpression) @@ -198,8 +218,15 @@ class Signal(Obj, WithDefaultExpressionMixin): signal counter : unsigned(7 downto 0) := '0'; """ - def __init__(self, identifiers: Iterable[str], subtype: Symbol, defaultExpression: Nullable[ExpressionUnion] = None, documentation: Nullable[str] = None): - super().__init__(identifiers, subtype, documentation) + def __init__( + self, + identifiers: Iterable[str], + subtype: Symbol, + defaultExpression: Nullable[ExpressionUnion] = None, + documentation: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(identifiers, subtype, documentation, parent) WithDefaultExpressionMixin.__init__(self, defaultExpression) diff --git a/pyVHDLModel/Regions.py b/pyVHDLModel/Regions.py index 00285fa6a..ad8bee57a 100644 --- a/pyVHDLModel/Regions.py +++ b/pyVHDLModel/Regions.py @@ -36,7 +36,7 @@ """ from typing import List, Dict, Iterable, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyVHDLModel.Object import Constant, SharedVariable, File, Variable, Signal @@ -80,47 +80,47 @@ def __init__(self, declaredItems: Nullable[Iterable] = None) -> None: self._functions = {} self._procedures = {} - @property + @readonly def DeclaredItems(self) -> List: return self._declaredItems - @property + @readonly def Types(self) -> Dict[str, FullType]: return self._types - @property + @readonly def Subtypes(self) -> Dict[str, Subtype]: return self._subtypes - # @property + # @readonly # def Objects(self) -> Dict[str, Union[Constant, SharedVariable, Signal, File]]: # return self._objects - @property + @readonly def Constants(self) -> Dict[str, Constant]: return self._constants - @property + @readonly def Signals(self) -> Dict[str, Signal]: return self._signals - @property + @readonly def SharedVariables(self) -> Dict[str, SharedVariable]: return self._sharedVariables - @property + @readonly def Files(self) -> Dict[str, File]: return self._files - @property + @readonly def Subprograms(self) -> Dict[str, Subprogram]: return self._subprograms - @property + @readonly def Functions(self) -> Dict[str, Dict[str, Function]]: return self._functions - @property + @readonly def Procedures(self) -> Dict[str, Dict[str, Procedure]]: return self._procedures diff --git a/pyVHDLModel/Sequential.py b/pyVHDLModel/Sequential.py index d40ef7972..36e080047 100644 --- a/pyVHDLModel/Sequential.py +++ b/pyVHDLModel/Sequential.py @@ -36,11 +36,11 @@ """ from typing import List, Iterable, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType -from pyVHDLModel.Base import ModelEntity, ExpressionUnion, Range, BaseChoice, BaseCase, ConditionalMixin, IfBranchMixin, ElsifBranchMixin, ElseBranchMixin, \ - ReportStatementMixin, AssertStatementMixin, WaveformElement +from pyVHDLModel.Base import ModelEntity, ExpressionUnion, Range, BaseChoice, BaseCase, ConditionalMixin, IfBranchMixin, ElsifBranchMixin +from pyVHDLModel.Base import ElseBranchMixin, ReportStatementMixin, AssertStatementMixin, WaveformElement from pyVHDLModel.Symbol import Symbol from pyVHDLModel.Common import Statement, ProcedureCallMixin from pyVHDLModel.Common import SignalAssignmentMixin, VariableAssignmentMixin @@ -56,7 +56,7 @@ class SequentialStatement(Statement): class SequentialStatementsMixin(metaclass=ExtendedType, mixin=True): _statements: List[SequentialStatement] - def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None): + def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None) -> None: # TODO: extract to mixin self._statements = [] if statements is not None: @@ -64,22 +64,28 @@ def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None): self._statements.append(item) item._parent = self - @property + @readonly def Statements(self) -> List[SequentialStatement]: return self._statements @export class SequentialProcedureCall(SequentialStatement, ProcedureCallMixin): - def __init__(self, procedureName: Symbol, parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None, label: Nullable[str] = None): - super().__init__(label) + def __init__( + self, + procedureName: Symbol, + parameterMappings: Nullable[Iterable[ParameterAssociationItem]] = None, + label: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) ProcedureCallMixin.__init__(self, procedureName, parameterMappings) @export class SequentialSignalAssignment(SequentialStatement, SignalAssignmentMixin): - def __init__(self, target: Symbol, label: Nullable[str] = None): - super().__init__(label) + def __init__(self, target: Symbol, label: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(label, parent) SignalAssignmentMixin.__init__(self, target) @@ -87,8 +93,8 @@ def __init__(self, target: Symbol, label: Nullable[str] = None): class SequentialSimpleSignalAssignment(SequentialSignalAssignment): _waveform: List[WaveformElement] - def __init__(self, target: Symbol, waveform: Iterable[WaveformElement], label: Nullable[str] = None): - super().__init__(target, label) + def __init__(self, target: Symbol, waveform: Iterable[WaveformElement], label: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(target, label, parent) # TODO: extract to mixin self._waveform = [] @@ -97,29 +103,36 @@ def __init__(self, target: Symbol, waveform: Iterable[WaveformElement], label: N self._waveform.append(waveformElement) waveformElement._parent = self - @property + @readonly def Waveform(self) -> List[WaveformElement]: return self._waveform @export class SequentialVariableAssignment(SequentialStatement, VariableAssignmentMixin): - def __init__(self, target: Symbol, expression: ExpressionUnion, label: Nullable[str] = None): - super().__init__(label) + def __init__(self, target: Symbol, expression: ExpressionUnion, label: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(label, parent) VariableAssignmentMixin.__init__(self, target, expression) @export class SequentialReportStatement(SequentialStatement, ReportStatementMixin): - def __init__(self, message: ExpressionUnion, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None): - super().__init__(label) + def __init__(self, message: ExpressionUnion, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(label, parent) ReportStatementMixin.__init__(self, message, severity) @export class SequentialAssertStatement(SequentialStatement, AssertStatementMixin): - def __init__(self, condition: ExpressionUnion, message: Nullable[ExpressionUnion] = None, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None): - super().__init__(label) + def __init__( + self, + condition: ExpressionUnion, + message: Nullable[ExpressionUnion] = None, + severity: Nullable[ExpressionUnion] = None, + label: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) AssertStatementMixin.__init__(self, condition, message, severity) @@ -132,29 +145,29 @@ class CompoundStatement(SequentialStatement): class Branch(ModelEntity, SequentialStatementsMixin): """A ``Branch`` is a base-class for all branches in a if statement.""" - def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None): - super().__init__() + def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None: + super().__init__(parent) SequentialStatementsMixin.__init__(self, statements) @export class IfBranch(Branch, IfBranchMixin): - def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None): - super().__init__(statements) + def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None: + super().__init__(statements, parent) IfBranchMixin.__init__(self, condition) @export class ElsifBranch(Branch, ElsifBranchMixin): - def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None): - super().__init__(statements) + def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None: + super().__init__(statements, parent) ElsifBranchMixin.__init__(self, condition) @export class ElseBranch(Branch, ElseBranchMixin): - def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None): - super().__init__(statements) + def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None: + super().__init__(statements, parent) ElseBranchMixin.__init__(self) @@ -164,8 +177,15 @@ class IfStatement(CompoundStatement): _elsifBranches: List['ElsifBranch'] _elseBranch: Nullable[ElseBranch] - def __init__(self, ifBranch: IfBranch, elsifBranches: Nullable[Iterable[ElsifBranch]] = None, elseBranch: Nullable[ElseBranch] = None, label: Nullable[str] = None): - super().__init__(label) + def __init__( + self, + ifBranch: IfBranch, + elsifBranches: Nullable[Iterable[ElsifBranch]] = None, + elseBranch: Nullable[ElseBranch] = None, + label: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) self._ifBranch = ifBranch ifBranch._parent = self @@ -182,7 +202,7 @@ def __init__(self, ifBranch: IfBranch, elsifBranches: Nullable[Iterable[ElsifBra else: self._elseBranch = None - @property + @readonly def IfBranch(self) -> IfBranch: return self._ifBranch @@ -204,8 +224,8 @@ class SequentialChoice(BaseChoice): class IndexedChoice(SequentialChoice): _expression: ExpressionUnion - def __init__(self, expression: ExpressionUnion): - super().__init__() + def __init__(self, expression: ExpressionUnion, parent: ModelEntity = None) -> None: + super().__init__(parent) self._expression = expression # expression._parent = self # FIXME: received None @@ -222,8 +242,8 @@ def __str__(self) -> str: class RangedChoice(SequentialChoice): _range: 'Range' - def __init__(self, rng: 'Range'): - super().__init__() + def __init__(self, rng: 'Range', parent: ModelEntity = None) -> None: + super().__init__(parent) self._range = rng rng._parent = self @@ -240,8 +260,8 @@ def __str__(self) -> str: class SequentialCase(BaseCase, SequentialStatementsMixin): _choices: List - def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None): - super().__init__() + def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None: + super().__init__(parent) SequentialStatementsMixin.__init__(self, statements) # TODO: what about choices? @@ -253,8 +273,8 @@ def Choices(self) -> List[BaseChoice]: @export class Case(SequentialCase): - def __init__(self, choices: Iterable[SequentialChoice], statements: Nullable[Iterable[SequentialStatement]] = None): - super().__init__(statements) + def __init__(self, choices: Iterable[SequentialChoice], statements: Nullable[Iterable[SequentialStatement]] = None, parent: ModelEntity = None) -> None: + super().__init__(statements, parent) self._choices = [] if choices is not None: @@ -281,8 +301,8 @@ class CaseStatement(CompoundStatement): _expression: ExpressionUnion _cases: List[SequentialCase] - def __init__(self, expression: ExpressionUnion, cases: Iterable[SequentialCase], label: Nullable[str] = None): - super().__init__(label) + def __init__(self, expression: ExpressionUnion, cases: Iterable[SequentialCase], label: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(label, parent) self._expression = expression expression._parent = self @@ -306,8 +326,8 @@ def Cases(self) -> List[SequentialCase]: class LoopStatement(CompoundStatement, SequentialStatementsMixin): """A ``LoopStatement`` is a base-class for all loop statements.""" - def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None): - super().__init__(label) + def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(label, parent) SequentialStatementsMixin.__init__(self, statements) @@ -321,8 +341,8 @@ class ForLoopStatement(LoopStatement): _loopIndex: str _range: Range - def __init__(self, loopIndex: str, rng: Range, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None): - super().__init__(statements, label) + def __init__(self, loopIndex: str, rng: Range, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(statements, label, parent) self._loopIndex = loopIndex @@ -340,8 +360,14 @@ def Range(self) -> Range: @export class WhileLoopStatement(LoopStatement, ConditionalMixin): - def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None): - super().__init__(statements, label) + def __init__( + self, + condition: ExpressionUnion, + statements: Nullable[Iterable[SequentialStatement]] = None, + label: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(statements, label, parent) ConditionalMixin.__init__(self, condition) @@ -351,8 +377,8 @@ class LoopControlStatement(SequentialStatement, ConditionalMixin): _loopReference: LoopStatement - def __init__(self, condition: Nullable[ExpressionUnion] = None, loopLabel: Nullable[str] = None) -> None: # TODO: is this label (currently str) a Name or a Label class? - super().__init__() + def __init__(self, condition: Nullable[ExpressionUnion] = None, loopLabel: Nullable[str] = None, parent: ModelEntity = None) -> None: # TODO: is this label (currently str) a Name or a Label class? + super().__init__(parent) ConditionalMixin.__init__(self, condition) # TODO: loopLabel @@ -382,8 +408,8 @@ class NullStatement(SequentialStatement): class ReturnStatement(SequentialStatement, ConditionalMixin): _returnValue: ExpressionUnion - def __init__(self, returnValue: Nullable[ExpressionUnion] = None) -> None: - super().__init__() + def __init__(self, returnValue: Nullable[ExpressionUnion] = None, parent: ModelEntity = None) -> None: + super().__init__(parent) ConditionalMixin.__init__(self, returnValue) # TODO: return value? @@ -398,8 +424,15 @@ class WaitStatement(SequentialStatement, ConditionalMixin): _sensitivityList: Nullable[List[Symbol]] _timeout: ExpressionUnion - def __init__(self, sensitivityList: Nullable[Iterable[Symbol]] = None, condition: Nullable[ExpressionUnion] = None, timeout: Nullable[ExpressionUnion] = None, label: Nullable[str] = None): - super().__init__(label) + def __init__( + self, + sensitivityList: Nullable[Iterable[Symbol]] = None, + condition: Nullable[ExpressionUnion] = None, + timeout: Nullable[ExpressionUnion] = None, + label: Nullable[str] = None, + parent: ModelEntity = None + ) -> None: + super().__init__(label, parent) ConditionalMixin.__init__(self, condition) if sensitivityList is None: @@ -427,7 +460,7 @@ def Timeout(self) -> ExpressionUnion: class SequentialDeclarationsMixin(metaclass=ExtendedType, mixin=True): _declaredItems: List - def __init__(self, declaredItems: Iterable): + def __init__(self, declaredItems: Iterable) -> None: # TODO: extract to mixin self._declaredItems = [] # TODO: convert to dict if declaredItems is not None: diff --git a/pyVHDLModel/Subprogram.py b/pyVHDLModel/Subprogram.py index 0a3cd0836..d9a8748ef 100644 --- a/pyVHDLModel/Subprogram.py +++ b/pyVHDLModel/Subprogram.py @@ -36,7 +36,7 @@ """ from typing import List, Optional as Nullable -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, DocumentedEntityMixin @@ -52,8 +52,8 @@ class Subprogram(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): _statements: List['SequentialStatement'] _isPure: bool - def __init__(self, identifier: str, documentation: Nullable[str] = None): - super().__init__() + def __init__(self, identifier: str, isPure: bool, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(parent) NamedEntityMixin.__init__(self, identifier) DocumentedEntityMixin.__init__(self, documentation) @@ -61,46 +61,45 @@ def __init__(self, identifier: str, documentation: Nullable[str] = None): self._parameterItems = [] # TODO: convert to dict self._declaredItems = [] # TODO: use mixin class self._statements = [] # TODO: use mixin class + self._isPure = isPure - @property + @readonly def GenericItems(self) -> List['GenericInterfaceItem']: return self._genericItems - @property + @readonly def ParameterItems(self) -> List['ParameterInterfaceItem']: return self._parameterItems - @property + @readonly def DeclaredItems(self) -> List: return self._declaredItems - @property + @readonly def Statements(self) -> List['SequentialStatement']: return self._statements - @property + @readonly def IsPure(self) -> bool: return self._isPure @export class Procedure(Subprogram): - def __init__(self, identifier: str, documentation: Nullable[str] = None): - super().__init__(identifier, documentation) - self._isPure = False + def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, False, documentation, parent) @export class Function(Subprogram): _returnType: Subtype - def __init__(self, identifier: str, isPure: bool = True, documentation: Nullable[str] = None): - super().__init__(identifier, documentation) + def __init__(self, identifier: str, isPure: bool = True, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, isPure, documentation, parent) - self._isPure = isPure # FIXME: return type is missing - @property + @readonly def ReturnType(self) -> Subtype: return self._returnType @@ -111,24 +110,24 @@ class MethodMixin(metaclass=ExtendedType, mixin=True): _protectedType: ProtectedType - def __init__(self, protectedType: ProtectedType): + def __init__(self, protectedType: ProtectedType) -> None: self._protectedType = protectedType protectedType._parent = self - @property + @readonly def ProtectedType(self) -> ProtectedType: return self._protectedType @export class ProcedureMethod(Procedure, MethodMixin): - def __init__(self, identifier: str, protectedType: ProtectedType): - super().__init__(identifier) + def __init__(self, identifier: str, documentation: Nullable[str] = None, protectedType: Nullable[ProtectedType] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, documentation, parent) MethodMixin.__init__(self, protectedType) @export class FunctionMethod(Function, MethodMixin): - def __init__(self, identifier: str, protectedType: ProtectedType): - super().__init__(identifier) + def __init__(self, identifier: str, isPure: bool = True, documentation: Nullable[str] = None, protectedType: Nullable[ProtectedType] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, isPure, documentation, parent) MethodMixin.__init__(self, protectedType) diff --git a/pyVHDLModel/Symbol.py b/pyVHDLModel/Symbol.py index c754e7a95..d839300c4 100644 --- a/pyVHDLModel/Symbol.py +++ b/pyVHDLModel/Symbol.py @@ -35,11 +35,12 @@ Symbols are entity specific wrappers for names that reference VHDL language entities. """ from enum import Flag, auto -from typing import Any, Optional as Nullable +from typing import Any, Optional as Nullable, Iterable, List, Dict, Mapping -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType +from pyVHDLModel.Base import Range from pyVHDLModel.Name import Name, AllName @@ -101,20 +102,20 @@ class Symbol(metaclass=ExtendedType): _possibleReferences: PossibleReference #: An enumeration to filter possible references. _reference: Nullable[Any] #: The resolved language entity, otherwise ``None``. - def __init__(self, name: Name, possibleReferences: PossibleReference): + def __init__(self, name: Name, possibleReferences: PossibleReference) -> None: self._name = name self._possibleReferences = possibleReferences self._reference = None - @property + @readonly def Name(self) -> Name: return self._name - @property + @readonly def Reference(self) -> Nullable[Any]: return self._reference - @property + @readonly def IsResolved(self) -> bool: return self._reference is not None @@ -149,10 +150,10 @@ class LibraryReferenceSymbol(Symbol): -- ^^^^ """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Library) - @property + @readonly def Library(self) -> Nullable['Library']: return self._reference @@ -176,7 +177,7 @@ class PackageReferenceSymbol(Symbol): -- ^^^^^^^^^^^^^^^^ """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Package) @property @@ -203,7 +204,7 @@ class ContextReferenceSymbol(Symbol): -- ^^^^^^^^^^^^^^^^^^^^^ """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Context) @property @@ -230,7 +231,7 @@ class PackageMemberReferenceSymbol(Symbol): -- ^^^^^^^^^^^^^^^^^^^^^^^^^ """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.PackageMember) @property @@ -257,7 +258,7 @@ class AllPackageMembersReferenceSymbol(Symbol): -- ^^^^^^^^^^^^^^^^^^^^ """ - def __init__(self, name: AllName): + def __init__(self, name: AllName) -> None: super().__init__(name, PossibleReference.PackageMember) @property @@ -284,7 +285,7 @@ class EntityInstantiationSymbol(Symbol): -- ^^^^^^^^^^^^ """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Entity) @property @@ -311,7 +312,7 @@ class ComponentInstantiationSymbol(Symbol): -- ^^^^^^^ """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Component) @property @@ -338,7 +339,7 @@ class ConfigurationInstantiationSymbol(Symbol): -- ^^^^^^^ """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Configuration) @property @@ -367,7 +368,7 @@ class EntitySymbol(Symbol): end architecture; """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Entity) @property @@ -383,7 +384,7 @@ def Entity(self, value: 'Entity') -> None: class ArchitectureSymbol(Symbol): """An entity reference in an entity instantiation with architecture name.""" - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Architecture) @property @@ -411,7 +412,7 @@ class PackageSymbol(Symbol): end package body; """ - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Package) @property @@ -423,9 +424,15 @@ def Package(self, value: 'Package') -> None: self._reference = value +@export +class RecordElementSymbol(Symbol): + def __init__(self, name: Name) -> None: + super().__init__(name, PossibleReference.RecordElement) + + @export class SubtypeSymbol(Symbol): - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Type | PossibleReference.Subtype) @property @@ -462,19 +469,13 @@ class ConstrainedRecordSubtypeSymbol(ConstrainedCompositeSubtypeSymbol): pass -@export -class RecordElementSymbol(Symbol): - def __init__(self, name: Name): - super().__init__(name, PossibleReference.RecordElement) - - @export class SimpleObjectOrFunctionCallSymbol(Symbol): - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.SimpleNameInExpression) @export class IndexedObjectOrFunctionCallSymbol(Symbol): - def __init__(self, name: Name): + def __init__(self, name: Name) -> None: super().__init__(name, PossibleReference.Object | PossibleReference.Function) diff --git a/pyVHDLModel/Type.py b/pyVHDLModel/Type.py index 8493a7c10..bacd45d2a 100644 --- a/pyVHDLModel/Type.py +++ b/pyVHDLModel/Type.py @@ -34,9 +34,9 @@ Types. """ -from typing import Union, List, Iterator, Iterable, Tuple, Optional as Nullable +from typing import Union, List, Iterator, Iterable, Tuple, Optional as Nullable, Dict, Mapping -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.MetaClasses import ExtendedType from pyTooling.Graph import Vertex @@ -52,13 +52,13 @@ class BaseType(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): _objectVertex: Vertex - def __init__(self, identifier: str, documentation: Nullable[str] = None): + def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: """ Initializes underlying ``BaseType``. :param identifier: Name of the type. """ - super().__init__() + super().__init__(parent) NamedEntityMixin.__init__(self, identifier) DocumentedEntityMixin.__init__(self, documentation) @@ -87,27 +87,27 @@ class Subtype(BaseType): _range: Range _resolutionFunction: 'Function' - def __init__(self, identifier: str, symbol: Symbol): - super().__init__(identifier) + def __init__(self, identifier: str, symbol: Symbol, parent: ModelEntity = None) -> None: + super().__init__(identifier, parent) self._type = symbol self._baseType = None self._range = None self._resolutionFunction = None - @property + @readonly def Type(self) -> Symbol: return self._type - @property + @readonly def BaseType(self) -> BaseType: return self._baseType - @property + @readonly def Range(self) -> Range: return self._range - @property + @readonly def ResolutionFunction(self) -> 'Function': return self._resolutionFunction @@ -128,11 +128,11 @@ class RangedScalarType(ScalarType): _leftBound: ExpressionUnion _rightBound: ExpressionUnion - def __init__(self, identifier: str, rng: Union[Range, Name]): - super().__init__(identifier) + def __init__(self, identifier: str, rng: Union[Range, Name], parent: ModelEntity = None) -> None: + super().__init__(identifier, parent) self._range = rng - @property + @readonly def Range(self) -> Union[Range, Name]: return self._range @@ -157,8 +157,8 @@ def __init__(self) -> None: class EnumeratedType(ScalarType, DiscreteTypeMixin): _literals: List[EnumerationLiteral] - def __init__(self, identifier: str, literals: Iterable[EnumerationLiteral]): - super().__init__(identifier) + def __init__(self, identifier: str, literals: Iterable[EnumerationLiteral], parent: ModelEntity = None) -> None: + super().__init__(identifier, parent) self._literals = [] if literals is not None: @@ -166,7 +166,7 @@ def __init__(self, identifier: str, literals: Iterable[EnumerationLiteral]): self._literals.append(literal) literal._parent = self - @property + @readonly def Literals(self) -> List[EnumerationLiteral]: return self._literals @@ -176,8 +176,8 @@ def __str__(self) -> str: @export class IntegerType(RangedScalarType, NumericTypeMixin, DiscreteTypeMixin): - def __init__(self, identifier: str, rng: Union[Range, Name]): - super().__init__(identifier, rng) + def __init__(self, identifier: str, rng: Union[Range, Name], parent: ModelEntity = None) -> None: + super().__init__(identifier, rng, parent) def __str__(self) -> str: return f"{self._identifier} is range {self._range}" @@ -185,8 +185,8 @@ def __str__(self) -> str: @export class RealType(RangedScalarType, NumericTypeMixin): - def __init__(self, identifier: str, rng: Union[Range, Name]): - super().__init__(identifier, rng) + def __init__(self, identifier: str, rng: Union[Range, Name], parent: ModelEntity = None) -> None: + super().__init__(identifier, rng, parent) def __str__(self) -> str: return f"{self._identifier} is range {self._range}" @@ -197,8 +197,15 @@ class PhysicalType(RangedScalarType, NumericTypeMixin): _primaryUnit: str _secondaryUnits: List[Tuple[str, PhysicalIntegerLiteral]] - def __init__(self, identifier: str, rng: Union[Range, Name], primaryUnit: str, units: Iterable[Tuple[str, PhysicalIntegerLiteral]]): - super().__init__(identifier, rng) + def __init__( + self, + identifier: str, + rng: Union[Range, Name], + primaryUnit: str, + units: Iterable[Tuple[str, PhysicalIntegerLiteral]], + parent: ModelEntity = None + ) -> None: + super().__init__(identifier, rng, parent) self._primaryUnit = primaryUnit @@ -207,7 +214,7 @@ def __init__(self, identifier: str, rng: Union[Range, Name], primaryUnit: str, u self._secondaryUnits.append(unit) unit[1]._parent = self - @property + @readonly def PrimaryUnit(self) -> str: return self._primaryUnit @@ -229,8 +236,14 @@ class ArrayType(CompositeType): _dimensions: List[Range] _elementType: Symbol - def __init__(self, identifier: str, indices: Iterable, elementSubtype: Symbol): - super().__init__(identifier) + def __init__( + self, + identifier: str, + indices: Iterable, + elementSubtype: Symbol, + parent: ModelEntity = None + ) -> None: + super().__init__(identifier, parent) self._dimensions = [] for index in indices: @@ -256,8 +269,8 @@ def __str__(self) -> str: class RecordTypeElement(ModelEntity, MultipleNamedEntityMixin): _subtype: Symbol - def __init__(self, identifiers: Iterable[str], subtype: Symbol): - super().__init__() + def __init__(self, identifiers: Iterable[str], subtype: Symbol, parent: ModelEntity = None) -> None: + super().__init__(parent) MultipleNamedEntityMixin.__init__(self, identifiers) self._subtype = subtype @@ -275,8 +288,8 @@ def __str__(self) -> str: class RecordType(CompositeType): _elements: List[RecordTypeElement] - def __init__(self, identifier: str, elements: Nullable[Iterable[RecordTypeElement]] = None): - super().__init__(identifier) + def __init__(self, identifier: str, elements: Nullable[Iterable[RecordTypeElement]] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, parent) self._elements = [] # TODO: convert to dict if elements is not None: @@ -296,8 +309,8 @@ def __str__(self) -> str: class ProtectedType(FullType): _methods: List[Union['Procedure', 'Function']] - def __init__(self, identifier: str, methods: Union[List, Iterator] = None): - super().__init__(identifier) + def __init__(self, identifier: str, methods: Union[List, Iterator] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, parent) self._methods = [] if methods is not None: @@ -314,8 +327,8 @@ def Methods(self) -> List[Union['Procedure', 'Function']]: class ProtectedTypeBody(FullType): _methods: List[Union['Procedure', 'Function']] - def __init__(self, identifier: str, declaredItems: Union[List, Iterator] = None): - super().__init__(identifier) + def __init__(self, identifier: str, declaredItems: Union[List, Iterator] = None, parent: ModelEntity = None) -> None: + super().__init__(identifier, parent) self._methods = [] if declaredItems is not None: @@ -333,8 +346,8 @@ def Methods(self) -> List[Union['Procedure', 'Function']]: class AccessType(FullType): _designatedSubtype: Symbol - def __init__(self, identifier: str, designatedSubtype: Symbol): - super().__init__(identifier) + def __init__(self, identifier: str, designatedSubtype: Symbol, parent: ModelEntity = None) -> None: + super().__init__(identifier, parent) self._designatedSubtype = designatedSubtype designatedSubtype._parent = self @@ -351,8 +364,8 @@ def __str__(self) -> str: class FileType(FullType): _designatedSubtype: Symbol - def __init__(self, identifier: str, designatedSubtype: Symbol): - super().__init__(identifier) + def __init__(self, identifier: str, designatedSubtype: Symbol, parent: ModelEntity = None) -> None: + super().__init__(identifier, parent) self._designatedSubtype = designatedSubtype designatedSubtype._parent = self diff --git a/pyVHDLModel/__init__.py b/pyVHDLModel/__init__.py index fb388cf11..7e4bd17f2 100644 --- a/pyVHDLModel/__init__.py +++ b/pyVHDLModel/__init__.py @@ -58,7 +58,7 @@ from typing import Union, Dict, cast, List, Generator, Optional as Nullable from pyTooling.Common import getFullyQualifiedName -from pyTooling.Decorators import export +from pyTooling.Decorators import export, readonly from pyTooling.Graph import Graph, Vertex, Edge from pyVHDLModel.Exception import VHDLModelException @@ -245,7 +245,7 @@ def __eq__(self, other: Any) -> bool: else: raise TypeError("Second operand is not of type 'VHDLVersion'.") - @property + @readonly def IsVHDL(self) -> bool: """ Checks if the version is a VHDL (not VHDL-AMS) version. @@ -254,7 +254,7 @@ def IsVHDL(self) -> bool: """ return self in (self.VHDL87, self.VHDL93, self.VHDL2002, self.VHDL2008, self.VHDL2019) - @property + @readonly def IsAMS(self) -> bool: """ Checks if the version is a VHDL-AMS (not VHDL) version. @@ -298,7 +298,7 @@ def __repr__(self) -> str: @unique class ObjectClass(Enum): """ - An ``ObjectClass`` is an enumeration. It represents an object's class (``constant``, ``signal``, ...). + An ``ObjectClass`` is an enumeration and represents an object's class (``constant``, ``signal``, ...). In case no *object class* is defined, ``Default`` is used, so the *object class* is inferred from context. """ @@ -325,39 +325,49 @@ def __str__(self) -> str: @export @unique class DesignUnitKind(Flag): - Context = auto() - Package = auto() - PackageBody = auto() - Entity = auto() - Architecture = auto() - Configuration = auto() + """ + A ``DesignUnitKind`` is an enumeration and represents the kind of design unit (``Entity``, ``Architecture``, ...). + + """ + Context = auto() #: Context + Package = auto() #: Package + PackageBody = auto() #: Package Body + Entity = auto() #: Entity + Architecture = auto() #: Architecture + Configuration = auto() #: Configuration - Primary = Context | Configuration | Entity | Package - Secondary = PackageBody | Architecture - WithContext = Configuration | Package | Entity | PackageBody | Architecture - WithDeclaredItems = Package | Entity | PackageBody | Architecture + Primary = Context | Configuration | Entity | Package #: List of primary design units. + Secondary = PackageBody | Architecture #: List of secondary design units. + WithContext = Configuration | Package | Entity | PackageBody | Architecture #: List of design units with a context. + WithDeclaredItems = Package | Entity | PackageBody | Architecture #: List of design units having a declaration region. - All = Primary | Secondary + All = Primary | Secondary #: List of all design units. @export @unique class DependencyGraphVertexKind(Flag): - Document = auto() - Library = auto() + """ + A ``DependencyGraphVertexKind`` is an enumeration and represents the kind of vertex in the dependency graph. + """ + Document = auto() #: A document (VHDL source file). + Library = auto() #: A VHDL library. - Context = auto() - Package = auto() - PackageBody = auto() - Entity = auto() - Architecture = auto() - Component = auto() - Configuration = auto() + Context = auto() #: A context design unit. + Package = auto() #: A package design unit. + PackageBody = auto() #: A package body design unit. + Entity = auto() #: A entity design unit. + Architecture = auto() #: A architecture design unit. + Component = auto() #: A VHDL component. + Configuration = auto() #: A configuration design unit. @export @unique class DependencyGraphEdgeKind(Flag): + """ + A ``DependencyGraphEdgeKind`` is an enumeration and represents the kind of edge in the dependency graph. + """ Document = auto() Library = auto() Context = auto() @@ -391,6 +401,9 @@ class DependencyGraphEdgeKind(Flag): @export @unique class ObjectGraphVertexKind(Flag): + """ + A ``ObjectGraphVertexKind`` is an enumeration and represents the kind of vertex in the object graph. + """ Type = auto() Subtype = auto() @@ -406,6 +419,9 @@ class ObjectGraphVertexKind(Flag): @export @unique class ObjectGraphEdgeKind(Flag): + """ + A ``ObjectGraphEdgeKind`` is an enumeration and represents the kind of edge in the object graph. + """ BaseType = auto() Subtype = auto() @@ -415,8 +431,18 @@ class ObjectGraphEdgeKind(Flag): @export class Design(ModelEntity): """ - A ``Design`` represents all loaded and analysed files (see :class:`~pyVHDLModel.Document`). It's the root of this - document-object-model (DOM). It contains at least one VHDL library (see :class:`~pyVHDLModel.Library`). + A ``Design`` represents set of VHDL libraries as well as all loaded and analysed source files (see :class:`~pyVHDLModel.Document`). + + It's the root of this code document-object-model (CodeDOM). It contains at least one VHDL library (see :class:`~pyVHDLModel.Library`). When the design is + analysed (see :meth:`Analyze`), multiple graph data structures will be created and populated with vertices and edges. As a first result, the design's compile + order and hierarchy can be iterated. As a second result, the design's *top-level* is identified and referenced from the design (see :attr:`TopLevel`). + + The *design* contains references to the following graphs: + + * :attr:`DependencyGraph` + * :attr:`CompileOrderGraph` + * :attr:`HierarchyGraph` + * :attr:`ObjectGraph` """ _name: Nullable[str] #: Name of the design _libraries: Dict[str, 'Library'] #: List of all libraries defined for a design. @@ -424,7 +450,7 @@ class Design(ModelEntity): _dependencyGraph: Graph[None, None, None, None, None, None, None, None, str, DesignUnit, None, None, None, None, None, None, None, None, None, None, None, None, None] #: The graph of all dependencies in the designs. _compileOrderGraph: Graph[None, None, None, None, None, None, None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] #: A graph derived from dependency graph containing the order of documents for compilation. _hierarchyGraph: Graph[None, None, None, None, None, None, None, None, str, DesignUnit, None, None, None, None, None, None, None, None, None, None, None, None, None] #: A graph derived from dependency graph containing the design hierarchy. - _objectGraph: Graph[None, None, None, None, None, None, None, None, str, Obj, None, None, None, None, None, None, None, None, None, None, None, None, None] #: The graph of all types and objects in the design. + _objectGraph: Graph[None, None, None, None, None, None, None, None, str, Obj, None, None, None, None, None, None, None, None, None, None, None, None, None] #: The graph of all types and objects in the design. _toplevel: Union[Entity, Configuration] #: When computed, the toplevel design unit is cached in this field. def __init__(self, name: Nullable[str] = None) -> None: @@ -445,34 +471,72 @@ def __init__(self, name: Nullable[str] = None) -> None: self._objectGraph = Graph() self._toplevel = None - @property + @readonly def Libraries(self) -> Dict[str, 'Library']: - """Returns a list of all libraries specified for this design.""" + """ + Read-only property to access the dictionary of library names and VHDL libraries (:attr:`_libraries`). + + :returns: A dictionary of library names and VHDL libraries. + """ return self._libraries - @property + @readonly def Documents(self) -> List['Document']: - """Returns a list of all documents (files) loaded for this design.""" + """ + Read-only property to access the list of all documents (VHDL source files) loaded for this design (:attr:`_documents`). + + :returns: A list of all documents. + """ return self._documents - @property + @readonly def CompileOrderGraph(self) -> Graph: + """ + Read-only property to access the compile-order graph (:attr:`_compileOrderGraph`). + + :returns: Reference to the compile-order graph. + """ return self._compileOrderGraph - @property + @readonly def DependencyGraph(self) -> Graph: + """ + Read-only property to access the dependency graph (:attr:`_dependencyGraph`). + + :returns: Reference to the dependency graph. + """ return self._dependencyGraph - @property + @readonly def HierarchyGraph(self) -> Graph: + """ + Read-only property to access the hierarchy graph (:attr:`_hierarchyGraph`). + + :returns: Reference to the hierarchy graph. + """ return self._hierarchyGraph - @property + @readonly def ObjectGraph(self) -> Graph: + """ + Read-only property to access the object graph (:attr:`_objectGraph`). + + :returns: Reference to the object graph. + """ return self._objectGraph - @property - def TopLevel(self) -> 'Entity': + @readonly + def TopLevel(self) -> Union[Entity, Configuration]: + """ + Read-only property to access the design's *top-level* (:attr:`_toplevel`). + + When called the first time, the hierarchy graph is checked for its root elements. When there is only one root element in the graph, a new field ``toplevel`` + is added to :attr:`_hierarchyGraph` referencing that single element. In addition, the result is cached in :attr:`_toplevel`. + + :returns: Reference to the design's *top-level*. + :raises VHDLModelException: If the hierarchy graph is not yet computed from dependency graph. + :raises VHDLModelException: If there is more than one *top-level*. + """ # Check for cached result if self._toplevel is not None: return self._toplevel @@ -485,45 +549,62 @@ def TopLevel(self) -> 'Entity': toplevel = roots[0] self._hierarchyGraph["toplevel"] = toplevel self._toplevel = toplevel.Value + return toplevel.Value else: raise VHDLModelException(f"Found more than one toplevel: {', '.join(roots)}") - def _LoadLibrary(self, library: 'Library') -> None: - libraryIdentifier = library.NormalizedIdentifier - if libraryIdentifier in self._libraries: - raise LibraryExistsInDesignError(library) + def LoadStdLibrary(self) -> 'Library': + """ + Load the predefined VHDL library ``std`` into the design. - self._libraries[libraryIdentifier] = library - library._parent = self + This will create a virtual source code file ``std.vhdl`` and register VHDL design units of library ``std`` to that file. - def LoadStdLibrary(self) -> 'Library': + :returns: The library object of library ``std``. + """ from pyVHDLModel.STD import Std - doc = Document(Path("std.vhdl")) + doc = Document(Path("std.vhdl"), parent=self) library = Std() for designUnit in library.IterateDesignUnits(): doc._AddDesignUnit(designUnit) - self._LoadLibrary(library) + self.AddLibrary(library) return library def LoadIEEELibrary(self) -> 'Library': + """ + Load the predefined VHDL library ``ieee`` into the design. + + This will create a virtual source code file ``ieee.vhdl`` and register VHDL design units of library ``ieee`` to that file. + + :returns: The library object of library ``ieee``. + """ from pyVHDLModel.IEEE import Ieee - doc = Document(Path("ieee.vhdl")) + doc = Document(Path("ieee.vhdl"), parent=self) library = Ieee() for designUnit in library.IterateDesignUnits(): doc._AddDesignUnit(designUnit) - self._LoadLibrary(library) + self.AddLibrary(library) return library def AddLibrary(self, library: 'Library') -> None: + """ + Add a VHDL library to the design. + + Ensure the libraries name doesn't collide with existing libraries in the design. |br| + If ok, set the libraries parent reference to the design. + + :param library: Library object to loaded. + :raises LibraryExistsInDesignError: If the library already exists in the design. + :raises LibraryRegisteredToForeignDesignError: If library is already used by a different design. + """ libraryIdentifier = library.NormalizedIdentifier if libraryIdentifier in self._libraries: raise LibraryExistsInDesignError(library) @@ -535,18 +616,73 @@ def AddLibrary(self, library: 'Library') -> None: library._parent = self def GetLibrary(self, libraryName: str) -> 'Library': + """ + Return an (existing) VHDL library object of name ``libraryName``. + + If the requested VHDL library doesn't exist, a new VHDL library with that name will be created. + + :param libraryName: Name of the requested VHDL library. + :returns: The VHDL library object. + """ libraryIdentifier = libraryName.lower() try: return self._libraries[libraryIdentifier] except KeyError: - lib = Library(libraryName) + lib = Library(libraryName, parent=self) self._libraries[libraryIdentifier] = lib lib._parent = self return lib # TODO: allow overloaded parameter library to be str? def AddDocument(self, document: 'Document', library: 'Library') -> None: - if library.NormalizedIdentifier not in self._libraries: + """ + Add a document (VHDL source file) to the design and register all embedded design units to the given VHDL library. + + .. rubric:: Algorithm + + 1. Iterate all entities in the document + + 1. Check if entity name might exist in target library. + 2. Add entity to library and update library membership. + + 2. Iterate all architectures in the document + + 1. Check if architecture name might exist in target library. + 2. Add architecture to library and update library membership. + + 3. Iterate all packages in the document + + 1. Check if package name might exist in target library. + 2. Add package to library and update library membership. + + 4. Iterate all package bodies in the document + + 1. Check if package body name might exist in target library. + 2. Add package body to library and update library membership. + + 5. Iterate all configurations in the document + + 1. Check if configuration name might exist in target library. + 2. Add configuration to library and update library membership. + + 6. Iterate all contexts in the document + + 1. Check if context name might exist in target library. + 2. Add context to library and update library membership. + + :param document: The VHDL source code file. + :param library: The VHDL library used to register the embedded design units to. + :raises LibraryNotRegisteredError: If the given VHDL library is not a library in the design. + :raises EntityExistsInLibraryError: If the processed entity's name is already existing in the VHDL library. + :raises ArchitectureExistsInLibraryError: If the processed architecture's name is already existing in the VHDL library. + :raises PackageExistsInLibraryError: If the processed package's name is already existing in the VHDL library. + :raises PackageBodyExistsError: If the processed package body's name is already existing in the VHDL library. + :raises ConfigurationExistsInLibraryError: If the processed configuration's name is already existing in the VHDL library. + :raises ContextExistsInLibraryError: If the processed context's name is already existing in the VHDL library. + """ + # FIXME: this checks for the library name, but not the object + # should the libraries parent be checked too? + if library._normalizedIdentifier not in self._libraries: raise LibraryNotRegisteredError(library) self._documents.append(document) @@ -604,14 +740,89 @@ def AddDocument(self, document: 'Document', library: 'Library') -> None: context.Library = library def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]: + """ + Iterate all design units in the design. + + A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units. + + .. rubric:: Algorithm + + * Iterate all VHDL libraries. + + 1. Iterate all contexts in that library. + 2. Iterate all packages in that library. + 3. Iterate all package bodies in that library. + 4. Iterate all entites in that library. + 5. Iterate all architectures in that library. + 6. Iterate all configurations in that library. + + :param filter: An enumeration with possibly multiple flags to filter the returned design units. + :returns: A generator to iterate all matched design units in the design. + + .. seealso:: + + :meth:`pyVHDLModel.Library.IterateDesignUnits` + Iterate all design units in the library. + """ for library in self._libraries.values(): yield from library.IterateDesignUnits(filter) def Analyze(self) -> None: + """ + Analyze the whole design. + + .. rubric:: Algorithm + + 1. Analyze dependencies of design units. |br| + This will also yield the design hierarchy and the compiler order. + 2. Analyze dependencies of types and objects. + + .. seealso:: + + :meth:`AnalyzeDependencies` + Analyze the dependencies of design units. + + :meth:`AnalyzeObjects` + Analyze the dependencies of types and objects. + """ self.AnalyzeDependencies() self.AnalyzeObjects() def AnalyzeDependencies(self) -> None: + """ + Analyze the dependencies of design units. + + .. rubric:: Algorithm + + 1. Create all vertices of the dependency graph by iterating all design units in all libraries. |br| + |rarr| :meth:`CreateDependencyGraph` + 2. Create the compile order graph. |br| + |rarr| :meth:`CreateCompileOrderGraph` + 3. Index all packages. |br| + |rarr| :meth:`IndexPackages` + 4. Index all architectures. |br| + |rarr| :meth:`IndexArchitectures` + 5. Link all contexts |br| + |rarr| :meth:`LinkContexts` + 6. Link all architectures. |br| + |rarr| :meth:`LinkArchitectures` + 7. Link all package bodies. |br| + |rarr| :meth:`LinkPackageBodies` + 8. Link all library references. |br| + |rarr| :meth:`LinkLibraryReferences` + 9. Link all package references. |br| + |rarr| :meth:`LinkPackageReferences` + 10. Link all context references. |br| + |rarr| :meth:`LinkContextReferences` + 11. Link all components. |br| + |rarr| :meth:`LinkComponents` + 12. Link all instantiations. |br| + |rarr| :meth:`LinkInstantiations` + 13. Create the hierarchy graph. |br| + |rarr| :meth:`CreateHierarchyGraph` + 14. Compute the compile order. |br| + |rarr| :meth:`ComputeCompileOrder` + """ self.CreateDependencyGraph() self.CreateCompileOrderGraph() @@ -631,6 +842,20 @@ def AnalyzeDependencies(self) -> None: self.ComputeCompileOrder() def AnalyzeObjects(self) -> None: + """ + Analyze the dependencies of types and objects. + + .. rubric:: Algorithm + + 1. Index all entities. |br| + |rarr| :meth:`IndexEntities` + 2. Index all package bodies. |br| + |rarr| :meth:`IndexPackageBodies` + 3. Import objects. |br| + |rarr| :meth:`ImportObjects` + 4. Create the type and object graph. |br| + |rarr| :meth:`CreateTypeAndObjectGraph` + """ self.IndexEntities() self.IndexPackageBodies() @@ -638,6 +863,55 @@ def AnalyzeObjects(self) -> None: self.CreateTypeAndObjectGraph() def CreateDependencyGraph(self) -> None: + """ + Create all vertices of the dependency graph by iterating all design units in all libraries. + + This method will purely create a sea of vertices without any linking between vertices. The edges will be created later by other methods. |br| + See :meth:`AnalyzeDependencies` for these methods and their algorithmic order. + + Each vertex has the following properties: + + * The vertex' ID is the design unit's identifier. + * The vertex' value references the design unit. + * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`. + * A key-value-pair called ``predefined`` denotes if the referenced design unit is a predefined language entity. + + .. rubric:: Algorithm + + * Iterate all libraries in the design. + + 1. Create a vertex for that library and reference the library by the vertex' value field. |br| + In return, set the library's :attr:`~pyVHDLModel.Library._dependencyVertex` field to reference the created vertex. + 2. Iterate all contexts in that library. + + * Create a vertex for that context and reference the context by the vertex' value field. |br| + In return, set the context's :attr:`~pyVHDLModel.DesignUnit.Context._dependencyVertex` field to reference the created vertex. + + 3. Iterate all packages in that library. + + * Create a vertex for that package and reference the package by the vertex' value field. |br| + In return, set the package's :attr:`~pyVHDLModel.DesignUnit.Package._dependencyVertex` field to reference the created vertex. + + 4. Iterate all package bodies in that library. + + * Create a vertex for that package body and reference the package body by the vertex' value field. |br| + In return, set the package body's :attr:`~pyVHDLModel.DesignUnit.PackageBody._dependencyVertex` field to reference the created vertex. + + 5. Iterate all entities in that library. + + * Create a vertex for that entity and reference the entity by the vertex' value field. |br| + In return, set the entity's :attr:`~pyVHDLModel.DesignUnit.Entity._dependencyVertex` field to reference the created vertex. + + 6. Iterate all architectures in that library. + + * Create a vertex for that architecture and reference the architecture by the vertex' value field. |br| + In return, set the architecture's :attr:`~pyVHDLModel.DesignUnit.Architecture._dependencyVertex` field to reference the created vertex. + + 7. Iterate all configurations in that library. + + * Create a vertex for that configuration and reference the configuration by the vertex' value field. |br| + In return, set the configuration's :attr:`~pyVHDLModel.DesignUnit.Configuration._dependencyVertex` field to reference the created vertex. + """ predefinedLibraries = ("std", "ieee") for libraryIdentifier, library in self._libraries.items(): @@ -684,12 +958,44 @@ def CreateDependencyGraph(self) -> None: configuration._dependencyVertex = dependencyVertex def CreateCompileOrderGraph(self) -> None: + """ + Create a compile-order graph with bidirectional references to the dependency graph. + + Add vertices representing a document (VHDL source file) to the dependency graph. Each "document" vertex in dependency graph is copied into the compile-order + graph and bidirectionally referenced. + + In addition, each vertex of a corresponding design unit in a document is linked to the vertex representing that document to express the design unit in + document relationship. + + Each added vertex has the following properties: + + * The vertex' ID is the document's filename. + * The vertex' value references the document. + * A key-value-pair called ``kind`` denotes the vertex's kind as an enumeration value of type :class:`DependencyGraphVertexKind`. + * A key-value-pair called ``predefined`` does not exist. + + .. rubric:: Algorithm + + * Iterate all documents in the design. + + 1. Create a vertex for that document and reference the document by the vertex' value field. |br| + In return, set the documents's :attr:`~pyVHDLModel.Document._dependencyVertex` field to reference the created vertex. + 2. Copy ... + + 1. Iterate + + """ for document in self._documents: dependencyVertex = Vertex(vertexID=document.Path.name, value=document, graph=self._dependencyGraph) dependencyVertex["kind"] = DependencyGraphVertexKind.Document document._dependencyVertex = dependencyVertex - compilerOrderVertex = dependencyVertex.Copy(self._compileOrderGraph, copyDict=True, linkingKeyToOriginalVertex="dependencyVertex", linkingKeyFromOriginalVertex="compileOrderVertex") + compilerOrderVertex = dependencyVertex.Copy( + self._compileOrderGraph, + copyDict=True, + linkingKeyToOriginalVertex="dependencyVertex", + linkingKeyFromOriginalVertex="compileOrderVertex" + ) document._compileOrderVertex = compilerOrderVertex for designUnit in document._designUnits: @@ -848,7 +1154,6 @@ def _LinkItems(package: Package): else: print(f"not handled: {item}") - for libraryName in ("std", "ieee"): for package in self.GetLibrary(libraryName).IterateDesignUnits(filter=DesignUnitKind.Package): # type: Package _HandlePackage(package) @@ -873,7 +1178,7 @@ def LinkContexts(self) -> None: dependency graph is added for that relationship. At second, all use clauses are resolved (a use clause my have multiple package member reference symbols). For each - references package, + referenced package, """ for context in self.IterateDesignUnits(DesignUnitKind.Context): # type: Context # Create entries in _referenced*** for the current working library under its real name. @@ -1038,7 +1343,6 @@ def LinkPackageReferences(self) -> None: dependency = designUnit._dependencyVertex.EdgeToVertex(referencedPackage._dependencyVertex) dependency["kind"] = DependencyGraphEdgeKind.UseClause - # All secondary units inherit referenced packages from their primary units. else: if isinstance(designUnit, Architecture): @@ -1308,10 +1612,10 @@ class Library(ModelEntity, NamedEntityMixin): _packages: Dict[str, Package] #: Dictionary of all packages defined in a library. _packageBodies: Dict[str, PackageBody] #: Dictionary of all package bodies defined in a library. - _dependencyVertex: Vertex[None, None, str, Union['Library', DesignUnit], None, None, None, None, None, None, None, None, None, None, None, None, None] + _dependencyVertex: Vertex[None, None, str, Union['Library', DesignUnit], None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the dependency graph representing the library. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateDependencyGraph`. - def __init__(self, identifier: str): - super().__init__() + def __init__(self, identifier: str, parent: ModelEntity = None) -> None: + super().__init__(parent) NamedEntityMixin.__init__(self, identifier) self._contexts = {} @@ -1323,41 +1627,63 @@ def __init__(self, identifier: str): self._dependencyVertex = None - @property + @readonly def Contexts(self) -> Dict[str, Context]: """Returns a list of all context declarations declared in this library.""" return self._contexts - @property + @readonly def Configurations(self) -> Dict[str, Configuration]: """Returns a list of all configuration declarations declared in this library.""" return self._configurations - @property + @readonly def Entities(self) -> Dict[str, Entity]: """Returns a list of all entity declarations declared in this library.""" return self._entities - @property + @readonly def Architectures(self) -> Dict[str, Dict[str, Architecture]]: """Returns a list of all architectures declarations declared in this library.""" return self._architectures - @property + @readonly def Packages(self) -> Dict[str, Package]: """Returns a list of all package declarations declared in this library.""" return self._packages - @property + @readonly def PackageBodies(self) -> Dict[str, PackageBody]: """Returns a list of all package body declarations declared in this library.""" return self._packageBodies - @property + @readonly def DependencyVertex(self) -> Vertex: return self._dependencyVertex def IterateDesignUnits(self, filter: DesignUnitKind = DesignUnitKind.All) -> Generator[DesignUnit, None, None]: + """ + Iterate all design units in the library. + + A union of :class:`DesignUnitKind` values can be given to filter the returned result for suitable design units. + + .. rubric:: Algorithm + + 1. Iterate all contexts in that library. + 2. Iterate all packages in that library. + 3. Iterate all package bodies in that library. + 4. Iterate all entites in that library. + 5. Iterate all architectures in that library. + 6. Iterate all configurations in that library. + + :param filter: An enumeration with possibly multiple flags to filter the returned design units. + :returns: A generator to iterate all matched design units in the design. + + .. seealso:: + + :meth:`pyVHDLModel.Design.IterateDesignUnits` + Iterate all design units in the design. + """ if DesignUnitKind.Context in filter: for context in self._contexts.values(): yield context @@ -1455,7 +1781,7 @@ def __repr__(self) -> str: class Document(ModelEntity, DocumentedEntityMixin): """A ``Document`` represents a sourcefile. It contains *primary* and *secondary* design units.""" - _path: Path #: path to the document. ``None`` if virtual document. + _path: Path #: path to the document. ``None`` if virtual document. _designUnits: List[DesignUnit] #: List of all design units defined in a document. _contexts: Dict[str, Context] #: Dictionary of all contexts defined in a document. _configurations: Dict[str, Configuration] #: Dictionary of all configurations defined in a document. @@ -1467,11 +1793,11 @@ class Document(ModelEntity, DocumentedEntityMixin): _verificationProperties: Dict[str, VerificationProperty] #: Dictionary of all PSL verification properties defined in a document. _verificationModes: Dict[str, VerificationMode] #: Dictionary of all PSL verification modes defined in a document. - _dependencyVertex: Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] + _dependencyVertex: Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] #: Reference to the vertex in the dependency graph representing the document. |br| This reference is set by :meth:`~pyVHDLModel.Design.CreateCompileOrderGraph`. _compileOrderVertex: Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None] - def __init__(self, path: Path, documentation: Nullable[str] = None): - super().__init__() + def __init__(self, path: Path, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: + super().__init__(parent) DocumentedEntityMixin.__init__(self, documentation) self._path = path @@ -1672,61 +1998,61 @@ def _AddDesignUnit(self, item: DesignUnit) -> None: self._designUnits.append(item) item._parent = self - @property + @readonly def Path(self) -> Path: return self._path - @property + @readonly def DesignUnits(self) -> List[DesignUnit]: """Returns a list of all design units declarations found in this document.""" return self._designUnits - @property + @readonly def Contexts(self) -> Dict[str, Context]: """Returns a list of all context declarations found in this document.""" return self._contexts - @property + @readonly def Configurations(self) -> Dict[str, Configuration]: """Returns a list of all configuration declarations found in this document.""" return self._configurations - @property + @readonly def Entities(self) -> Dict[str, Entity]: """Returns a list of all entity declarations found in this document.""" return self._entities - @property + @readonly def Architectures(self) -> Dict[str, Dict[str, Architecture]]: """Returns a list of all architecture declarations found in this document.""" return self._architectures - @property + @readonly def Packages(self) -> Dict[str, Package]: """Returns a list of all package declarations found in this document.""" return self._packages - @property + @readonly def PackageBodies(self) -> Dict[str, PackageBody]: """Returns a list of all package body declarations found in this document.""" return self._packageBodies - @property + @readonly def VerificationUnits(self) -> Dict[str, VerificationUnit]: """Returns a list of all verification unit declarations found in this document.""" return self._verificationUnits - @property + @readonly def VerificationProperties(self) -> Dict[str, VerificationProperty]: """Returns a list of all verification property declarations found in this document.""" return self._verificationProperties - @property + @readonly def VerificationModes(self) -> Dict[str, VerificationMode]: """Returns a list of all verification mode declarations found in this document.""" return self._verificationModes - @property + @readonly def CompileOrderVertex(self) -> Vertex[None, None, None, 'Document', None, None, None, None, None, None, None, None, None, None, None, None, None]: return self._compileOrderVertex