# =============================================================================
# ____ _ _ ____ _ _
# _ __ _ _ / ___| | | | _ \| | __| | ___ _ __ ___
# | '_ \| | | | | _| |_| | | | | | / _` |/ _ \| '_ ` _ \
# | |_) | |_| | |_| | _ | |_| | |___ | (_| | (_) | | | | | |
# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_|
# |_| |___/
# =============================================================================
# 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 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,
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 pyGHDL.dom.Symbol import SimpleSubtypeSymbol
from pyGHDL.dom.Aggregates import (
OthersAggregateElement,
SimpleAggregateElement,
RangedAggregateElement,
IndexedAggregateElement,
NamedAggregateElement,
)
class _ParseUnaryExpressionMixin:
@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:
@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):
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]@export
class IdentityExpression(VHDLModel_IdentityExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs] def __init__(self, node: Iir, operand: ExpressionUnion):
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]@export
class NegationExpression(VHDLModel_NegationExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs] def __init__(self, node: Iir, operand: ExpressionUnion):
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]@export
class AbsoluteExpression(VHDLModel_AbsoluteExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs] def __init__(self, node: Iir, operand: ExpressionUnion):
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]@export
class ParenthesisExpression(VHDLModel_ParenthesisExpression, DOMMixin, _ParseUnaryExpressionMixin):
[docs] def __init__(self, node: Iir, operand: ExpressionUnion):
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):
[docs] def __init__(self, node: Iir, operand: ExpressionUnion):
super().__init__(operand)
DOMMixin.__init__(self, node)
[docs]@export
class FunctionCall(VHDLModel_FunctionCall, DOMMixin):
[docs] def __init__(self, node: Iir, operand: ExpressionUnion):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
super().__init__(left, right)
DOMMixin.__init__(self, node)
[docs]@export
class EqualExpression(VHDLModel_EqualExpression, DOMMixin, _ParseBinaryExpressionMixin):
[docs] def __init__(self, node: Iir, left: ExpressionUnion, right: ExpressionUnion):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
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):
super().__init__(subtype, operand)
DOMMixin.__init__(self, node)
@classmethod
def parse(cls, node: Iir) -> "QualifiedExpression":
from pyGHDL.dom._Translate import GetExpressionFromNode, GetNameOfNode
typeMarkName = GetNameOfNode(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):
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):
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]):
super().__init__(elements)
DOMMixin.__init__(self, node)
@classmethod
def parse(cls, node: Iir) -> "Aggregate":
from pyGHDL.dom._Translate import (
GetExpressionFromNode,
GetRangeFromNode,
GetNameFromNode,
)
choices = []
choicesChain = nodes.Get_Association_Choices_Chain(node)
for item in utils.chain_iter(choicesChain):
kind = GetIirKindOfNode(item)
value = GetExpressionFromNode(nodes.Get_Associated_Expr(item))
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:
choiceRange = nodes.Get_Choice_Range(item)
rangeKind = GetIirKindOfNode(choiceRange)
if rangeKind == nodes.Iir_Kind.Range_Expression:
rng = GetRangeFromNode(choiceRange)
elif rangeKind in (
nodes.Iir_Kind.Attribute_Name,
nodes.Iir_Kind.Parenthesis_Name,
):
rng = GetNameFromNode(choiceRange)
else:
pos = Position.parse(item)
raise DOMException(
f"Unknown discrete range kind '{rangeKind.name}' in for...generate statement at line {pos.Line}."
)
choices.append(RangedAggregateElement(item, rng, value))
elif kind == nodes.Iir_Kind.Choice_By_Name:
name = GetNameFromNode(nodes.Get_Choice_Name(item))
symbol = Symbol(item, name)
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)