# =============================================================================
# ____ _ _ ____ _ _
# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___
# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \
# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | |
# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_|
# |_| |___/
# =============================================================================
# Authors:
# Patrick Lehmann
#
# Package module: DOM: IIR to *** translations.
#
# License:
# ============================================================================
# Copyright (C) 2019-2021 Tristan Gingold
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <gnu.org/licenses>.
#
# SPDX-License-Identifier: GPL-2.0-or-later
# ============================================================================
"""
This module offers helper functions to translate often used IIR substructures to pyGHDL.dom (pyVHDLModel) constructs.
"""
from typing import List, Generator, Type, Dict, Union, Optional as Nullable
from pyTooling.Decorators import export
from pyTooling.Warning import WarningCollector
from pyVHDLModel.Base import ModelEntity, Direction, ExpressionUnion, Range
from pyVHDLModel.Name import Name
from pyVHDLModel.Symbol import Symbol
from pyVHDLModel.Association import AssociationItem
from pyVHDLModel.Interface import GenericInterfaceItemMixin, PortInterfaceItemMixin, ParameterInterfaceItemMixin
from pyVHDLModel.Type import BaseType
from pyVHDLModel.Sequential import SequentialStatement
from pyVHDLModel.Concurrent import ConcurrentStatement
from pyGHDL.libghdl import utils
from pyGHDL.libghdl._types import Iir
from pyGHDL.libghdl.vhdl import nodes
from pyGHDL.dom.Sequential import (
IfStatement,
ForLoopStatement,
WhileLoopStatement,
CaseStatement,
SequentialReportStatement,
SequentialAssertStatement,
WaitStatement,
SequentialSimpleSignalAssignment,
NullStatement,
NextStatement,
ExitStatement,
ReturnStatement,
SequentialProcedureCall,
)
from pyGHDL.dom import Position, DOMException
from pyGHDL.dom._Utils import GetNameOfNode, GetLabelOfNode, GetIirKindOfNode, GetDocumentationOfNode
from pyGHDL.dom.Name import (
SimpleName,
SelectedName,
AttributeName,
ParenthesisName,
AllName,
OpenName,
)
from pyGHDL.dom.Symbol import (
SimpleObjectOrFunctionCallSymbol,
SimpleSubtypeSymbol,
ConstrainedArraySubtypeSymbol,
IndexedObjectOrFunctionCallSymbol,
ConstrainedScalarSubtypeSymbol,
ConstrainedRecordSubtypeSymbol,
RecordElementSymbol,
RangeAttributeSymbol,
)
from pyGHDL.dom.Type import (
IntegerType,
Subtype,
ArrayType,
RecordType,
EnumeratedType,
AccessType,
ProtectedType,
ProtectedTypeBody,
FileType,
PhysicalType,
IncompleteType,
)
from pyGHDL.dom.Range import RangeFromName, SimpleRange
from pyGHDL.dom.Literal import (
IntegerLiteral,
CharacterLiteral,
FloatingPointLiteral,
StringLiteral,
PhysicalIntegerLiteral,
PhysicalFloatingLiteral,
NullLiteral,
)
from pyGHDL.dom.Object import Variable
from pyGHDL.dom.Expression import (
SubtractionExpression,
AdditionExpression,
MultiplyExpression,
DivisionExpression,
InverseExpression,
ExponentiationExpression,
Aggregate,
NegationExpression,
ParenthesisExpression,
ConcatenationExpression,
QualifiedExpression,
ModuloExpression,
RemainderExpression,
AndExpression,
NandExpression,
OrExpression,
NorExpression,
XorExpression,
XnorExpression,
UnaryAndExpression,
UnaryXnorExpression,
UnaryXorExpression,
UnaryNorExpression,
UnaryOrExpression,
UnaryNandExpression,
EqualExpression,
UnequalExpression,
LessThanExpression,
GreaterThanExpression,
GreaterEqualExpression,
LessEqualExpression,
ShiftLeftLogicExpression,
ShiftRightLogicExpression,
ShiftLeftArithmeticExpression,
ShiftRightArithmeticExpression,
RotateLeftExpression,
RotateRightExpression,
RangeExpression,
QualifiedExpressionAllocation,
SubtypeAllocation,
IdentityExpression,
AbsoluteExpression,
MatchingGreaterEqualExpression,
MatchingEqualExpression,
MatchingUnequalExpression,
MatchingLessThanExpression,
MatchingLessEqualExpression,
MatchingGreaterThanExpression,
)
from pyGHDL.dom.Concurrent import (
ConcurrentBlockStatement,
EntityInstantiation,
ConfigurationInstantiation,
ComponentInstantiation,
ProcessStatement,
IfGenerateStatement,
ForGenerateStatement,
CaseGenerateStatement,
ConcurrentSimpleSignalAssignment,
ConcurrentProcedureCall,
GenericAssociationItem,
PortAssociationItem,
ParameterAssociationItem,
ConcurrentAssertStatement,
)
from pyGHDL.dom.Subprogram import Function, Procedure
from pyGHDL.dom.PSL import DefaultClock
[docs]
@export
def GetName(node: Iir) -> Name:
"""
Translates a *name* IIR node to a :class:`~pyVHDLModel.Name.Name`.
A name can be a *simple name* or complex name consisting of *selected*, *parenthesis*, *attribute*, ... *names*.
Complex names are composed as a chain of name objects, which can be traversed using the
:attr:`~pyVHDLModel.Name.Name.Prefix` property.
:param node: The name IIR node to translate.
:return: A name object.
"""
kind = GetIirKindOfNode(node)
if kind == nodes.Iir_Kind.Simple_Name:
name = GetNameOfNode(node)
return SimpleName(node, name)
elif kind == nodes.Iir_Kind.Selected_Name:
name = GetNameOfNode(node)
prefixName = GetName(nodes.Get_Prefix(node))
return SelectedName(node, name, prefixName)
elif kind == nodes.Iir_Kind.Parenthesis_Name:
prefixName = GetName(nodes.Get_Prefix(node))
associations = GetAssociations(node)
return ParenthesisName(node, prefixName, associations)
elif kind == nodes.Iir_Kind.Attribute_Name:
name = GetNameOfNode(node)
prefixName = GetName(nodes.Get_Prefix(node))
return AttributeName(node, name, prefixName)
elif kind == nodes.Iir_Kind.Selected_By_All_Name:
prefixName = GetName(nodes.Get_Prefix(node))
return AllName(node, prefixName)
else:
raise DOMException(f"Unknown name kind '{kind.name}'")
def GetAssociations(node: Iir) -> List:
associations = []
for item in utils.chain_iter(nodes.Get_Association_Chain(node)):
kind = GetIirKindOfNode(item)
if kind in (nodes.Iir_Kind.Association_Element_By_Expression, nodes.Iir_Kind.Association_Element_By_Name):
actual = nodes.Get_Actual(item)
expr = GetExpressionFromNode(actual)
associations.append(expr)
else:
raise DOMException(
f"Unknown association kind '{kind.name}' in array index/slice or function call '{node}'."
)
return associations
[docs]
@export
def GetArrayConstraintsFromSubtypeIndication(
subtypeIndication: Iir,
) -> List:
constraints = []
for constraint in utils.flist_iter(nodes.Get_Index_Constraint_List(subtypeIndication)):
constraintKind = GetIirKindOfNode(constraint)
if constraintKind == nodes.Iir_Kind.Range_Expression:
constraints.append(RangeExpression.parse(constraint))
elif constraintKind in (
nodes.Iir_Kind.Simple_Name,
nodes.Iir_Kind.Parenthesis_Name,
nodes.Iir_Kind.Selected_Name,
nodes.Iir_Kind.Attribute_Name,
):
constraints.append(GetName(constraint))
else:
position = Position.parse(constraint)
raise DOMException(
f"Unknown constraint kind '{constraintKind.name}' for constraint '{constraint}' in subtype indication '{subtypeIndication}' at {position}."
)
return constraints
[docs]
@export
def GetRecordConstraintsFromSubtypeIndication(
subtypeIndication: Iir,
) -> Dict:
constraints = {}
recordElementConstraint = nodes.Get_Owned_Elements_Chain(subtypeIndication)
while recordElementConstraint != nodes.Null_Iir:
recordElementKind = GetIirKindOfNode(recordElementConstraint)
if recordElementKind == nodes.Iir_Kind.Record_Element_Constraint:
recordElementName = GetNameOfNode(recordElementConstraint)
sym = RecordElementSymbol(recordElementConstraint, SimpleName(recordElementConstraint, recordElementName))
constraints[sym] = None
else:
position = Position.parse(recordElementConstraint)
raise DOMException(
f"Unknown constraint kind '{recordElementKind.name}' for constraint '{recordElementConstraint}' in subtype indication '{subtypeIndication}' at {position}."
)
recordElementConstraint = nodes.Get_Chain(recordElementConstraint)
return constraints
[docs]
@export
def GetTypeFromNode(node: Iir) -> BaseType:
typeName = GetNameOfNode(node)
# A doc comment attaches to the type *declaration*, not the type definition inside it, so it is read
# here and handed to whichever class parses the definition.
documentation = GetDocumentationOfNode(node)
typeDefinition = nodes.Get_Type_Definition(node)
if typeDefinition is nodes.Null_Iir:
return IncompleteType(node, typeName, documentation)
kind = GetIirKindOfNode(typeDefinition)
if kind == nodes.Iir_Kind.Enumeration_Type_Definition:
return EnumeratedType.parse(typeName, typeDefinition, documentation)
elif kind == nodes.Iir_Kind.Array_Type_Definition:
return ArrayType.parse(typeName, typeDefinition, documentation)
elif kind == nodes.Iir_Kind.Record_Type_Definition:
return RecordType.parse(typeName, typeDefinition, documentation)
elif kind == nodes.Iir_Kind.Access_Type_Definition:
return AccessType.parse(typeName, typeDefinition, documentation)
elif kind == nodes.Iir_Kind.File_Type_Definition:
return FileType.parse(typeName, typeDefinition, documentation)
elif kind == nodes.Iir_Kind.Protected_Type_Declaration:
return ProtectedType.parse(typeName, typeDefinition, documentation)
else:
position = Position.parse(typeDefinition)
raise DOMException(
f"GetTypeFromNode: Unknown type definition kind '{kind.name}' for type '{typeName}' at {position}."
)
[docs]
@export
def GetAnonymousTypeFromNode(node: Iir) -> BaseType:
typeName = GetNameOfNode(node)
documentation = GetDocumentationOfNode(node)
typeDefinition = nodes.Get_Type_Definition(node)
if typeDefinition is nodes.Null_Iir:
return IncompleteType(node, typeName, documentation)
kind = GetIirKindOfNode(typeDefinition)
if kind == nodes.Iir_Kind.Range_Expression:
r = GetRangeFromNode(typeDefinition)
return IntegerType(node, typeName, r, documentation)
elif kind in (nodes.Iir_Kind.Attribute_Name, nodes.Iir_Kind.Parenthesis_Name):
n = GetName(typeDefinition)
return IntegerType(node, typeName, n, documentation)
elif kind == nodes.Iir_Kind.Physical_Type_Definition:
return PhysicalType.parse(typeName, typeDefinition, documentation)
elif kind == nodes.Iir_Kind.Array_Subtype_Definition:
WarningCollector.Raise(NotImplementedError("Array_Subtype_Definition"))
return ArrayType(typeDefinition, "????", [], None, documentation)
else:
position = Position.parse(typeDefinition)
raise DOMException(
f"GetAnonymousTypeFromNode: Unknown type definition kind '{kind.name}' for type '{typeName}' at {position}."
)
[docs]
@export
def GetSubtypeIndicationFromNode(node: Iir, entity: str, name: str) -> Symbol:
"""
Extracts the subtype indication from an IIR node and translates it to a :class:`~pyVHDLModel.Symbol.Symbol`.
.. note::
This function calls :func:`GetSubtypeIndicationFromIndicationNode`.
This function should be used directly if :pycode:`nodes.Get_Subtype_Indication(...)` was already called or a
subtype indication is return by another getter.
:param node: The IIR node to get the subtype indication from.
:param entity: The entity kind the subtype indication is extracted from (e.g. ``constant``). Used in exception messages.
:param name: The entity's name the subtype indication is extracted from (e.g. ``BITS``). Used in exception messages.
:returns: A symbol representing a reference to a type/subtype and possible array or record constraints.
"""
subtypeIndicationNode = nodes.Get_Subtype_Indication(node)
return GetSubtypeIndicationFromIndicationNode(subtypeIndicationNode, entity, name)
[docs]
@export
def GetSubtypeIndicationFromIndicationNode(subtypeIndicationNode: Iir, entity: str, name: str) -> Symbol:
"""
Translate a subtype indication to a :class:`~pyVHDLModel.Symbol.Symbol`.
:param subtypeIndicationNode: The subtype indication IIR node.
:param entity: The entity kind the subtype indication is extracted from (e.g. ``constant``). Used in exception messages.
:param name: The entity's name the subtype indication is extracted from (e.g. ``BITS``). Used in exception messages.
:returns: A symbol representing a reference to a type/subtype and possible array or record constraints.
"""
if subtypeIndicationNode is nodes.Null_Iir:
raise ValueError("Parameter 'subtypeIndicationNode' is 'Null_Iir'.")
kind = GetIirKindOfNode(subtypeIndicationNode)
if kind in (
nodes.Iir_Kind.Simple_Name,
nodes.Iir_Kind.Selected_Name,
nodes.Iir_Kind.Attribute_Name,
):
return GetSimpleTypeFromNode(subtypeIndicationNode)
elif kind == nodes.Iir_Kind.Subtype_Definition:
return GetScalarConstrainedSubtypeFromNode(subtypeIndicationNode)
elif kind == nodes.Iir_Kind.Array_Subtype_Definition:
return GetArrayConstrainedSubtypeFromNode(subtypeIndicationNode)
elif kind == nodes.Iir_Kind.Record_Subtype_Definition:
return GetRecordConstrainedSubtypeFromNode(subtypeIndicationNode)
else:
raise DOMException(f"Unknown kind '{kind.name}' for an subtype indication in a {entity} of `{name}`.")
[docs]
@export
def GetSimpleTypeFromNode(subtypeIndicationNode: Iir) -> SimpleSubtypeSymbol:
subtypeName = GetName(subtypeIndicationNode)
return SimpleSubtypeSymbol(subtypeIndicationNode, subtypeName)
[docs]
@export
def GetScalarConstrainedSubtypeFromNode(
subtypeIndicationNode: Iir,
) -> Union[SimpleSubtypeSymbol, ConstrainedScalarSubtypeSymbol]:
"""
Translate a scalar subtype indication IIR node to a subtype symbol.
A ``Subtype_Definition`` node carries a type mark and *optionally* a range constraint, because the
node is also used for a subtype indication that only adds a resolution indication
(``subtype resolvedBit is resolveBit myBit;``). Without a range constraint the result is a
:class:`~pyVHDLModel.Symbol.SimpleSubtypeSymbol`; with one it is a
:class:`~pyVHDLModel.Symbol.ConstrainedScalarSubtypeSymbol`, whose constraint is mandatory.
:param subtypeIndicationNode: The subtype indication IIR node.
:returns: The translated subtype symbol.
:raises DOMException: If the range constraint's IIR node isn't a known range.
"""
typeMark = nodes.Get_Subtype_Type_Mark(subtypeIndicationNode)
typeMarkName = GetNameOfNode(typeMark)
simpleTypeMark = SimpleName(typeMark, typeMarkName)
rangeConstraint = nodes.Get_Range_Constraint(subtypeIndicationNode)
if rangeConstraint == nodes.Null_Iir:
return SimpleSubtypeSymbol(subtypeIndicationNode, simpleTypeMark)
rangeKind = GetIirKindOfNode(rangeConstraint)
if rangeKind == nodes.Iir_Kind.Range_Expression:
constraint = GetRangeFromNode(rangeConstraint)
elif rangeKind in (
nodes.Iir_Kind.Attribute_Name,
nodes.Iir_Kind.Parenthesis_Name,
):
# A range attribute like `natural range vector'range`.
constraint = RangeFromName(rangeConstraint, RangeAttributeSymbol(rangeConstraint, GetName(rangeConstraint)))
else:
position = Position.parse(subtypeIndicationNode)
ex = DOMException(
f"Unknown range constraint kind '{rangeKind.name}' in a subtype indication at line {position.Line}."
)
ex.add_note("Supported: a range expression or a range attribute name.")
raise ex
return ConstrainedScalarSubtypeSymbol(subtypeIndicationNode, simpleTypeMark, constraint)
[docs]
@export
def GetArrayConstrainedSubtypeFromNode(
subtypeIndicationNode: Iir,
) -> ConstrainedArraySubtypeSymbol:
typeMark = nodes.Get_Subtype_Type_Mark(subtypeIndicationNode)
typeMarkName = GetNameOfNode(typeMark)
simpleTypeMark = SimpleName(typeMark, typeMarkName)
constraints = GetArrayConstraintsFromSubtypeIndication(subtypeIndicationNode)
return ConstrainedArraySubtypeSymbol(subtypeIndicationNode, simpleTypeMark, constraints)
[docs]
@export
def GetRecordConstrainedSubtypeFromNode(
subtypeIndicationNode: Iir,
) -> ConstrainedRecordSubtypeSymbol:
typeMark = nodes.Get_Subtype_Type_Mark(subtypeIndicationNode)
typeMarkName = GetNameOfNode(typeMark)
simpleTypeMark = SimpleName(typeMark, typeMarkName)
constraints = GetRecordConstraintsFromSubtypeIndication(subtypeIndicationNode)
return ConstrainedRecordSubtypeSymbol(subtypeIndicationNode, simpleTypeMark, constraints)
[docs]
@export
def GetSubtypeFromNode(subtypeNode: Iir) -> Symbol:
subtypeName = GetNameOfNode(subtypeNode)
symbol = GetSubtypeIndicationFromNode(subtypeNode, "subtype", subtypeName)
return Subtype(subtypeNode, subtypeName, symbol)
[docs]
@export
def GetRangeFromNode(node: Iir) -> SimpleRange:
"""
Translate a range IIR node to a :class:`~pyVHDLModel.Base.SimpleRange`.
:param node: The IIR node representing a range.
:return: The translated range object.
"""
direction = nodes.Get_Direction(node)
leftBound = nodes.Get_Left_Limit_Expr(node)
rightBound = nodes.Get_Right_Limit_Expr(node)
return SimpleRange(
node,
GetExpressionFromNode(leftBound),
GetExpressionFromNode(rightBound),
Direction.DownTo if direction else Direction.To,
)
[docs]
@export
def GetDiscreteRangeFromNode(discreteRangeNode: Iir, entity: str) -> Range:
"""
Translate a discrete range IIR node to a :class:`~pyVHDLModel.Base.Range`.
A discrete range is either an explicit range (``0 to 7``, ``vector'range``) or a discrete subtype
indication - a type mark (``bit``), optionally with a range constraint (``integer range 0 to 7``).
Everything but the explicit-bounds form becomes a
:class:`~pyVHDLModel.Base.RangeFromName` wrapping the referenced symbol.
Shared by ``for ... loop`` statements, ``for ... generate`` statements and aggregate choices, which
all use the same VHDL ``discrete_range`` grammar rule.
:param discreteRangeNode: The IIR node representing a discrete range.
:param entity: The construct the discrete range appears in (e.g. ``for...loop``). Used in exception messages.
:returns: The translated range.
:raises DOMException: If the IIR node's kind isn't a known discrete range.
"""
rangeKind = GetIirKindOfNode(discreteRangeNode)
if rangeKind == nodes.Iir_Kind.Range_Expression:
return GetRangeFromNode(discreteRangeNode)
elif rangeKind == nodes.Iir_Kind.Subtype_Definition:
# A subtype indication like `integer range 0 to 7`, which keeps its type mark alongside the
# range constraint.
return RangeFromName(discreteRangeNode, GetScalarConstrainedSubtypeFromNode(discreteRangeNode))
elif rangeKind in (
nodes.Iir_Kind.Simple_Name,
nodes.Iir_Kind.Selected_Name,
):
# A bare type mark like `bit` or `work.pkg.sub`.
return RangeFromName(discreteRangeNode, GetSimpleTypeFromNode(discreteRangeNode))
elif rangeKind in (
nodes.Iir_Kind.Attribute_Name,
nodes.Iir_Kind.Parenthesis_Name,
):
# A range attribute like `vector'range`.
return RangeFromName(discreteRangeNode, RangeAttributeSymbol(discreteRangeNode, GetName(discreteRangeNode)))
position = Position.parse(discreteRangeNode)
ex = DOMException(f"Unknown discrete range kind '{rangeKind.name}' in {entity} at line {position.Line}.")
ex.add_note("Supported: a range expression, a range attribute name, or a discrete subtype indication.")
raise ex
__EXPRESSION_TRANSLATION = {
nodes.Iir_Kind.Simple_Name: SimpleObjectOrFunctionCallSymbol,
nodes.Iir_Kind.Selected_Name: IndexedObjectOrFunctionCallSymbol,
nodes.Iir_Kind.Selected_By_All_Name: IndexedObjectOrFunctionCallSymbol,
nodes.Iir_Kind.Attribute_Name: IndexedObjectOrFunctionCallSymbol,
nodes.Iir_Kind.Parenthesis_Name: IndexedObjectOrFunctionCallSymbol,
nodes.Iir_Kind.Null_Literal: NullLiteral,
nodes.Iir_Kind.Integer_Literal: IntegerLiteral,
nodes.Iir_Kind.Floating_Point_Literal: FloatingPointLiteral,
nodes.Iir_Kind.Physical_Int_Literal: PhysicalIntegerLiteral,
nodes.Iir_Kind.Physical_Fp_Literal: PhysicalFloatingLiteral,
nodes.Iir_Kind.Character_Literal: CharacterLiteral,
nodes.Iir_Kind.String_Literal8: StringLiteral,
nodes.Iir_Kind.Identity_Operator: IdentityExpression,
nodes.Iir_Kind.Negation_Operator: NegationExpression,
nodes.Iir_Kind.Absolute_Operator: AbsoluteExpression,
nodes.Iir_Kind.Range_Expression: RangeExpression,
nodes.Iir_Kind.Addition_Operator: AdditionExpression,
nodes.Iir_Kind.Concatenation_Operator: ConcatenationExpression,
nodes.Iir_Kind.Not_Operator: InverseExpression,
nodes.Iir_Kind.Parenthesis_Expression: ParenthesisExpression,
nodes.Iir_Kind.Substraction_Operator: SubtractionExpression,
nodes.Iir_Kind.Multiplication_Operator: MultiplyExpression,
nodes.Iir_Kind.Division_Operator: DivisionExpression,
nodes.Iir_Kind.Modulus_Operator: ModuloExpression,
nodes.Iir_Kind.Remainder_Operator: RemainderExpression,
nodes.Iir_Kind.Exponentiation_Operator: ExponentiationExpression,
nodes.Iir_Kind.And_Operator: AndExpression,
nodes.Iir_Kind.Nand_Operator: NandExpression,
nodes.Iir_Kind.Or_Operator: OrExpression,
nodes.Iir_Kind.Nor_Operator: NorExpression,
nodes.Iir_Kind.Xor_Operator: XorExpression,
nodes.Iir_Kind.Xnor_Operator: XnorExpression,
nodes.Iir_Kind.Reduction_And_Operator: UnaryAndExpression,
nodes.Iir_Kind.Reduction_Nand_Operator: UnaryNandExpression,
nodes.Iir_Kind.Reduction_Or_Operator: UnaryOrExpression,
nodes.Iir_Kind.Reduction_Nor_Operator: UnaryNorExpression,
nodes.Iir_Kind.Reduction_Xor_Operator: UnaryXorExpression,
nodes.Iir_Kind.Reduction_Xnor_Operator: UnaryXnorExpression,
nodes.Iir_Kind.Equality_Operator: EqualExpression,
nodes.Iir_Kind.Inequality_Operator: UnequalExpression,
nodes.Iir_Kind.Less_Than_Operator: LessThanExpression,
nodes.Iir_Kind.Less_Than_Or_Equal_Operator: LessEqualExpression,
nodes.Iir_Kind.Greater_Than_Operator: GreaterThanExpression,
nodes.Iir_Kind.Greater_Than_Or_Equal_Operator: GreaterEqualExpression,
nodes.Iir_Kind.Match_Equality_Operator: MatchingEqualExpression,
nodes.Iir_Kind.Match_Inequality_Operator: MatchingUnequalExpression,
nodes.Iir_Kind.Match_Less_Than_Operator: MatchingLessThanExpression,
nodes.Iir_Kind.Match_Less_Than_Or_Equal_Operator: MatchingLessEqualExpression,
nodes.Iir_Kind.Match_Greater_Than_Operator: MatchingGreaterThanExpression,
nodes.Iir_Kind.Match_Greater_Than_Or_Equal_Operator: MatchingGreaterEqualExpression,
nodes.Iir_Kind.Sll_Operator: ShiftLeftLogicExpression,
nodes.Iir_Kind.Srl_Operator: ShiftRightLogicExpression,
nodes.Iir_Kind.Sla_Operator: ShiftLeftArithmeticExpression,
nodes.Iir_Kind.Sra_Operator: ShiftRightArithmeticExpression,
nodes.Iir_Kind.Rol_Operator: RotateLeftExpression,
nodes.Iir_Kind.Ror_Operator: RotateRightExpression,
nodes.Iir_Kind.Qualified_Expression: QualifiedExpression,
nodes.Iir_Kind.Aggregate: Aggregate,
nodes.Iir_Kind.Allocator_By_Subtype: SubtypeAllocation,
nodes.Iir_Kind.Allocator_By_Expression: QualifiedExpressionAllocation,
}
[docs]
@export
def GetExpressionFromNode(node: Iir) -> ExpressionUnion:
"""
Translates an expression IIR node to an :class:`~pyVHDLModel.Expression.BaseExpression`.
:param node: The IIR node representing an expression.
:return: The translated expression.
"""
kind = GetIirKindOfNode(node)
try:
cls = __EXPRESSION_TRANSLATION[kind]
except KeyError:
position = Position.parse(node)
raise DOMException(f"Unknown expression kind '{kind.name}' in expression '{node}' at {position}.")
return cls.parse(node)
def GetOptionalExpressionFromNode(node: Iir) -> Nullable[ExpressionUnion]:
"""
Like :func:`GetExpressionFromNode`, but for fields that may legitimately be absent (e.g. an
optional condition on the final branch of a conditional assignment, or on an unconditional
``exit``/``next`` statement) - returns ``None`` instead of translating when ``node`` is
``Null_Iir``, rather than requiring every call site to repeat that check.
:param node: The IIR node representing an expression, or ``Null_Iir`` if absent.
:return: The translated expression, or ``None``.
"""
return None if node == nodes.Null_Iir else GetExpressionFromNode(node)
[docs]
@export
def GetModeViewElementsFromChainedNodes(nodeChain: Iir) -> Generator["ModeViewElement", None, None]:
"""
Translates a chain of mode view elements (IIR nodes) to a sequence of
:class:`pyVHDLModel.Interface.ModeViewElement`.
:param nodeChain: The IIR node representing the first mode view element in the chain.
:return: A generator returning mode view elements.
.. note::
Unlike declarations/interface items (where the *last* node in a ``Has_Identifier_List`` group owns
the shared subtype/value and earlier ones are Null), mode view elements are the other way around:
the *first* node in the group (``Has_Identifier_List == True``) owns the real ``Mode``/
``Mode_View_Name`` - subsequent nodes only contribute their identifier, ending with the node where
``Has_Identifier_List`` becomes ``False``. Verified against real GHDL analysis for
``x, y : out;``: ``x`` has ``Has_Identifier_List=True``, ``Mode=out``; ``y`` has
``Has_Identifier_List=False``, ``Mode=<unset>``.
"""
from pyGHDL.dom.InterfaceItem import SimpleModeViewElement, CompositeModeViewElement
furtherIdentifiers = []
element = nodeChain
while element != nodes.Null_Iir:
kind = GetIirKindOfNode(element)
if kind == nodes.Iir_Kind.Simple_Mode_View_Element:
parseMethod = SimpleModeViewElement.parse
elif kind in (nodes.Iir_Kind.Array_Mode_View_Element, nodes.Iir_Kind.Record_Mode_View_Element):
parseMethod = CompositeModeViewElement.parse
else:
position = Position.parse(element)
raise DOMException(f"Unknown mode view element kind '{kind.name}' at {position}.")
elementToParse = element
if nodes.Get_Has_Identifier_List(element):
nextNode = nodes.Get_Chain(element)
for nextElement in utils.chain_iter(nextNode):
furtherIdentifiers.append(GetNameOfNode(nextElement))
if not nodes.Get_Has_Identifier_List(nextElement):
element = nodes.Get_Chain(nextElement)
break
else:
element = nodes.Null_Iir
else:
element = nodes.Get_Chain(element)
yield parseMethod(elementToParse, furtherIdentifiers)
furtherIdentifiers.clear()
[docs]
@export
def GetGenericsFromChainedNodes(nodeChain: Iir) -> Generator[GenericInterfaceItemMixin, None, None]:
"""
Translates a chain of generics (IIR nodes) to a sequence of :class:`pyVHDLModel.Interface.GenericInterfaceItem`.
:param nodeChain: The IIR node representing the first generic in the chain.
:return: A generator returning generic interface items.
"""
from pyGHDL.dom.InterfaceItem import (
GenericTypeInterfaceItem,
GenericPackageInterfaceItem,
GenericProcedureInterfaceItem,
GenericFunctionInterfaceItem,
)
furtherIdentifiers = []
generic = nodeChain
while generic != nodes.Null_Iir:
kind = GetIirKindOfNode(generic)
if kind == nodes.Iir_Kind.Interface_Constant_Declaration:
from pyGHDL.dom.InterfaceItem import GenericConstantInterfaceItem
parseNode = generic
# Lookahead for generics with multiple identifiers at once
if nodes.Get_Has_Identifier_List(generic):
nextNode = nodes.Get_Chain(generic)
for nextGeneric in utils.chain_iter(nextNode):
# Consecutive identifiers are found, if the subtype indication is Null
if nodes.Get_Subtype_Indication(nextGeneric) == nodes.Null_Iir:
furtherIdentifiers.append(GetNameOfNode(nextGeneric))
else:
generic = nextGeneric
break
# The last consecutive identifiers has no Identifier_List flag
if not nodes.Get_Has_Identifier_List(nextGeneric):
generic = nodes.Get_Chain(nextGeneric)
break
else:
generic = nodes.Null_Iir
else:
generic = nodes.Get_Chain(generic)
yield GenericConstantInterfaceItem.parse(parseNode, furtherIdentifiers)
furtherIdentifiers.clear()
continue
else:
if kind == nodes.Iir_Kind.Interface_Type_Declaration:
yield GenericTypeInterfaceItem.parse(generic)
elif kind == nodes.Iir_Kind.Interface_Package_Declaration:
yield GenericPackageInterfaceItem.parse(generic)
elif kind == nodes.Iir_Kind.Interface_Procedure_Declaration:
yield GenericProcedureInterfaceItem.parse(generic)
elif kind == nodes.Iir_Kind.Interface_Function_Declaration:
yield GenericFunctionInterfaceItem.parse(generic)
else:
position = Position.parse(generic)
raise DOMException(f"Unknown generic kind '{kind.name}' in generic '{generic}' at {position}.")
generic = nodes.Get_Chain(generic)
[docs]
@export
def GetPortsFromChainedNodes(nodeChain: Iir) -> Generator[PortInterfaceItemMixin, None, None]:
"""
Translates a chain of ports (IIR nodes) to a sequence of :class:`pyVHDLModel.Interface.PortInterfaceItem`.
:param nodeChain: The IIR node representing the first port in the chain.
:return: A generator returning port interface items.
"""
furtherIdentifiers = []
port = nodeChain
while port != nodes.Null_Iir:
kind = GetIirKindOfNode(port)
if kind == nodes.Iir_Kind.Interface_Signal_Declaration:
from pyGHDL.dom.InterfaceItem import PortSimpleSignalInterfaceItem
parseMethod = PortSimpleSignalInterfaceItem.parse
parseNode = port
elif kind == nodes.Iir_Kind.Interface_View_Declaration:
from pyGHDL.dom.InterfaceItem import PortViewSignalInterfaceItem
parseMethod = PortViewSignalInterfaceItem.parse
parseNode = port
else:
position = Position.parse(port)
raise DOMException(f"Unknown port kind '{kind.name}' in port '{port}' at {position}.")
# Lookahead for ports with multiple identifiers at once
if nodes.Get_Has_Identifier_List(port):
nextNode = nodes.Get_Chain(port)
for nextPort in utils.chain_iter(nextNode):
# Consecutive identifiers are found, if the subtype indication is Null
if nodes.Get_Subtype_Indication(nextPort) == nodes.Null_Iir:
furtherIdentifiers.append(GetNameOfNode(nextPort))
else:
port = nextPort
break
# The last consecutive identifiers has no Identifier_List flag
if not nodes.Get_Has_Identifier_List(nextPort):
port = nodes.Get_Chain(nextPort)
break
else:
port = nodes.Null_Iir
else:
port = nodes.Get_Chain(port)
yield parseMethod(parseNode, furtherIdentifiers)
furtherIdentifiers.clear()
[docs]
@export
def GetParameterFromChainedNodes(nodeChain: Iir) -> Generator[ParameterInterfaceItemMixin, None, None]:
"""
Translates a chain of parameters (IIR nodes) to a sequence of :class:`pyVHDLModel.Interface.ParameterInterfaceItem`.
:param nodeChain: The IIR node representing the first parameter in the chain.
:return: A generator returning parameter interface items.
"""
identifiers = []
parameter = nodeChain
while parameter != nodes.Null_Iir:
kind = GetIirKindOfNode(parameter)
if kind == nodes.Iir_Kind.Interface_Constant_Declaration:
from pyGHDL.dom.InterfaceItem import ParameterConstantInterfaceItem
parseMethod = ParameterConstantInterfaceItem.parse
parseNode = parameter
elif kind == nodes.Iir_Kind.Interface_Variable_Declaration:
from pyGHDL.dom.InterfaceItem import ParameterVariableInterfaceItem
parseMethod = ParameterVariableInterfaceItem.parse
parseNode = parameter
elif kind == nodes.Iir_Kind.Interface_Signal_Declaration:
from pyGHDL.dom.InterfaceItem import ParameterSimpleSignalInterfaceItem
parseMethod = ParameterSimpleSignalInterfaceItem.parse
parseNode = parameter
elif kind == nodes.Iir_Kind.Interface_View_Declaration:
from pyGHDL.dom.InterfaceItem import ParameterViewSignalInterfaceItem
parseMethod = ParameterViewSignalInterfaceItem.parse
parseNode = parameter
elif kind == nodes.Iir_Kind.Interface_File_Declaration:
from pyGHDL.dom.InterfaceItem import ParameterFileInterfaceItem
parseMethod = ParameterFileInterfaceItem.parse
parseNode = parameter
else:
position = Position.parse(parameter)
raise DOMException(f"Unknown parameter kind '{kind.name}' in parameter '{parameter}' at {position}.")
# Lookahead for parameters with multiple identifiers at once
if nodes.Get_Has_Identifier_List(parameter):
nextNode = nodes.Get_Chain(parameter)
for nextParameter in utils.chain_iter(nextNode):
# Consecutive identifiers are found, if the subtype indication is Null
if nodes.Get_Subtype_Indication(nextParameter) == nodes.Null_Iir:
identifiers.append(GetNameOfNode(nextParameter))
else:
parameter = nextParameter
break
# The last consecutive identifiers has no Identifier_List flag
if not nodes.Get_Has_Identifier_List(nextParameter):
parameter = nodes.Get_Chain(nextParameter)
break
else:
parameter = nodes.Null_Iir
else:
parameter = nodes.Get_Chain(parameter)
yield parseMethod(parseNode, identifiers)
def GetMapAspect(mapAspect: Iir, cls: Type, entity: str) -> Generator[AssociationItem, None, None]:
for item in utils.chain_iter(mapAspect):
kind = GetIirKindOfNode(item)
if kind is nodes.Iir_Kind.Association_Element_By_Expression:
formalNode = nodes.Get_Formal(item)
if formalNode is nodes.Null_Iir:
formal = None
else:
formal = GetName(formalNode)
actual = GetExpressionFromNode(nodes.Get_Actual(item))
yield cls(item, formal, actual)
elif kind is nodes.Iir_Kind.Association_Element_Open:
formalNode = nodes.Get_Formal(item)
if formalNode is nodes.Null_Iir:
formal = None
else:
formal = GetName(formalNode)
yield cls(item, formal, OpenName(item))
else:
pos = Position.parse(item)
raise DOMException(f"Unknown association kind '{kind.name}' in {entity} map at line {pos.Line}.")
def GetGenericMapAspect(genericMapAspect: Iir) -> Generator[GenericAssociationItem, None, None]:
return GetMapAspect(genericMapAspect, GenericAssociationItem, "generic")
def GetPortMapAspect(portMapAspect: Iir) -> Generator[PortAssociationItem, None, None]:
return GetMapAspect(portMapAspect, PortAssociationItem, "port")
def GetParameterMapAspect(parameterMapAspect: Iir) -> Generator[ParameterAssociationItem, None, None]:
return GetMapAspect(parameterMapAspect, ParameterAssociationItem, "parameter")
def GetDeclaredItemsFromChainedNodes(nodeChain: Iir, entity: str, name: str) -> Generator[ModelEntity, None, None]:
furtherIdentifiers = []
item = nodeChain
lastKind = None
while item != nodes.Null_Iir:
kind = GetIirKindOfNode(item)
if kind == nodes.Iir_Kind.Constant_Declaration:
from pyGHDL.dom.Object import Constant
objectParseMethod = Constant.parse
objectItem = item
elif kind == nodes.Iir_Kind.Variable_Declaration:
from pyGHDL.dom.Object import SharedVariable
if nodes.Get_Shared_Flag(item):
objectParseMethod = SharedVariable.parse
objectItem = item
else:
objectParseMethod = Variable.parse
objectItem = item
elif kind == nodes.Iir_Kind.Signal_Declaration:
from pyGHDL.dom.Object import Signal
objectParseMethod = Signal.parse
objectItem = item
elif kind == nodes.Iir_Kind.File_Declaration:
from pyGHDL.dom.Object import File
objectParseMethod = File.parse
objectItem = item
else:
if kind == nodes.Iir_Kind.Type_Declaration:
yield GetTypeFromNode(item)
elif kind == nodes.Iir_Kind.Anonymous_Type_Declaration:
yield GetAnonymousTypeFromNode(item)
elif kind == nodes.Iir_Kind.Subtype_Declaration:
yield GetSubtypeFromNode(item)
elif kind == nodes.Iir_Kind.Mode_View_Declaration:
from pyGHDL.dom.InterfaceItem import ModeViewDeclaration
yield ModeViewDeclaration.parse(item)
elif kind == nodes.Iir_Kind.Function_Declaration:
yield Function.parse(item)
lastKind = kind
item = nodes.Get_Chain(item)
continue
elif kind == nodes.Iir_Kind.Function_Instantiation_Declaration:
from pyGHDL.dom.Subprogram import FunctionInstantiation
yield FunctionInstantiation.parse(item)
elif kind == nodes.Iir_Kind.Procedure_Instantiation_Declaration:
from pyGHDL.dom.Subprogram import ProcedureInstantiation
yield ProcedureInstantiation.parse(item)
elif kind == nodes.Iir_Kind.Function_Body:
if lastKind is nodes.Iir_Kind.Function_Declaration:
pass
else:
position = Position.parse(item)
raise DOMException(
f"Found unexpected function body '{GetNameOfNode(item)}' in {entity} '{name}' at {position}."
)
elif kind == nodes.Iir_Kind.Procedure_Declaration:
yield Procedure.parse(item)
lastKind = kind
item = nodes.Get_Chain(item)
continue
elif kind == nodes.Iir_Kind.Procedure_Body:
if lastKind is nodes.Iir_Kind.Procedure_Declaration:
pass
else:
position = Position.parse(item)
raise DOMException(
f"Found unexpected procedure body '{GetNameOfNode(item)}' in {entity} '{name}' at {position}."
)
elif kind == nodes.Iir_Kind.Protected_Type_Body:
yield ProtectedTypeBody.parse(item)
elif kind == nodes.Iir_Kind.Object_Alias_Declaration:
from pyGHDL.dom.Misc import Alias
yield Alias.parse(item)
elif kind == nodes.Iir_Kind.Configuration_Specification:
from pyGHDL.dom.Configuration import ComponentConfiguration
yield ComponentConfiguration.parse(item)
elif kind == nodes.Iir_Kind.Component_Declaration:
from pyGHDL.dom.DesignUnit import Component
yield Component.parse(item)
elif kind == nodes.Iir_Kind.Attribute_Declaration:
from pyGHDL.dom.Attribute import Attribute
yield Attribute.parse(item)
elif kind == nodes.Iir_Kind.Attribute_Specification:
from pyGHDL.dom.Attribute import AttributeSpecification
yield AttributeSpecification.parse(item)
elif kind == nodes.Iir_Kind.Use_Clause:
from pyGHDL.dom.DesignUnit import UseClause
yield UseClause.parse(item)
elif kind == nodes.Iir_Kind.Package_Declaration:
from pyGHDL.dom.DesignUnit import Package
yield Package.parse(item, None) # TODO: Can it have a context?
elif kind == nodes.Iir_Kind.Package_Instantiation_Declaration:
from pyGHDL.dom.DesignUnit import PackageInstantiation
yield PackageInstantiation.parse(item)
elif kind == nodes.Iir_Kind.Psl_Default_Clock:
yield DefaultClock.parse(item)
elif kind == nodes.Iir_Kind.Group_Declaration:
WarningCollector.Raise(NotImplementedError(f"Group declaration in {name}"))
elif kind == nodes.Iir_Kind.Group_Template_Declaration:
WarningCollector.Raise(NotImplementedError(f"Group template declaration in {name}"))
elif kind == nodes.Iir_Kind.Disconnection_Specification:
WarningCollector.Raise(NotImplementedError(f"Disconnect specification in {name}"))
elif kind == nodes.Iir_Kind.Nature_Declaration:
WarningCollector.Raise(NotImplementedError(f"Nature declaration in {name}"))
elif kind == nodes.Iir_Kind.Free_Quantity_Declaration:
WarningCollector.Raise(NotImplementedError(f"Free quantity declaration in {name}"))
elif kind == nodes.Iir_Kind.Across_Quantity_Declaration:
WarningCollector.Raise(NotImplementedError(f"Across quantity declaration in {name}"))
elif kind == nodes.Iir_Kind.Through_Quantity_Declaration:
WarningCollector.Raise(NotImplementedError(f"Through quantity declaration in {name}"))
elif kind == nodes.Iir_Kind.Terminal_Declaration:
WarningCollector.Raise(NotImplementedError(f"Terminal declaration in {name}"))
else:
position = Position.parse(item)
raise DOMException(f"Unknown declared item kind '{kind.name}' in {entity} '{name}' at {position}.")
lastKind = None
item = nodes.Get_Chain(item)
continue
# Lookahead for objects with multiple identifiers at once
if nodes.Get_Has_Identifier_List(item):
nextNode = nodes.Get_Chain(item)
for nextItem in utils.chain_iter(nextNode):
# Consecutive identifiers are found, if the subtype indication is Null
if nodes.Get_Subtype_Indication(nextItem) == nodes.Null_Iir:
furtherIdentifiers.append(GetNameOfNode(nextItem))
else:
item = nextItem
break
# The last consecutive identifiers has no Identifier_List flag
if not nodes.Get_Has_Identifier_List(nextItem):
item = nodes.Get_Chain(nextItem)
break
else:
item = nodes.Null_Iir
else:
item = nodes.Get_Chain(item)
yield objectParseMethod(objectItem, furtherIdentifiers)
furtherIdentifiers.clear()
def GetConcurrentStatementsFromChainedNodes(
nodeChain: Iir, entity: str, name: str
) -> Generator[ConcurrentStatement, None, None]:
for statement in utils.chain_iter(nodeChain):
label = GetLabelOfNode(statement)
position = Position.parse(statement)
kind = GetIirKindOfNode(statement)
if kind == nodes.Iir_Kind.Sensitized_Process_Statement:
yield ProcessStatement.parse(statement, label, True)
elif kind == nodes.Iir_Kind.Process_Statement:
yield ProcessStatement.parse(statement, label, False)
elif kind == nodes.Iir_Kind.Concurrent_Simple_Signal_Assignment:
yield ConcurrentSimpleSignalAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Concurrent_Conditional_Signal_Assignment:
from pyGHDL.dom.Concurrent import ConcurrentConditionalSignalAssignment
yield ConcurrentConditionalSignalAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Concurrent_Selected_Signal_Assignment:
from pyGHDL.dom.Concurrent import ConcurrentSelectedSignalAssignment
yield ConcurrentSelectedSignalAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Concurrent_Procedure_Call_Statement:
yield ConcurrentProcedureCall.parse(statement, label)
elif kind == nodes.Iir_Kind.Component_Instantiation_Statement:
instantiatedUnit = nodes.Get_Instantiated_Unit(statement)
instantiatedUnitKind = GetIirKindOfNode(instantiatedUnit)
if instantiatedUnitKind == nodes.Iir_Kind.Entity_Aspect_Entity:
yield EntityInstantiation.parse(statement, instantiatedUnit, label)
elif instantiatedUnitKind == nodes.Iir_Kind.Entity_Aspect_Configuration:
yield ConfigurationInstantiation.parse(statement, instantiatedUnit, label)
elif (
instantiatedUnitKind == nodes.Iir_Kind.Simple_Name
or instantiatedUnitKind == nodes.Iir_Kind.Selected_Name
):
yield ComponentInstantiation.parse(statement, instantiatedUnit, label)
else:
raise DOMException(
f"Unknown instantiation kind '{instantiatedUnitKind.name}' in instantiation of label {label} at {position}."
)
elif kind == nodes.Iir_Kind.Block_Statement:
yield ConcurrentBlockStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.If_Generate_Statement:
yield IfGenerateStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Case_Generate_Statement:
yield CaseGenerateStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.For_Generate_Statement:
yield ForGenerateStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Psl_Assert_Directive:
yield ConcurrentAssertStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Simple_Simultaneous_Statement:
WarningCollector.Raise(
NotImplementedError(f"Simple simultaneous statement (label: '{label}') at line {position.Line}")
)
else:
raise DOMException(
f"Unknown concurrent statement of kind '{kind.name}' in {entity} '{name}' at {position}."
)
def GetSequentialStatementsFromChainedNodes(
nodeChain: Iir, entity: str, name: str
) -> Generator[SequentialStatement, None, None]:
for statement in utils.chain_iter(nodeChain):
label = GetLabelOfNode(statement)
position = Position.parse(statement)
kind = GetIirKindOfNode(statement)
if kind == nodes.Iir_Kind.If_Statement:
yield IfStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Case_Statement:
yield CaseStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.For_Loop_Statement:
yield ForLoopStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.While_Loop_Statement:
yield WhileLoopStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Simple_Signal_Assignment_Statement:
yield SequentialSimpleSignalAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Variable_Assignment_Statement:
from pyGHDL.dom.Sequential import SequentialVariableAssignment
yield SequentialVariableAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Conditional_Variable_Assignment_Statement:
from pyGHDL.dom.Sequential import SequentialConditionalVariableAssignment
yield SequentialConditionalVariableAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Conditional_Signal_Assignment_Statement:
from pyGHDL.dom.Sequential import SequentialConditionalSignalAssignment
yield SequentialConditionalSignalAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Selected_Variable_Assignment_Statement:
from pyGHDL.dom.Sequential import SequentialSelectedVariableAssignment
yield SequentialSelectedVariableAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Selected_Waveform_Assignment_Statement:
from pyGHDL.dom.Sequential import SequentialSelectedSignalAssignment
yield SequentialSelectedSignalAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Signal_Force_Assignment_Statement:
from pyGHDL.dom.Sequential import SignalForceAssignment
yield SignalForceAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Signal_Release_Assignment_Statement:
from pyGHDL.dom.Sequential import SignalReleaseAssignment
yield SignalReleaseAssignment.parse(statement, label)
elif kind == nodes.Iir_Kind.Wait_Statement:
yield WaitStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Procedure_Call_Statement:
yield SequentialProcedureCall.parse(statement, label)
elif kind == nodes.Iir_Kind.Report_Statement:
yield SequentialReportStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Assertion_Statement:
yield SequentialAssertStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Null_Statement:
yield NullStatement(statement, label)
elif kind == nodes.Iir_Kind.Next_Statement:
yield NextStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Exit_Statement:
yield ExitStatement.parse(statement, label)
elif kind == nodes.Iir_Kind.Return_Statement:
yield ReturnStatement.parse(statement, label)
else:
raise DOMException(
f"Unknown sequential statement of kind '{kind.name}' in {entity} '{name}' at {position}."
)