Source code for pyVHDLModel.Expression

# ==================================================================================================================== #
#             __     ___   _ ____  _     __  __           _      _                                                     #
#   _ __  _   \ \   / / | | |  _ \| |   |  \/  | ___   __| | ___| |                                                    #
#  | '_ \| | | \ \ / /| |_| | | | | |   | |\/| |/ _ \ / _` |/ _ \ |                                                    #
#  | |_) | |_| |\ V / |  _  | |_| | |___| |  | | (_) | (_| |  __/ |                                                    #
#  | .__/ \__, | \_/  |_| |_|____/|_____|_|  |_|\___/ \__,_|\___|_|                                                    #
#  |_|    |___/                                                                                                        #
# ==================================================================================================================== #
# Authors:                                                                                                             #
#   Patrick Lehmann                                                                                                    #
#                                                                                                                      #
# License:                                                                                                             #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany                                                            #
# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany                                                               #
#                                                                                                                      #
# Licensed under the Apache License, Version 2.0 (the "License");                                                      #
# you may not use this file except in compliance with the License.                                                     #
# You may obtain a copy of the License at                                                                              #
#                                                                                                                      #
#   http://www.apache.org/licenses/LICENSE-2.0                                                                         #
#                                                                                                                      #
# Unless required by applicable law or agreed to in writing, software                                                  #
# distributed under the License is distributed on an "AS IS" BASIS,                                                    #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                                             #
# See the License for the specific language governing permissions and                                                  #
# limitations under the License.                                                                                       #
#                                                                                                                      #
# SPDX-License-Identifier: Apache-2.0                                                                                  #
# ==================================================================================================================== #
#
"""
This module contains parts of an abstract document language model for VHDL.

All declarations for literals, aggregates, operators forming an expressions.
"""
from typing               import Tuple, List, Iterable, Union

from pyTooling.Decorators import export

from pyVHDLModel.Base     import ModelEntity, Direction, Range
from pyVHDLModel.Symbol   import Symbol


ExpressionUnion = Union[
	'BaseExpression',
	'QualifiedExpression',
	'FunctionCall',
	'TypeConversion',
	# ConstantOrSymbol,     TODO: ObjectSymbol
	'Literal',
]


