Coverage for pyVHDLModel / Expression.py: 77%
507 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-21 22:17 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-21 22:17 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2025 Patrick Lehmann - Boetzingen, Germany #
15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32"""
33This module contains parts of an abstract document language model for VHDL.
35All declarations for literals, aggregates, operators forming an expressions.
36"""
37from enum import Flag
38from typing import Tuple, List, Iterable, Union, ClassVar, Optional as Nullable
40from pyTooling.Decorators import export, readonly
42from pyVHDLModel.Base import ModelEntity, Direction, Range
43from pyVHDLModel.Symbol import Symbol
46ExpressionUnion = Union[
47 'BaseExpression',
48 'QualifiedExpression',
49 'FunctionCall',
50 'TypeConversion',
51 # ConstantOrSymbol, TODO: ObjectSymbol
52 'Literal',
53]
56@export
57class BaseExpression(ModelEntity):
58 """A ``BaseExpression`` is a base-class for all expressions."""
61@export
62class Literal(BaseExpression):
63 """A ``Literal`` is a base-class for all literals."""
66@export
67class NullLiteral(Literal):
68 def __str__(self) -> str:
69 return "null"
72@export
73class EnumerationLiteral(Literal):
74 _value: str
76 def __init__(self, value: str, parent: ModelEntity = None) -> None:
77 super().__init__(parent)
79 self._value = value
81 @readonly
82 def Value(self) -> str:
83 return self._value
85 def __str__(self) -> str:
86 return self._value
89@export
90class NumericLiteral(Literal):
91 """A ``NumericLiteral`` is a base-class for all numeric literals."""
94@export
95class IntegerLiteral(NumericLiteral):
96 _value: int
98 def __init__(self, value: int) -> None:
99 super().__init__()
100 self._value = value
102 @readonly
103 def Value(self) -> int:
104 return self._value
106 def __str__(self) -> str:
107 return str(self._value)
110@export
111class FloatingPointLiteral(NumericLiteral):
112 _value: float
114 def __init__(self, value: float) -> None:
115 super().__init__()
116 self._value = value
118 @readonly
119 def Value(self) -> float:
120 return self._value
122 def __str__(self) -> str:
123 return str(self._value)
126@export
127class PhysicalLiteral(NumericLiteral):
128 _unitName: str
130 def __init__(self, unitName: str) -> None:
131 super().__init__()
132 self._unitName = unitName
134 @readonly
135 def UnitName(self) -> str:
136 return self._unitName
138 def __str__(self) -> str:
139 return f"{self._value} {self._unitName}"
142@export
143class PhysicalIntegerLiteral(PhysicalLiteral):
144 _value: int
146 def __init__(self, value: int, unitName: str) -> None:
147 super().__init__(unitName)
148 self._value = value
150 @readonly
151 def Value(self) -> int:
152 return self._value
155@export
156class PhysicalFloatingLiteral(PhysicalLiteral):
157 _value: float
159 def __init__(self, value: float, unitName: str) -> None:
160 super().__init__(unitName)
161 self._value = value
163 @readonly
164 def Value(self) -> float:
165 return self._value
168@export
169class CharacterLiteral(Literal):
170 _value: str
172 def __init__(self, value: str) -> None:
173 super().__init__()
174 self._value = value
176 @readonly
177 def Value(self) -> str:
178 return self._value
180 def __str__(self) -> str:
181 return str(self._value)
184@export
185class StringLiteral(Literal):
186 _value: str
188 def __init__(self, value: str) -> None:
189 super().__init__()
190 self._value = value
192 @readonly
193 def Value(self) -> str:
194 return self._value
196 def __str__(self) -> str:
197 return "\"" + self._value + "\""
200@export
201class BitStringBase(Flag):
202 NoBase = 0
203 Binary = 2
204 Octal = 8
205 Decimal = 10
206 Hexadecimal = 16
207 Unsigned = 32
208 Signed = 64
211@export
212class BitStringLiteral(Literal):
213 # _base: ClassVar[BitStringBase]
214 _value: str
215 _binaryValue: str
216 _bits: int
217 _length: Nullable[int]
218 _signed: Nullable[bool]
220 def __init__(self, value: str, length: Nullable[int] = None, signed: Nullable[bool] = None) -> None:
221 super().__init__()
222 self._value = value
223 self._length = length
224 self._signed = signed
226 self._binaryValue = None
227 self._bits = None
229 @readonly
230 def Value(self) -> str:
231 return self._value
233 @readonly
234 def BinaryValue(self) -> str:
235 return self._binaryValue
237 @readonly
238 def Bits(self) -> Nullable[int]:
239 return self._bits
241 @readonly
242 def Length(self) -> Nullable[int]:
243 return self._length
245 @readonly
246 def Signed(self) -> Nullable[bool]:
247 return self._signed
249 def __str__(self) -> str:
250 signed = "" if self._signed is None else "s" if self._signed is True else "u"
251 if self._base is BitStringBase.NoBase:
252 base = ""
253 elif self._base is BitStringBase.Binary:
254 base = "b"
255 elif self._base is BitStringBase.Octal:
256 base = "o"
257 elif self._base is BitStringBase.Decimal:
258 base = "d"
259 elif self._base is BitStringBase.Hexadecimal:
260 base = "x"
261 length = "" if self._length is None else str(self._length)
262 return length + signed + base + "\"" + self._value + "\""
265@export
266class BinaryBitStringLiteral(BitStringLiteral):
267 _base: ClassVar[BitStringBase] = BitStringBase.Binary
270@export
271class OctalBitStringLiteral(BitStringLiteral):
272 _base: ClassVar[BitStringBase] = BitStringBase.Octal
275@export
276class DecimalBitStringLiteral(BitStringLiteral):
277 _base: ClassVar[BitStringBase] = BitStringBase.Decimal
280@export
281class HexadecimalBitStringLiteral(BitStringLiteral):
282 _base: ClassVar[BitStringBase] = BitStringBase.Hexadecimal
285@export
286class ParenthesisExpression: #(Protocol):
287 __slots__ = () # FIXME: use ExtendedType?
289 @readonly
290 def Operand(self) -> ExpressionUnion:
291 return None
294@export
295class UnaryExpression(BaseExpression):
296 """A ``UnaryExpression`` is a base-class for all unary expressions."""
298 _FORMAT: Tuple[str, str]
299 _operand: ExpressionUnion
301 def __init__(self, operand: ExpressionUnion, parent: ModelEntity = None) -> None:
302 super().__init__(parent)
304 self._operand = operand
305 # operand._parent = self # FIXME: operand is provided as None
307 @readonly
308 def Operand(self):
309 return self._operand
311 def __str__(self) -> str:
312 return f"{self._FORMAT[0]}{self._operand!s}{self._FORMAT[1]}"
315@export
316class NegationExpression(UnaryExpression):
317 _FORMAT = ("-", "")
320@export
321class IdentityExpression(UnaryExpression):
322 _FORMAT = ("+", "")
325@export
326class InverseExpression(UnaryExpression):
327 _FORMAT = ("not ", "")
330@export
331class UnaryAndExpression(UnaryExpression):
332 _FORMAT = ("and ", "")
335@export
336class UnaryNandExpression(UnaryExpression):
337 _FORMAT = ("nand ", "")
340@export
341class UnaryOrExpression(UnaryExpression):
342 _FORMAT = ("or ", "")
345@export
346class UnaryNorExpression(UnaryExpression):
347 _FORMAT = ("nor ", "")
350@export
351class UnaryXorExpression(UnaryExpression):
352 _FORMAT = ("xor ", "")
355@export
356class UnaryXnorExpression(UnaryExpression):
357 _FORMAT = ("xnor ", "")
360@export
361class AbsoluteExpression(UnaryExpression):
362 _FORMAT = ("abs ", "")
365@export
366class TypeConversion(UnaryExpression):
367 pass
370@export
371class SubExpression(UnaryExpression, ParenthesisExpression):
372 _FORMAT = ("(", ")")
375@export
376class BinaryExpression(BaseExpression):
377 """A ``BinaryExpression`` is a base-class for all binary expressions."""
379 _FORMAT: Tuple[str, str, str]
380 _leftOperand: ExpressionUnion
381 _rightOperand: ExpressionUnion
383 def __init__(self, leftOperand: ExpressionUnion, rightOperand: ExpressionUnion, parent: ModelEntity = None) -> None:
384 super().__init__(parent)
386 self._leftOperand = leftOperand
387 leftOperand._parent = self
389 self._rightOperand = rightOperand
390 rightOperand._parent = self
392 @property
393 def LeftOperand(self):
394 return self._leftOperand
396 @property
397 def RightOperand(self):
398 return self._rightOperand
400 def __str__(self) -> str:
401 return "{leftOperator}{leftOperand!s}{middleOperator}{rightOperand!s}{rightOperator}".format(
402 leftOperator=self._FORMAT[0],
403 leftOperand=self._leftOperand,
404 middleOperator=self._FORMAT[1],
405 rightOperand=self._rightOperand,
406 rightOperator=self._FORMAT[2],
407 )
410@export
411class RangeExpression(BinaryExpression):
412 _direction: Direction
414 @property
415 def Direction(self) -> Direction:
416 return self._direction
419@export
420class AscendingRangeExpression(RangeExpression):
421 _direction = Direction.To
422 _FORMAT = ("", " to ", "")
425@export
426class DescendingRangeExpression(RangeExpression):
427 _direction = Direction.DownTo
428 _FORMAT = ("", " downto ", "")
431@export
432class AddingExpression(BinaryExpression):
433 """A ``AddingExpression`` is a base-class for all adding expressions."""
436@export
437class AdditionExpression(AddingExpression):
438 _FORMAT = ("", " + ", "")
441@export
442class SubtractionExpression(AddingExpression):
443 _FORMAT = ("", " - ", "")
446@export
447class ConcatenationExpression(AddingExpression):
448 _FORMAT = ("", " & ", "")
451@export
452class MultiplyingExpression(BinaryExpression):
453 """A ``MultiplyingExpression`` is a base-class for all multiplying expressions."""
456@export
457class MultiplyExpression(MultiplyingExpression):
458 _FORMAT = ("", " * ", "")
461@export
462class DivisionExpression(MultiplyingExpression):
463 _FORMAT = ("", " / ", "")
466@export
467class RemainderExpression(MultiplyingExpression):
468 _FORMAT = ("", " rem ", "")
471@export
472class ModuloExpression(MultiplyingExpression):
473 _FORMAT = ("", " mod ", "")
476@export
477class ExponentiationExpression(MultiplyingExpression):
478 _FORMAT = ("", "**", "")
481@export
482class LogicalExpression(BinaryExpression):
483 """A ``LogicalExpression`` is a base-class for all logical expressions."""
486@export
487class AndExpression(LogicalExpression):
488 _FORMAT = ("", " and ", "")
491@export
492class NandExpression(LogicalExpression):
493 _FORMAT = ("", " nand ", "")
496@export
497class OrExpression(LogicalExpression):
498 _FORMAT = ("", " or ", "")
501@export
502class NorExpression(LogicalExpression):
503 _FORMAT = ("", " nor ", "")
506@export
507class XorExpression(LogicalExpression):
508 _FORMAT = ("", " xor ", "")
511@export
512class XnorExpression(LogicalExpression):
513 _FORMAT = ("", " xnor ", "")
516@export
517class RelationalExpression(BinaryExpression):
518 """A ``RelationalExpression`` is a base-class for all shifting expressions."""
521@export
522class EqualExpression(RelationalExpression):
523 _FORMAT = ("", " = ", "")
526@export
527class UnequalExpression(RelationalExpression):
528 _FORMAT = ("", " /= ", "")
531@export
532class GreaterThanExpression(RelationalExpression):
533 _FORMAT = ("", " > ", "")
536@export
537class GreaterEqualExpression(RelationalExpression):
538 _FORMAT = ("", " >= ", "")
541@export
542class LessThanExpression(RelationalExpression):
543 _FORMAT = ("", " < ", "")
546@export
547class LessEqualExpression(RelationalExpression):
548 _FORMAT = ("", " <= ", "")
551@export
552class MatchingRelationalExpression(RelationalExpression):
553 pass
556@export
557class MatchingEqualExpression(MatchingRelationalExpression):
558 _FORMAT = ("", " ?= ", "")
561@export
562class MatchingUnequalExpression(MatchingRelationalExpression):
563 _FORMAT = ("", " ?/= ", "")
566@export
567class MatchingGreaterThanExpression(MatchingRelationalExpression):
568 _FORMAT = ("", " ?> ", "")
571@export
572class MatchingGreaterEqualExpression(MatchingRelationalExpression):
573 _FORMAT = ("", " ?>= ", "")
576@export
577class MatchingLessThanExpression(MatchingRelationalExpression):
578 _FORMAT = ("", " ?< ", "")
581@export
582class MatchingLessEqualExpression(MatchingRelationalExpression):
583 _FORMAT = ("", " ?<= ", "")
586@export
587class ShiftExpression(BinaryExpression):
588 """A ``ShiftExpression`` is a base-class for all shifting expressions."""
591@export
592class ShiftLogicExpression(ShiftExpression):
593 pass
596@export
597class ShiftArithmeticExpression(ShiftExpression):
598 pass
601@export
602class RotateExpression(ShiftExpression):
603 pass
606@export
607class ShiftRightLogicExpression(ShiftLogicExpression):
608 _FORMAT = ("", " srl ", "")
611@export
612class ShiftLeftLogicExpression(ShiftLogicExpression):
613 _FORMAT = ("", " sll ", "")
616@export
617class ShiftRightArithmeticExpression(ShiftArithmeticExpression):
618 _FORMAT = ("", " sra ", "")
621@export
622class ShiftLeftArithmeticExpression(ShiftArithmeticExpression):
623 _FORMAT = ("", " sla ", "")
626@export
627class RotateRightExpression(RotateExpression):
628 _FORMAT = ("", " ror ", "")
631@export
632class RotateLeftExpression(RotateExpression):
633 _FORMAT = ("", " rol ", "")
636@export
637class QualifiedExpression(BaseExpression, ParenthesisExpression):
638 _operand: ExpressionUnion
639 _subtype: Symbol
641 def __init__(self, subtype: Symbol, operand: ExpressionUnion, parent: ModelEntity = None) -> None:
642 super().__init__(parent)
644 self._operand = operand
645 operand._parent = self
647 self._subtype = subtype
648 subtype._parent = self
650 @property
651 def Operand(self):
652 return self._operand
654 @property
655 def Subtyped(self):
656 return self._subtype
658 def __str__(self) -> str:
659 return f"{self._subtype}'({self._operand!s})"
662@export
663class TernaryExpression(BaseExpression):
664 """A ``TernaryExpression`` is a base-class for all ternary expressions."""
666 _FORMAT: Tuple[str, str, str, str]
667 _firstOperand: ExpressionUnion
668 _secondOperand: ExpressionUnion
669 _thirdOperand: ExpressionUnion
671 def __init__(self, parent: ModelEntity = None) -> None:
672 super().__init__(parent)
674 # FIXME: parameters and initializers are missing !!
676 @property
677 def FirstOperand(self):
678 return self._firstOperand
680 @property
681 def SecondOperand(self):
682 return self._secondOperand
684 @property
685 def ThirdOperand(self):
686 return self._thirdOperand
688 def __str__(self) -> str:
689 return "{beforeFirstOperator}{firstOperand!s}{beforeSecondOperator}{secondOperand!s}{beforeThirdOperator}{thirdOperand!s}{lastOperator}".format(
690 beforeFirstOperator=self._FORMAT[0],
691 firstOperand=self._firstOperand,
692 beforeSecondOperator=self._FORMAT[1],
693 secondOperand=self._secondOperand,
694 beforeThirdOperator=self._FORMAT[2],
695 thirdOperand=self._thirdOperand,
696 lastOperator=self._FORMAT[4],
697 )
700@export
701class WhenElseExpression(TernaryExpression):
702 _FORMAT = ("", " when ", " else ", "")
705@export
706class FunctionCall(BaseExpression):
707 pass
710@export
711class Allocation(BaseExpression):
712 pass
715@export
716class SubtypeAllocation(Allocation):
717 _subtype: Symbol
719 def __init__(self, subtype: Symbol, parent: ModelEntity = None) -> None:
720 super().__init__(parent)
722 self._subtype = subtype
723 subtype._parent = self
725 @property
726 def Subtype(self) -> Symbol:
727 return self._subtype
729 def __str__(self) -> str:
730 return f"new {self._subtype!s}"
733@export
734class QualifiedExpressionAllocation(Allocation):
735 _qualifiedExpression: QualifiedExpression
737 def __init__(self, qualifiedExpression: QualifiedExpression, parent: ModelEntity = None) -> None:
738 super().__init__(parent)
740 self._qualifiedExpression = qualifiedExpression
741 qualifiedExpression._parent = self
743 @property
744 def QualifiedExpression(self) -> QualifiedExpression:
745 return self._qualifiedExpression
747 def __str__(self) -> str:
748 return f"new {self._qualifiedExpression!s}"
751@export
752class AggregateElement(ModelEntity):
753 """A ``AggregateElement`` is a base-class for all aggregate elements."""
755 _expression: ExpressionUnion
757 def __init__(self, expression: ExpressionUnion, parent: ModelEntity = None) -> None:
758 super().__init__(parent)
760 self._expression = expression
761 expression._parent = self
763 @property
764 def Expression(self):
765 return self._expression
768@export
769class SimpleAggregateElement(AggregateElement):
770 def __str__(self) -> str:
771 return str(self._expression)
774@export
775class IndexedAggregateElement(AggregateElement):
776 _index: int
778 def __init__(self, index: ExpressionUnion, expression: ExpressionUnion, parent: ModelEntity = None) -> None:
779 super().__init__(expression, parent)
781 self._index = index
783 @property
784 def Index(self) -> int:
785 return self._index
787 def __str__(self) -> str:
788 return f"{self._index!s} => {self._expression!s}"
791@export
792class RangedAggregateElement(AggregateElement):
793 _range: Range
795 def __init__(self, rng: Range, expression: ExpressionUnion, parent: ModelEntity = None) -> None:
796 super().__init__(expression, parent)
798 self._range = rng
799 rng._parent = self
801 @property
802 def Range(self) -> Range:
803 return self._range
805 def __str__(self) -> str:
806 return f"{self._range!s} => {self._expression!s}"
809@export
810class NamedAggregateElement(AggregateElement):
811 _name: Symbol
813 def __init__(self, name: Symbol, expression: ExpressionUnion, parent: ModelEntity = None) -> None:
814 super().__init__(expression, parent)
816 self._name = name
817 name._parent = self
819 @property
820 def Name(self) -> Symbol:
821 return self._name
823 def __str__(self) -> str:
824 return "{name!s} => {value!s}".format(
825 name=self._name,
826 value=self._expression,
827 )
830@export
831class OthersAggregateElement(AggregateElement):
832 def __str__(self) -> str:
833 return "others => {value!s}".format(
834 value=self._expression,
835 )
838@export
839class Aggregate(BaseExpression):
840 _elements: List[AggregateElement]
842 def __init__(self, elements: Iterable[AggregateElement], parent: ModelEntity = None) -> None:
843 super().__init__(parent)
845 self._elements = []
846 for element in elements:
847 self._elements.append(element)
848 element._parent = self
850 @property
851 def Elements(self) -> List[AggregateElement]:
852 return self._elements
854 def __str__(self) -> str:
855 choices = [str(element) for element in self._elements]
856 return "({choices})".format(
857 choices=", ".join(choices)
858 )