# ==================================================================================================================== #
# __ ___ _ ____ _ __ __ _ _ #
# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
# |_| |___/ #
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany #
# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
#
"""
This module contains parts of an abstract document language model for VHDL.
"""
from enum import unique, Enum
from typing import List, Iterable, Union, Optional as Nullable
from pyTooling.Decorators import export, readonly
from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, DocumentedEntityMixin
from pyVHDLModel.Expression import BaseExpression, QualifiedExpression, FunctionCall, TypeConversion, Literal
from pyVHDLModel.Name import Name
from pyVHDLModel.Symbol import Symbol, SubtypeSymbol
ExpressionUnion = Union[
BaseExpression,
QualifiedExpression,
FunctionCall,
TypeConversion,
# ConstantOrSymbol, TODO: ObjectSymbol
Literal,
]
@export
@unique
class EntityClass(Enum):
"""An ``EntityClass`` is an enumeration. It represents a VHDL language entity class (``entity``, ``label``, ...)."""
Entity = 0 #: Entity
Architecture = 1 #: Architecture
Configuration = 2 #: Configuration
Procedure = 3 #: Procedure
Function = 4 #: Function
Package = 5 #: Package
Type = 6 #: Type
Subtype = 7 #: Subtype
Constant = 8 #: Constant
Signal = 9 #: Signal
Variable = 10 #: Variable
Component = 11 #: Component
Label = 12 #: Label
Literal = 13 #: Literal
Units = 14 #: Units
Group = 15 #: Group
File = 16 #: File
Property = 17 #: Property
Sequence = 18 #: Sequence
View = 19 #: View
Others = 20 #: Others
@export
class Attribute(ModelEntity, NamedEntityMixin, DocumentedEntityMixin):
"""
Represents an attribute declaration.
.. admonition:: Example
.. code-block:: VHDL
attribute TotalBits : natural;
"""
_subtype: Symbol #: Reference to the attribute's subtype.
def __init__(
self,
identifier: str,
subtype: Symbol,
documentation: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes an attribute declaration.
:param identifier: The identifier of a model entity.
:param subtype: Reference to the attribute's subtype.
:param documentation: The documentation comment associated with this declaration.
:param parent: The parent model entity of this entity.
"""
super().__init__(parent)
NamedEntityMixin.__init__(self, identifier)
DocumentedEntityMixin.__init__(self, documentation)
self._subtype = subtype
subtype.Parent = self
@readonly
def Subtype(self) -> None:
"""
Read-only property to access the subtype (:attr:`_subtype`).
:returns: The subtype.
"""
return self._subtype
[docs]
def __str__(self) -> str:
"""
Formats the attribute declaration.
**Format:** ``attribute myAttribute: bit``
:returns: Formatted attribute declaration.
"""
return f"attribute {self._identifier}: {self._subtype}"
@export
class AttributeSpecification(ModelEntity, DocumentedEntityMixin):
"""
Represents an attribute specification.
.. admonition:: Example
.. code-block:: VHDL
attribute TotalBits of BusType : subtype is 32;
"""
_identifiers: List[Name] #: List of all names the attribute is specified for.
_attribute: Name #: Reference to the specified attribute.
_entityClass: EntityClass #: The entity class the named items belong to.
_expression: ExpressionUnion #: The value assigned to the attribute.
def __init__(
self,
identifiers: Iterable[Name],
attribute: Name,
entityClass: EntityClass,
expression: ExpressionUnion,
documentation: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes an attribute specification.
:param identifiers: List of all names the attribute is specified for.
:param attribute: Reference to the specified attribute.
:param entityClass: The entity class the named items belong to.
:param expression: The value assigned to the attribute.
:param documentation: The documentation comment associated with this declaration.
:param parent: The parent model entity of this entity.
"""
super().__init__(parent)
DocumentedEntityMixin.__init__(self, documentation)
self._identifiers = [] # TODO: convert to dict
for identifier in identifiers:
self._identifiers.append(identifier)
identifier.Parent = self
self._attribute = attribute
attribute.Parent = self
self._entityClass = entityClass
self._expression = expression
expression.Parent = self
@readonly
def Identifiers(self) -> List[Name]:
"""
Read-only property to access the identifiers (:attr:`_identifiers`).
:returns: List of identifiers.
"""
return self._identifiers
@readonly
def Attribute(self) -> Name:
"""
Read-only property to access the attribute (:attr:`_attribute`).
:returns: The attribute.
"""
return self._attribute
@readonly
def EntityClass(self) -> EntityClass:
"""
Read-only property to access the entity class (:attr:`_entityClass`).
:returns: The entity class.
"""
return self._entityClass
@readonly
def Expression(self) -> ExpressionUnion:
"""
Read-only property to access the expression (:attr:`_expression`).
:returns: The expression.
"""
return self._expression
# TODO: move somewhere else
@export
class Alias(ModelEntity, NamedEntityMixin, DocumentedEntityMixin):
"""
Represents an alias declaration.
:attr:`Name` is a :class:`~pyVHDLModel.Symbol.Symbol` - like every other cross-reference in this
model - rather than a bare :class:`~pyVHDLModel.Name.Name`, so it participates in the usual
resolve-later mechanism (:attr:`~pyVHDLModel.Symbol.Symbol.Reference` /
:attr:`~pyVHDLModel.Symbol.Symbol.IsResolved`). Unlike ``PackageReferenceSymbol`` and similar,
there is no single fixed :class:`~pyVHDLModel.Symbol.PossibleReference` value that always fits: an
alias without a subtype indication can refer to almost anything nameable (an object, a type, a
subprogram, a literal, ...), while an alias *with* a subtype indication can - per the LRM - only
ever refer to an object (a constant, variable, signal, or file); the ``possibleReferences`` passed
to the ``Symbol`` should reflect whichever case applies.
.. admonition:: Example
.. code-block:: VHDL
alias a : bit_vector(3 downto 0) is s(3 downto 0);
-- ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
-- optional Subtype Name
alias b is s;
-- ^
-- Name
"""
_name: Symbol #: Reference to the name being aliased.
_subtype: Nullable[SubtypeSymbol] #: Reference to the alias' subtype, or ``None`` if none was given.
def __init__(
self,
identifier: str,
name: Symbol,
subtype: Nullable[SubtypeSymbol] = None,
documentation: Nullable[str] = None,
parent: Nullable[ModelEntity] = None
) -> None:
"""
Initializes an alias declaration.
:param identifier: The identifier of a model entity.
:param name: Reference to the name being aliased.
:param subtype: Reference to the alias' subtype, or ``None`` if none was given.
:param documentation: The documentation comment associated with this declaration.
:param parent: The parent model entity of this entity.
"""
super().__init__(parent)
NamedEntityMixin.__init__(self, identifier)
DocumentedEntityMixin.__init__(self, documentation)
self._name = name
name.Parent = self
self._subtype = subtype
if subtype is not None:
subtype.Parent = self
@readonly
def Name(self) -> Symbol:
"""
Read-only property to access the name (:attr:`_name`).
:returns: The name.
"""
return self._name
@readonly
def Subtype(self) -> Nullable[SubtypeSymbol]:
"""
Read-only property to access the subtype (:attr:`_subtype`).
:returns: The subtype, or ``None`` if not set.
"""
return self._subtype
[docs]
def __str__(self) -> str:
"""
Formats the alias declaration.
**Format:** ``alias myAlias : bit is target``, or without the subtype when none was given
:returns: Formatted alias declaration.
"""
subtype = f" : {self._subtype}" if self._subtype is not None else ""
return f"alias {self._identifier}{subtype} is {self._name}"