[docs] @export class BaseExpression(ModelEntity): """A ``BaseExpression`` is a base-class for all expressions."""
[docs] @export class Literal(BaseExpression): """A ``Literal`` is a base-class for all literals."""
[docs] @export class NullLiteral(Literal):
[docs] def __str__(self) -> str: return "null"
[docs] @export class EnumerationLiteral(Literal): _value: str
[docs] def __init__(self, value: str): super().__init__() self._value = value
@property def Value(self) -> str: return self._value
[docs] def __str__(self) -> str: return self._value
[docs] @export class NumericLiteral(Literal): """A ``NumericLiteral`` is a base-class for all numeric literals."""
[docs] @export class IntegerLiteral(NumericLiteral): _value: int
[docs] def __init__(self, value: int): super().__init__() self._value = value
@property def Value(self) -> int: return self._value
[docs] def __str__(self) -> str: return str(self._value)
[docs] @export class FloatingPointLiteral(NumericLiteral): _value: float
[docs] def __init__(self, value: float): super().__init__() self._value = value
@property def Value(self) -> float: return self._value
[docs] def __str__(self) -> str: return str(self._value)
[docs] @export class PhysicalLiteral(NumericLiteral): _unitName: str
[docs] def __init__(self, unitName: str): super().__init__() self._unitName = unitName
@property def UnitName(self) -> str: return self._unitName
[docs] def __str__(self) -> str: return f"{self._value} {self._unitName}"
[docs] @export class PhysicalIntegerLiteral(PhysicalLiteral): _value: int
[docs] def __init__(self, value: int, unitName: str): super().__init__(unitName) self._value = value
@property def Value(self) -> int: return self._value
[docs] @export class PhysicalFloatingLiteral(PhysicalLiteral): _value: float
[docs] def __init__(self, value: float, unitName: str): super().__init__(unitName) self._value = value
@property def Value(self) -> float: return self._value
[docs] @export class CharacterLiteral(Literal): _value: str
[docs] def __init__(self, value: str): super().__init__() self._value = value
@property def Value(self) -> str: return self._value
[docs] def __str__(self) -> str: return str(self._value)
[docs] @export class StringLiteral(Literal): _value: str
[docs] def __init__(self, value: str): super().__init__() self._value = value
@property def Value(self) -> str: return self._value
[docs] def __str__(self) -> str: return "\"" + self._value + "\""
[docs] @export class BitStringLiteral(Literal): _value: str
[docs] def __init__(self, value: str): super().__init__() self._value = value
@property def Value(self) -> str: return self._value
[docs] def __str__(self) -> str: return "\"" + self._value + "\""
[docs] @export class ParenthesisExpression: #(Protocol): __slots__ = () # FIXME: use ExtendedType? @property def Operand(self) -> ExpressionUnion: return None
[docs] @export class UnaryExpression(BaseExpression): """A ``UnaryExpression`` is a base-class for all unary expressions.""" _FORMAT: Tuple[str, str] _operand: ExpressionUnion
[docs] def __init__(self, operand: ExpressionUnion): super().__init__() self._operand = operand
# operand._parent = self # FIXME: operand is provided as None @property def Operand(self): return self._operand
[docs] def __str__(self) -> str: return f"{self._FORMAT[0]}{self._operand!s}{self._FORMAT[1]}"
[docs] @export class NegationExpression(UnaryExpression): _FORMAT = ("-", "")
[docs] @export class IdentityExpression(UnaryExpression): _FORMAT = ("+", "")
[docs] @export class InverseExpression(UnaryExpression): _FORMAT = ("not ", "")
[docs] @export class AbsoluteExpression(UnaryExpression): _FORMAT = ("abs ", "")
[docs] @export class TypeConversion(UnaryExpression): pass
[docs] @export class SubExpression(UnaryExpression, ParenthesisExpression): _FORMAT = ("(", ")")
[docs] @export class BinaryExpression(BaseExpression): """A ``BinaryExpression`` is a base-class for all binary expressions.""" _FORMAT: Tuple[str, str, str] _leftOperand: ExpressionUnion _rightOperand: ExpressionUnion
[docs] def __init__(self, leftOperand: ExpressionUnion, rightOperand: ExpressionUnion): super().__init__() self._leftOperand = leftOperand leftOperand._parent = self self._rightOperand = rightOperand rightOperand._parent = self
@property def LeftOperand(self): return self._leftOperand @property def RightOperand(self): return self._rightOperand
[docs] def __str__(self) -> str: return "{leftOperator}{leftOperand!s}{middleOperator}{rightOperand!s}{rightOperator}".format( leftOperator=self._FORMAT[0], leftOperand=self._leftOperand, middleOperator=self._FORMAT[1], rightOperand=self._rightOperand, rightOperator=self._FORMAT[2], )
[docs] @export class RangeExpression(BinaryExpression): _direction: Direction @property def Direction(self) -> Direction: return self._direction
[docs] @export class AscendingRangeExpression(RangeExpression): _direction = Direction.To _FORMAT = ("", " to ", "")
[docs] @export class DescendingRangeExpression(RangeExpression): _direction = Direction.DownTo _FORMAT = ("", " downto ", "")
[docs] @export class AddingExpression(BinaryExpression): """A ``AddingExpression`` is a base-class for all adding expressions."""
[docs] @export class AdditionExpression(AddingExpression): _FORMAT = ("", " + ", "")
[docs] @export class SubtractionExpression(AddingExpression): _FORMAT = ("", " - ", "")
[docs] @export class ConcatenationExpression(AddingExpression): _FORMAT = ("", " & ", "")
[docs] @export class MultiplyingExpression(BinaryExpression): """A ``MultiplyingExpression`` is a base-class for all multiplying expressions."""
[docs] @export class MultiplyExpression(MultiplyingExpression): _FORMAT = ("", " * ", "")
[docs] @export class DivisionExpression(MultiplyingExpression): _FORMAT = ("", " / ", "")
[docs] @export class RemainderExpression(MultiplyingExpression): _FORMAT = ("", " rem ", "")
[docs] @export class ModuloExpression(MultiplyingExpression): _FORMAT = ("", " mod ", "")
[docs] @export class ExponentiationExpression(MultiplyingExpression): _FORMAT = ("", "**", "")
[docs] @export class LogicalExpression(BinaryExpression): """A ``LogicalExpression`` is a base-class for all logical expressions."""
[docs] @export class AndExpression(LogicalExpression): _FORMAT = ("", " and ", "")
[docs] @export class NandExpression(LogicalExpression): _FORMAT = ("", " nand ", "")
[docs] @export class OrExpression(LogicalExpression): _FORMAT = ("", " or ", "")
[docs] @export class NorExpression(LogicalExpression): _FORMAT = ("", " nor ", "")
[docs] @export class XorExpression(LogicalExpression): _FORMAT = ("", " xor ", "")
[docs] @export class XnorExpression(LogicalExpression): _FORMAT = ("", " xnor ", "")
[docs] @export class RelationalExpression(BinaryExpression): """A ``RelationalExpression`` is a base-class for all shifting expressions."""
[docs] @export class EqualExpression(RelationalExpression): _FORMAT = ("", " = ", "")
[docs] @export class UnequalExpression(RelationalExpression): _FORMAT = ("", " /= ", "")
[docs] @export class GreaterThanExpression(RelationalExpression): _FORMAT = ("", " > ", "")
[docs] @export class GreaterEqualExpression(RelationalExpression): _FORMAT = ("", " >= ", "")
[docs] @export class LessThanExpression(RelationalExpression): _FORMAT = ("", " < ", "")
[docs] @export class LessEqualExpression(RelationalExpression): _FORMAT = ("", " <= ", "")
[docs] @export class MatchingRelationalExpression(RelationalExpression): pass
[docs] @export class MatchingEqualExpression(MatchingRelationalExpression): _FORMAT = ("", " ?= ", "")
[docs] @export class MatchingUnequalExpression(MatchingRelationalExpression): _FORMAT = ("", " ?/= ", "")
[docs] @export class MatchingGreaterThanExpression(MatchingRelationalExpression): _FORMAT = ("", " ?> ", "")
[docs] @export class MatchingGreaterEqualExpression(MatchingRelationalExpression): _FORMAT = ("", " ?>= ", "")
[docs] @export class MatchingLessThanExpression(MatchingRelationalExpression): _FORMAT = ("", " ?< ", "")
[docs] @export class MatchingLessEqualExpression(MatchingRelationalExpression): _FORMAT = ("", " ?<= ", "")
[docs] @export class ShiftExpression(BinaryExpression): """A ``ShiftExpression`` is a base-class for all shifting expressions."""
[docs] @export class ShiftLogicExpression(ShiftExpression): pass
[docs] @export class ShiftArithmeticExpression(ShiftExpression): pass
[docs] @export class RotateExpression(ShiftExpression): pass
[docs] @export class ShiftRightLogicExpression(ShiftLogicExpression): _FORMAT = ("", " srl ", "")
[docs] @export class ShiftLeftLogicExpression(ShiftLogicExpression): _FORMAT = ("", " sll ", "")
[docs] @export class ShiftRightArithmeticExpression(ShiftArithmeticExpression): _FORMAT = ("", " sra ", "")
[docs] @export class ShiftLeftArithmeticExpression(ShiftArithmeticExpression): _FORMAT = ("", " sla ", "")
[docs] @export class RotateRightExpression(RotateExpression): _FORMAT = ("", " ror ", "")
[docs] @export class RotateLeftExpression(RotateExpression): _FORMAT = ("", " rol ", "")
[docs] @export class QualifiedExpression(BaseExpression, ParenthesisExpression): _operand: ExpressionUnion _subtype: Symbol
[docs] def __init__(self, subtype: Symbol, operand: ExpressionUnion): super().__init__() self._operand = operand operand._parent = self self._subtype = subtype subtype._parent = self
@property def Operand(self): return self._operand @property def Subtyped(self): return self._subtype
[docs] def __str__(self) -> str: return f"{self._subtype}'({self._operand!s})"
[docs] @export class TernaryExpression(BaseExpression): """A ``TernaryExpression`` is a base-class for all ternary expressions.""" _FORMAT: Tuple[str, str, str, str] _firstOperand: ExpressionUnion _secondOperand: ExpressionUnion _thirdOperand: ExpressionUnion
[docs] def __init__(self): super().__init__()
# FIXME: parameters and initializers are missing !! @property def FirstOperand(self): return self._firstOperand @property def SecondOperand(self): return self._secondOperand @property def ThirdOperand(self): return self._thirdOperand
[docs] def __str__(self) -> str: return "{beforeFirstOperator}{firstOperand!s}{beforeSecondOperator}{secondOperand!s}{beforeThirdOperator}{thirdOperand!s}{lastOperator}".format( beforeFirstOperator=self._FORMAT[0], firstOperand=self._firstOperand, beforeSecondOperator=self._FORMAT[1], secondOperand=self._secondOperand, beforeThirdOperator=self._FORMAT[2], thirdOperand=self._thirdOperand, lastOperator=self._FORMAT[4], )
[docs] @export class WhenElseExpression(TernaryExpression): _FORMAT = ("", " when ", " else ", "")
[docs] @export class FunctionCall(BaseExpression): pass
[docs] @export class Allocation(BaseExpression): pass
[docs] @export class SubtypeAllocation(Allocation): _subtype: Symbol
[docs] def __init__(self, subtype: Symbol): super().__init__() self._subtype = subtype subtype._parent = self
@property def Subtype(self) -> Symbol: return self._subtype
[docs] def __str__(self) -> str: return f"new {self._subtype!s}"
[docs] @export class QualifiedExpressionAllocation(Allocation): _qualifiedExpression: QualifiedExpression
[docs] def __init__(self, qualifiedExpression: QualifiedExpression): super().__init__() self._qualifiedExpression = qualifiedExpression qualifiedExpression._parent = self
@property def QualifiedExpression(self) -> QualifiedExpression: return self._qualifiedExpression
[docs] def __str__(self) -> str: return f"new {self._qualifiedExpression!s}"
[docs] @export class AggregateElement(ModelEntity): """A ``AggregateElement`` is a base-class for all aggregate elements.""" _expression: ExpressionUnion
[docs] def __init__(self, expression: ExpressionUnion): super().__init__() self._expression = expression expression._parent = self
@property def Expression(self): return self._expression
[docs] @export class SimpleAggregateElement(AggregateElement):
[docs] def __str__(self) -> str: return str(self._expression)
[docs] @export class IndexedAggregateElement(AggregateElement): _index: int
[docs] def __init__(self, index: ExpressionUnion, expression: ExpressionUnion): super().__init__(expression) self._index = index
@property def Index(self) -> int: return self._index
[docs] def __str__(self) -> str: return f"{self._index!s} => {self._expression!s}"
[docs] @export class RangedAggregateElement(AggregateElement): _range: Range
[docs] def __init__(self, rng: Range, expression: ExpressionUnion): super().__init__(expression) self._range = rng rng._parent = self
@property def Range(self) -> Range: return self._range
[docs] def __str__(self) -> str: return f"{self._range!s} => {self._expression!s}"
[docs] @export class NamedAggregateElement(AggregateElement): _name: Symbol
[docs] def __init__(self, name: Symbol, expression: ExpressionUnion): super().__init__(expression) self._name = name name._parent = self
@property def Name(self) -> Symbol: return self._name
[docs] def __str__(self) -> str: return "{name!s} => {value!s}".format( name=self._name, value=self._expression, )
[docs] @export class OthersAggregateElement(AggregateElement):
[docs] def __str__(self) -> str: return "others => {value!s}".format( value=self._expression, )
[docs] @export class Aggregate(BaseExpression): _elements: List[AggregateElement]
[docs] def __init__(self, elements: Iterable[AggregateElement]): super().__init__() self._elements = [] for element in elements: self._elements.append(element) element._parent = self
@property def Elements(self) -> List[AggregateElement]: return self._elements
[docs] def __str__(self) -> str: choices = [str(element) for element in self._elements] return "({choices})".format( choices=", ".join(choices) )