# =============================================================================
# ____ _ _ ____ _ _
# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___
# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \
# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | |
# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_|
# |_| |___/
# =============================================================================
# Authors:
# Patrick Lehmann
#
# Package module: DOM: Expressions.
#
# 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
# ============================================================================
from typing import List, Union
from pyTooling.Decorators import export
from pyTooling.MetaClasses import ExtendedType
from pyVHDLModel.Base import ExpressionUnion
from pyVHDLModel.Symbol import Symbol
from pyVHDLModel.Expression import (
UnaryExpression as VHDLModel_UnaryExpression,
NegationExpression as VHDLModel_NegationExpression,
IdentityExpression as VHDLModel_IdentityExpression,
InverseExpression as VHDLModel_InverseExpression,
AbsoluteExpression as VHDLModel_AbsoluteExpression,
TypeConversion as VHDLModel_TypeConversion,
SubExpression as VHDLModel_ParenthesisExpression,
BinaryExpression as VHDLModel_BinaryExpression,
RangeExpression as VHDLModel_RangeExpression,
AscendingRangeExpression as VHDLModel_AscendingRangeExpression,
DescendingRangeExpression as VHDLModel_DescendingRangeExpression,
AdditionExpression as VHDLModel_AdditionExpression,
SubtractionExpression as VHDLModel_SubtractionExpression,
ConcatenationExpression as VHDLModel_ConcatenationExpression,
MultiplyExpression as VHDLModel_MultiplyExpression,
DivisionExpression as VHDLModel_DivisionExpression,
RemainderExpression as VHDLModel_RemainderExpression,
ModuloExpression as VHDLModel_ModuloExpression,
ExponentiationExpression as VHDLModel_ExponentiationExpression,
AndExpression as VHDLModel_AndExpression,
NandExpression as VHDLModel_NandExpression,
OrExpression as VHDLModel_OrExpression,
NorExpression as VHDLModel_NorExpression,
XorExpression as VHDLModel_XorExpression,
XnorExpression as VHDLModel_XnorExpression,
UnaryAndExpression as VHDLModel_UnaryAndExpression,
UnaryNandExpression as VHDLModel_UnaryNandExpression,
UnaryOrExpression as VHDLModel_UnaryOrExpression,
UnaryNorExpression as VHDLModel_UnaryNorExpression,
UnaryXorExpression as VHDLModel_UnaryXorExpression,
UnaryXnorExpression as VHDLModel_UnaryXnorExpression,
EqualExpression as VHDLModel_EqualExpression,
UnequalExpression as VHDLModel_UnequalExpression,
GreaterThanExpression as VHDLModel_GreaterThanExpression,
GreaterEqualExpression as VHDLModel_GreaterEqualExpression,
LessThanExpression as VHDLModel_LessThanExpression,
LessEqualExpression as VHDLModel_LessEqualExpression,
MatchingEqualExpression as VHDLModel_MatchingEqualExpression,
MatchingUnequalExpression as VHDLModel_MatchingUnequalExpression,
MatchingGreaterThanExpression as VHDLModel_MatchingGreaterThanExpression,
MatchingGreaterEqualExpression as VHDLModel_MatchingGreaterEqualExpression,
MatchingLessThanExpression as VHDLModel_MatchingLessThanExpression,
MatchingLessEqualExpression as VHDLModel_MatchingLessEqualExpression,
ShiftRightLogicExpression as VHDLModel_ShiftRightLogicExpression,
ShiftLeftLogicExpression as VHDLModel_ShiftLeftLogicExpression,
ShiftRightArithmeticExpression as VHDLModel_ShiftRightArithmeticExpression,
ShiftLeftArithmeticExpression as VHDLModel_ShiftLeftArithmeticExpression,
RotateRightExpression as VHDLModel_RotateRightExpression,
RotateLeftExpression as VHDLModel_RotateLeftExpression,
QualifiedExpression as VHDLModel_QualifiedExpression,
FunctionCall as VHDLModel_FunctionCall,
SubtypeAllocation as VHDLModel_SubtypeAllocation,
QualifiedExpressionAllocation as VHDLModel_QualifiedExpressionAllocation,
AggregateElement,
Aggregate as VHDLModel_Aggregate,
)
from pyGHDL.libghdl import utils
from pyGHDL.libghdl._types import Iir
from pyGHDL.libghdl.vhdl import nodes
from pyGHDL.dom import DOMMixin, DOMException, Position
from pyGHDL.dom._Utils import GetIirKindOfNode
from pyVHDLModel.Symbol import SubtypeSymbol
from pyGHDL.dom.Symbol import SimpleSubtypeSymbol, RecordElementSymbol
from pyGHDL.dom.Aggregates import (
OthersAggregateElement,
SimpleAggregateElement,
RangedAggregateElement,
IndexedAggregateElement,
NamedAggregateElement,
)
class _ParseUnaryExpressionMixin(metaclass=ExtendedType, mixin=True):
@classmethod
def parse(cls, node: Iir) -> VHDLModel_UnaryExpression:
from pyGHDL.dom._Translate import GetExpressionFromNode
operand = GetExpressionFromNode(nodes.Get_Operand(node))
return cls(node, operand)
class _ParseBinaryExpressionMixin(metaclass=ExtendedType, mixin=True):
@classmethod
def parse(cls, node: Iir) -> VHDLModel_BinaryExpression:
from pyGHDL.dom._Translate import GetExpressionFromNode
left = GetExpressionFromNode(nodes.Get_Left(node))
right = GetExpressionFromNode(nodes.Get_Right(node))
return cls(node, left, right)
[docs]
@export
class InverseExpression(VHDLModel_InverseExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class IdentityExpression(VHDLModel_IdentityExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class NegationExpression(VHDLModel_NegationExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class AbsoluteExpression(VHDLModel_AbsoluteExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class ParenthesisExpression(VHDLModel_ParenthesisExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
@classmethod
def parse(cls, node: Iir) -> "ParenthesisExpression":
from pyGHDL.dom._Translate import GetExpressionFromNode
operand = GetExpressionFromNode(nodes.Get_Expression(node))
return cls(node, operand)
[docs]
@export
class TypeConversion(VHDLModel_TypeConversion, DOMMixin):
"""
Represents a *type conversion*, e.g. ``integer(x)``.
.. note::
Not reachable from this translator today. GHDL's parser cannot tell a type conversion from an
indexed name or a function call - ``integer(x)``, ``arr(x)`` and ``f(x)`` are all parsed as
``Parenthesis_Name`` - and only semantic analysis rewrites one into ``Type_Conversion``.
:mod:`pyGHDL.dom` parses without that pass, so a ``Type_Conversion`` node never arrives and
``Parenthesis_Name`` is translated to
:class:`~pyVHDLModel.Symbol.IndexedObjectOrFunctionCallSymbol`, which carries the ambiguity.
The constructor is kept correct so this class works if semantic analysis is ever run.
"""
[docs]
def __init__(self, node: Iir, targetSubtype: SubtypeSymbol, operand: ExpressionUnion) -> None:
super().__init__(targetSubtype, operand)
DOMMixin.__init__(self, node)
[docs]
@export
class FunctionCall(VHDLModel_FunctionCall, DOMMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__()
DOMMixin.__init__(self, node)
class RangeExpression(VHDLModel_RangeExpression, DOMMixin):
@classmethod
def parse(cls, node: Iir) -> Union["AscendingRangeExpression", "DescendingRangeExpression"]:
from pyGHDL.dom._Translate import GetExpressionFromNode
direction = nodes.Get_Direction(node)
leftBound = GetExpressionFromNode(nodes.Get_Left_Limit_Expr(node))
rightBound = GetExpressionFromNode(nodes.Get_Right_Limit_Expr(node))
if not direction: # ascending
return AscendingRangeExpression(node, leftBound, rightBound)
else:
return DescendingRangeExpression(node, leftBound, rightBound)
[docs]
@export
class AscendingRangeExpression(VHDLModel_AscendingRangeExpression, DOMMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class DescendingRangeExpression(VHDLModel_DescendingRangeExpression, DOMMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class AdditionExpression(VHDLModel_AdditionExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class SubtractionExpression(VHDLModel_SubtractionExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class ConcatenationExpression(VHDLModel_ConcatenationExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class MultiplyExpression(VHDLModel_MultiplyExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class DivisionExpression(VHDLModel_DivisionExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class RemainderExpression(VHDLModel_RemainderExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class ModuloExpression(VHDLModel_ModuloExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class ExponentiationExpression(VHDLModel_ExponentiationExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class AndExpression(VHDLModel_AndExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class NandExpression(VHDLModel_NandExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class OrExpression(VHDLModel_OrExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class NorExpression(VHDLModel_NorExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class XorExpression(VHDLModel_XorExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class XnorExpression(VHDLModel_XnorExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class UnaryAndExpression(VHDLModel_UnaryAndExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class UnaryNandExpression(VHDLModel_UnaryNandExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class UnaryOrExpression(VHDLModel_UnaryOrExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class UnaryNorExpression(VHDLModel_UnaryNorExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class UnaryXorExpression(VHDLModel_UnaryXorExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class UnaryXnorExpression(VHDLModel_UnaryXnorExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs]
def __init__(self, node: Iir, operand: ExpressionUnion) -> None:
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]
@export
class EqualExpression(VHDLModel_EqualExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class UnequalExpression(VHDLModel_UnequalExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class LessThanExpression(VHDLModel_LessThanExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class LessEqualExpression(VHDLModel_LessEqualExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class GreaterThanExpression(VHDLModel_GreaterThanExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class GreaterEqualExpression(VHDLModel_GreaterEqualExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class MatchingEqualExpression(VHDLModel_MatchingEqualExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class MatchingUnequalExpression(VHDLModel_MatchingUnequalExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class MatchingLessThanExpression(VHDLModel_MatchingLessThanExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class MatchingLessEqualExpression(VHDLModel_MatchingLessEqualExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class MatchingGreaterThanExpression(VHDLModel_MatchingGreaterThanExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class MatchingGreaterEqualExpression(VHDLModel_MatchingGreaterEqualExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class ShiftRightLogicExpression(VHDLModel_ShiftRightLogicExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class ShiftLeftLogicExpression(VHDLModel_ShiftLeftLogicExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class ShiftRightArithmeticExpression(VHDLModel_ShiftRightArithmeticExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class ShiftLeftArithmeticExpression(VHDLModel_ShiftLeftArithmeticExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class RotateRightExpression(VHDLModel_RotateRightExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class RotateLeftExpression(VHDLModel_RotateLeftExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs]
def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion) -> None:
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]
@export
class QualifiedExpression(VHDLModel_QualifiedExpression, DOMMixin):
[docs]
def __init__(self, node: Iir, subtype: Symbol, operand: ExpressionUnion) -> None:
super().__init__(subtype, operand)
DOMMixin.__init__(self, node)
@classmethod
def parse(cls, node: Iir) -> "QualifiedExpression":
from pyGHDL.dom._Translate import GetExpressionFromNode, GetName
typeMarkName = GetName(nodes.Get_Type_Mark(node))
subtype = SimpleSubtypeSymbol(node, typeMarkName)
operand = GetExpressionFromNode(nodes.Get_Expression(node))
return cls(node, subtype, operand)
[docs]
@export
class SubtypeAllocation(VHDLModel_SubtypeAllocation, DOMMixin):
[docs]
def __init__(self, node: Iir, subtype: Symbol) -> None:
super().__init__(subtype)
DOMMixin.__init__(self, node)
@classmethod
def parse(cls, node: Iir) -> "QualifiedExpressionAllocation":
from pyGHDL.dom._Translate import GetSubtypeIndicationFromNode
subtype = GetSubtypeIndicationFromNode(node, "allocation", "?")
return cls(node, subtype)
[docs]
@export
class QualifiedExpressionAllocation(VHDLModel_QualifiedExpressionAllocation, DOMMixin):
[docs]
def __init__(self, node: Iir, qualifiedExpression: QualifiedExpression) -> None:
super().__init__(qualifiedExpression)
DOMMixin.__init__(self, node)
@classmethod
def parse(cls, node: Iir) -> "QualifiedExpressionAllocation":
from pyGHDL.dom._Translate import GetExpressionFromNode
expression = GetExpressionFromNode(nodes.Get_Expression(node))
return cls(node, expression)
[docs]
@export
class Aggregate(VHDLModel_Aggregate, DOMMixin):
[docs]
def __init__(self, node: Iir, elements: List[AggregateElement]) -> None:
super().__init__(elements)
DOMMixin.__init__(self, node)
@classmethod
def parse(cls, node: Iir) -> "Aggregate":
from pyGHDL.dom._Translate import (
GetExpressionFromNode,
GetDiscreteRangeFromNode,
GetName,
)
choices = []
ownerNode = nodes.Null_Iir
choicesChain = nodes.Get_Association_Choices_Chain(node)
for item in utils.chain_iter(choicesChain):
kind = GetIirKindOfNode(item)
# A choice list (`b | c => '0'`) groups multiple choices onto one associated expression:
# the *first* choice in the group owns it (``Same_Alternative_Flag=False``), while the later
# ones have a null ``Associated_Expr``. Same grouping algorithm as case statement
# alternatives, see :func:`pyGHDL.dom.Concurrent.GetSelectedWaveformsFromChainedNodes`.
if not nodes.Get_Same_Alternative_Flag(item):
ownerNode = item
elif ownerNode is nodes.Null_Iir:
position = Position.parse(item)
raise DOMException(
f"Aggregate choice at line {position.Line} continues a choice list that never started."
)
# Translated per element rather than once per group: each AggregateElement takes ownership of
# its expression by setting ``Parent``, so sharing one object across elements would misparent it.
value = GetExpressionFromNode(nodes.Get_Associated_Expr(ownerNode))
if kind == nodes.Iir_Kind.Choice_By_None:
choices.append(SimpleAggregateElement(item, value))
elif kind == nodes.Iir_Kind.Choice_By_Expression:
index = GetExpressionFromNode(nodes.Get_Choice_Expression(item))
choices.append(IndexedAggregateElement(item, index, value))
elif kind == nodes.Iir_Kind.Choice_By_Range:
rng = GetDiscreteRangeFromNode(nodes.Get_Choice_Range(item), "aggregate choice")
choices.append(RangedAggregateElement(item, rng, value))
elif kind == nodes.Iir_Kind.Choice_By_Name:
# An aggregate choice name always denotes a record element, never an object.
choiceName = nodes.Get_Choice_Name(item)
symbol = RecordElementSymbol(choiceName, GetName(choiceName))
choices.append(NamedAggregateElement(item, symbol, value))
elif kind == nodes.Iir_Kind.Choice_By_Others:
choices.append(OthersAggregateElement(item, value))
else:
raise DOMException(f"Unknown choice kind '{kind.name}' in aggregate '{node}'.")
return cls(node, choices)