Source code for pyGHDL.dom.Expression

# =============================================================================
#               ____ _   _ ____  _          _
#  _ __  _   _ / ___| | | |  _ \| |      __| | ___  _ __ ___
# | '_ \| | | | |  _| |_| | | | | |     / _` |/ _ \| '_ ` _ \
# | |_) | |_| | |_| |  _  | |_| | |___ | (_| | (_) | | | | | |
# | .__/ \__, |\____|_| |_|____/|_____(_)__,_|\___/|_| |_| |_|
# |_|    |___/
# =============================================================================
# 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, 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): 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, GetName, ) 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 = GetName(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 = GetName(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)