Coverage for pyVHDLModel / Expression.py: 77%

507 statements  

« 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. 

34 

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 

39 

40from pyTooling.Decorators import export, readonly 

41 

42from pyVHDLModel.Base import ModelEntity, Direction, Range 

43from pyVHDLModel.Symbol import Symbol 

44 

45 

46ExpressionUnion = Union[ 

47 'BaseExpression', 

48 'QualifiedExpression', 

49 'FunctionCall', 

50 'TypeConversion', 

51 # ConstantOrSymbol, TODO: ObjectSymbol 

52 'Literal', 

53] 

54 

55 

56@export 

57class BaseExpression(ModelEntity): 

58 """A ``BaseExpression`` is a base-class for all expressions.""" 

59 

60 

61@export 

62class Literal(BaseExpression): 

63 """A ``Literal`` is a base-class for all literals.""" 

64 

65 

66@export 

67class NullLiteral(Literal): 

68 def __str__(self) -> str: 

69 return "null" 

70 

71 

72@export 

73class EnumerationLiteral(Literal): 

74 _value: str 

75 

76 def __init__(self, value: str, parent: ModelEntity = None) -> None: 

77 super().__init__(parent) 

78 

79 self._value = value 

80 

81 @readonly 

82 def Value(self) -> str: 

83 return self._value 

84 

85 def __str__(self) -> str: 

86 return self._value 

87 

88 

89@export 

90class NumericLiteral(Literal): 

91 """A ``NumericLiteral`` is a base-class for all numeric literals.""" 

92 

93 

94@export 

95class IntegerLiteral(NumericLiteral): 

96 _value: int 

97 

98 def __init__(self, value: int) -> None: 

99 super().__init__() 

100 self._value = value 

101 

102 @readonly 

103 def Value(self) -> int: 

104 return self._value 

105 

106 def __str__(self) -> str: 

107 return str(self._value) 

108 

109 

110@export 

111class FloatingPointLiteral(NumericLiteral): 

112 _value: float 

113 

114 def __init__(self, value: float) -> None: 

115 super().__init__() 

116 self._value = value 

117 

118 @readonly 

119 def Value(self) -> float: 

120 return self._value 

121 

122 def __str__(self) -> str: 

123 return str(self._value) 

124 

125 

126@export 

127class PhysicalLiteral(NumericLiteral): 

128 _unitName: str 

129 

130 def __init__(self, unitName: str) -> None: 

131 super().__init__() 

132 self._unitName = unitName 

133 

134 @readonly 

135 def UnitName(self) -> str: 

136 return self._unitName 

137 

138 def __str__(self) -> str: 

139 return f"{self._value} {self._unitName}" 

140 

141 

142@export 

143class PhysicalIntegerLiteral(PhysicalLiteral): 

144 _value: int 

145 

146 def __init__(self, value: int, unitName: str) -> None: 

147 super().__init__(unitName) 

148 self._value = value 

149 

150 @readonly 

151 def Value(self) -> int: 

152 return self._value 

153 

154 

155@export 

156class PhysicalFloatingLiteral(PhysicalLiteral): 

157 _value: float 

158 

159 def __init__(self, value: float, unitName: str) -> None: 

160 super().__init__(unitName) 

161 self._value = value 

162 

163 @readonly 

164 def Value(self) -> float: 

165 return self._value 

166 

167 

168@export 

169class CharacterLiteral(Literal): 

170 _value: str 

171 

172 def __init__(self, value: str) -> None: 

173 super().__init__() 

174 self._value = value 

175 

176 @readonly 

177 def Value(self) -> str: 

178 return self._value 

179 

180 def __str__(self) -> str: 

181 return str(self._value) 

182 

183 

184@export 

185class StringLiteral(Literal): 

186 _value: str 

187 

188 def __init__(self, value: str) -> None: 

189 super().__init__() 

190 self._value = value 

191 

192 @readonly 

193 def Value(self) -> str: 

194 return self._value 

195 

196 def __str__(self) -> str: 

197 return "\"" + self._value + "\"" 

198 

199 

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 

209 

210 

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] 

219 

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 

225 

226 self._binaryValue = None 

227 self._bits = None 

228 

229 @readonly 

230 def Value(self) -> str: 

231 return self._value 

232 

233 @readonly 

234 def BinaryValue(self) -> str: 

235 return self._binaryValue 

236 

237 @readonly 

238 def Bits(self) -> Nullable[int]: 

239 return self._bits 

240 

241 @readonly 

242 def Length(self) -> Nullable[int]: 

243 return self._length 

244 

245 @readonly 

246 def Signed(self) -> Nullable[bool]: 

247 return self._signed 

248 

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 + "\"" 

263 

264 

265@export 

266class BinaryBitStringLiteral(BitStringLiteral): 

267 _base: ClassVar[BitStringBase] = BitStringBase.Binary 

268 

269 

270@export 

271class OctalBitStringLiteral(BitStringLiteral): 

272 _base: ClassVar[BitStringBase] = BitStringBase.Octal 

273 

274 

275@export 

276class DecimalBitStringLiteral(BitStringLiteral): 

277 _base: ClassVar[BitStringBase] = BitStringBase.Decimal 

278 

279 

280@export 

281class HexadecimalBitStringLiteral(BitStringLiteral): 

282 _base: ClassVar[BitStringBase] = BitStringBase.Hexadecimal 

283 

284 

285@export 

286class ParenthesisExpression: #(Protocol): 

287 __slots__ = () # FIXME: use ExtendedType? 

288 

289 @readonly 

290 def Operand(self) -> ExpressionUnion: 

291 return None 

292 

293 

294@export 

295class UnaryExpression(BaseExpression): 

296 """A ``UnaryExpression`` is a base-class for all unary expressions.""" 

297 

298 _FORMAT: Tuple[str, str] 

299 _operand: ExpressionUnion 

300 

301 def __init__(self, operand: ExpressionUnion, parent: ModelEntity = None) -> None: 

302 super().__init__(parent) 

303 

304 self._operand = operand 

305 # operand._parent = self # FIXME: operand is provided as None 

306 

307 @readonly 

308 def Operand(self): 

309 return self._operand 

310 

311 def __str__(self) -> str: 

312 return f"{self._FORMAT[0]}{self._operand!s}{self._FORMAT[1]}" 

313 

314 

315@export 

316class NegationExpression(UnaryExpression): 

317 _FORMAT = ("-", "") 

318 

319 

320@export 

321class IdentityExpression(UnaryExpression): 

322 _FORMAT = ("+", "") 

323 

324 

325@export 

326class InverseExpression(UnaryExpression): 

327 _FORMAT = ("not ", "") 

328 

329 

330@export 

331class UnaryAndExpression(UnaryExpression): 

332 _FORMAT = ("and ", "") 

333 

334 

335@export 

336class UnaryNandExpression(UnaryExpression): 

337 _FORMAT = ("nand ", "") 

338 

339 

340@export 

341class UnaryOrExpression(UnaryExpression): 

342 _FORMAT = ("or ", "") 

343 

344 

345@export 

346class UnaryNorExpression(UnaryExpression): 

347 _FORMAT = ("nor ", "") 

348 

349 

350@export 

351class UnaryXorExpression(UnaryExpression): 

352 _FORMAT = ("xor ", "") 

353 

354 

355@export 

356class UnaryXnorExpression(UnaryExpression): 

357 _FORMAT = ("xnor ", "") 

358 

359 

360@export 

361class AbsoluteExpression(UnaryExpression): 

362 _FORMAT = ("abs ", "") 

363 

364 

365@export 

366class TypeConversion(UnaryExpression): 

367 pass 

368 

369 

370@export 

371class SubExpression(UnaryExpression, ParenthesisExpression): 

372 _FORMAT = ("(", ")") 

373 

374 

375@export 

376class BinaryExpression(BaseExpression): 

377 """A ``BinaryExpression`` is a base-class for all binary expressions.""" 

378 

379 _FORMAT: Tuple[str, str, str] 

380 _leftOperand: ExpressionUnion 

381 _rightOperand: ExpressionUnion 

382 

383 def __init__(self, leftOperand: ExpressionUnion, rightOperand: ExpressionUnion, parent: ModelEntity = None) -> None: 

384 super().__init__(parent) 

385 

386 self._leftOperand = leftOperand 

387 leftOperand._parent = self 

388 

389 self._rightOperand = rightOperand 

390 rightOperand._parent = self 

391 

392 @property 

393 def LeftOperand(self): 

394 return self._leftOperand 

395 

396 @property 

397 def RightOperand(self): 

398 return self._rightOperand 

399 

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 ) 

408 

409 

410@export 

411class RangeExpression(BinaryExpression): 

412 _direction: Direction 

413 

414 @property 

415 def Direction(self) -> Direction: 

416 return self._direction 

417 

418 

419@export 

420class AscendingRangeExpression(RangeExpression): 

421 _direction = Direction.To 

422 _FORMAT = ("", " to ", "") 

423 

424 

425@export 

426class DescendingRangeExpression(RangeExpression): 

427 _direction = Direction.DownTo 

428 _FORMAT = ("", " downto ", "") 

429 

430 

431@export 

432class AddingExpression(BinaryExpression): 

433 """A ``AddingExpression`` is a base-class for all adding expressions.""" 

434 

435 

436@export 

437class AdditionExpression(AddingExpression): 

438 _FORMAT = ("", " + ", "") 

439 

440 

441@export 

442class SubtractionExpression(AddingExpression): 

443 _FORMAT = ("", " - ", "") 

444 

445 

446@export 

447class ConcatenationExpression(AddingExpression): 

448 _FORMAT = ("", " & ", "") 

449 

450 

451@export 

452class MultiplyingExpression(BinaryExpression): 

453 """A ``MultiplyingExpression`` is a base-class for all multiplying expressions.""" 

454 

455 

456@export 

457class MultiplyExpression(MultiplyingExpression): 

458 _FORMAT = ("", " * ", "") 

459 

460 

461@export 

462class DivisionExpression(MultiplyingExpression): 

463 _FORMAT = ("", " / ", "") 

464 

465 

466@export 

467class RemainderExpression(MultiplyingExpression): 

468 _FORMAT = ("", " rem ", "") 

469 

470 

471@export 

472class ModuloExpression(MultiplyingExpression): 

473 _FORMAT = ("", " mod ", "") 

474 

475 

476@export 

477class ExponentiationExpression(MultiplyingExpression): 

478 _FORMAT = ("", "**", "") 

479 

480 

481@export 

482class LogicalExpression(BinaryExpression): 

483 """A ``LogicalExpression`` is a base-class for all logical expressions.""" 

484 

485 

486@export 

487class AndExpression(LogicalExpression): 

488 _FORMAT = ("", " and ", "") 

489 

490 

491@export 

492class NandExpression(LogicalExpression): 

493 _FORMAT = ("", " nand ", "") 

494 

495 

496@export 

497class OrExpression(LogicalExpression): 

498 _FORMAT = ("", " or ", "") 

499 

500 

501@export 

502class NorExpression(LogicalExpression): 

503 _FORMAT = ("", " nor ", "") 

504 

505 

506@export 

507class XorExpression(LogicalExpression): 

508 _FORMAT = ("", " xor ", "") 

509 

510 

511@export 

512class XnorExpression(LogicalExpression): 

513 _FORMAT = ("", " xnor ", "") 

514 

515 

516@export 

517class RelationalExpression(BinaryExpression): 

518 """A ``RelationalExpression`` is a base-class for all shifting expressions.""" 

519 

520 

521@export 

522class EqualExpression(RelationalExpression): 

523 _FORMAT = ("", " = ", "") 

524 

525 

526@export 

527class UnequalExpression(RelationalExpression): 

528 _FORMAT = ("", " /= ", "") 

529 

530 

531@export 

532class GreaterThanExpression(RelationalExpression): 

533 _FORMAT = ("", " > ", "") 

534 

535 

536@export 

537class GreaterEqualExpression(RelationalExpression): 

538 _FORMAT = ("", " >= ", "") 

539 

540 

541@export 

542class LessThanExpression(RelationalExpression): 

543 _FORMAT = ("", " < ", "") 

544 

545 

546@export 

547class LessEqualExpression(RelationalExpression): 

548 _FORMAT = ("", " <= ", "") 

549 

550 

551@export 

552class MatchingRelationalExpression(RelationalExpression): 

553 pass 

554 

555 

556@export 

557class MatchingEqualExpression(MatchingRelationalExpression): 

558 _FORMAT = ("", " ?= ", "") 

559 

560 

561@export 

562class MatchingUnequalExpression(MatchingRelationalExpression): 

563 _FORMAT = ("", " ?/= ", "") 

564 

565 

566@export 

567class MatchingGreaterThanExpression(MatchingRelationalExpression): 

568 _FORMAT = ("", " ?> ", "") 

569 

570 

571@export 

572class MatchingGreaterEqualExpression(MatchingRelationalExpression): 

573 _FORMAT = ("", " ?>= ", "") 

574 

575 

576@export 

577class MatchingLessThanExpression(MatchingRelationalExpression): 

578 _FORMAT = ("", " ?< ", "") 

579 

580 

581@export 

582class MatchingLessEqualExpression(MatchingRelationalExpression): 

583 _FORMAT = ("", " ?<= ", "") 

584 

585 

586@export 

587class ShiftExpression(BinaryExpression): 

588 """A ``ShiftExpression`` is a base-class for all shifting expressions.""" 

589 

590 

591@export 

592class ShiftLogicExpression(ShiftExpression): 

593 pass 

594 

595 

596@export 

597class ShiftArithmeticExpression(ShiftExpression): 

598 pass 

599 

600 

601@export 

602class RotateExpression(ShiftExpression): 

603 pass 

604 

605 

606@export 

607class ShiftRightLogicExpression(ShiftLogicExpression): 

608 _FORMAT = ("", " srl ", "") 

609 

610 

611@export 

612class ShiftLeftLogicExpression(ShiftLogicExpression): 

613 _FORMAT = ("", " sll ", "") 

614 

615 

616@export 

617class ShiftRightArithmeticExpression(ShiftArithmeticExpression): 

618 _FORMAT = ("", " sra ", "") 

619 

620 

621@export 

622class ShiftLeftArithmeticExpression(ShiftArithmeticExpression): 

623 _FORMAT = ("", " sla ", "") 

624 

625 

626@export 

627class RotateRightExpression(RotateExpression): 

628 _FORMAT = ("", " ror ", "") 

629 

630 

631@export 

632class RotateLeftExpression(RotateExpression): 

633 _FORMAT = ("", " rol ", "") 

634 

635 

636@export 

637class QualifiedExpression(BaseExpression, ParenthesisExpression): 

638 _operand: ExpressionUnion 

639 _subtype: Symbol 

640 

641 def __init__(self, subtype: Symbol, operand: ExpressionUnion, parent: ModelEntity = None) -> None: 

642 super().__init__(parent) 

643 

644 self._operand = operand 

645 operand._parent = self 

646 

647 self._subtype = subtype 

648 subtype._parent = self 

649 

650 @property 

651 def Operand(self): 

652 return self._operand 

653 

654 @property 

655 def Subtyped(self): 

656 return self._subtype 

657 

658 def __str__(self) -> str: 

659 return f"{self._subtype}'({self._operand!s})" 

660 

661 

662@export 

663class TernaryExpression(BaseExpression): 

664 """A ``TernaryExpression`` is a base-class for all ternary expressions.""" 

665 

666 _FORMAT: Tuple[str, str, str, str] 

667 _firstOperand: ExpressionUnion 

668 _secondOperand: ExpressionUnion 

669 _thirdOperand: ExpressionUnion 

670 

671 def __init__(self, parent: ModelEntity = None) -> None: 

672 super().__init__(parent) 

673 

674 # FIXME: parameters and initializers are missing !! 

675 

676 @property 

677 def FirstOperand(self): 

678 return self._firstOperand 

679 

680 @property 

681 def SecondOperand(self): 

682 return self._secondOperand 

683 

684 @property 

685 def ThirdOperand(self): 

686 return self._thirdOperand 

687 

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 ) 

698 

699 

700@export 

701class WhenElseExpression(TernaryExpression): 

702 _FORMAT = ("", " when ", " else ", "") 

703 

704 

705@export 

706class FunctionCall(BaseExpression): 

707 pass 

708 

709 

710@export 

711class Allocation(BaseExpression): 

712 pass 

713 

714 

715@export 

716class SubtypeAllocation(Allocation): 

717 _subtype: Symbol 

718 

719 def __init__(self, subtype: Symbol, parent: ModelEntity = None) -> None: 

720 super().__init__(parent) 

721 

722 self._subtype = subtype 

723 subtype._parent = self 

724 

725 @property 

726 def Subtype(self) -> Symbol: 

727 return self._subtype 

728 

729 def __str__(self) -> str: 

730 return f"new {self._subtype!s}" 

731 

732 

733@export 

734class QualifiedExpressionAllocation(Allocation): 

735 _qualifiedExpression: QualifiedExpression 

736 

737 def __init__(self, qualifiedExpression: QualifiedExpression, parent: ModelEntity = None) -> None: 

738 super().__init__(parent) 

739 

740 self._qualifiedExpression = qualifiedExpression 

741 qualifiedExpression._parent = self 

742 

743 @property 

744 def QualifiedExpression(self) -> QualifiedExpression: 

745 return self._qualifiedExpression 

746 

747 def __str__(self) -> str: 

748 return f"new {self._qualifiedExpression!s}" 

749 

750 

751@export 

752class AggregateElement(ModelEntity): 

753 """A ``AggregateElement`` is a base-class for all aggregate elements.""" 

754 

755 _expression: ExpressionUnion 

756 

757 def __init__(self, expression: ExpressionUnion, parent: ModelEntity = None) -> None: 

758 super().__init__(parent) 

759 

760 self._expression = expression 

761 expression._parent = self 

762 

763 @property 

764 def Expression(self): 

765 return self._expression 

766 

767 

768@export 

769class SimpleAggregateElement(AggregateElement): 

770 def __str__(self) -> str: 

771 return str(self._expression) 

772 

773 

774@export 

775class IndexedAggregateElement(AggregateElement): 

776 _index: int 

777 

778 def __init__(self, index: ExpressionUnion, expression: ExpressionUnion, parent: ModelEntity = None) -> None: 

779 super().__init__(expression, parent) 

780 

781 self._index = index 

782 

783 @property 

784 def Index(self) -> int: 

785 return self._index 

786 

787 def __str__(self) -> str: 

788 return f"{self._index!s} => {self._expression!s}" 

789 

790 

791@export 

792class RangedAggregateElement(AggregateElement): 

793 _range: Range 

794 

795 def __init__(self, rng: Range, expression: ExpressionUnion, parent: ModelEntity = None) -> None: 

796 super().__init__(expression, parent) 

797 

798 self._range = rng 

799 rng._parent = self 

800 

801 @property 

802 def Range(self) -> Range: 

803 return self._range 

804 

805 def __str__(self) -> str: 

806 return f"{self._range!s} => {self._expression!s}" 

807 

808 

809@export 

810class NamedAggregateElement(AggregateElement): 

811 _name: Symbol 

812 

813 def __init__(self, name: Symbol, expression: ExpressionUnion, parent: ModelEntity = None) -> None: 

814 super().__init__(expression, parent) 

815 

816 self._name = name 

817 name._parent = self 

818 

819 @property 

820 def Name(self) -> Symbol: 

821 return self._name 

822 

823 def __str__(self) -> str: 

824 return "{name!s} => {value!s}".format( 

825 name=self._name, 

826 value=self._expression, 

827 ) 

828 

829 

830@export 

831class OthersAggregateElement(AggregateElement): 

832 def __str__(self) -> str: 

833 return "others => {value!s}".format( 

834 value=self._expression, 

835 ) 

836 

837 

838@export 

839class Aggregate(BaseExpression): 

840 _elements: List[AggregateElement] 

841 

842 def __init__(self, elements: Iterable[AggregateElement], parent: ModelEntity = None) -> None: 

843 super().__init__(parent) 

844 

845 self._elements = [] 

846 for element in elements: 

847 self._elements.append(element) 

848 element._parent = self 

849 

850 @property 

851 def Elements(self) -> List[AggregateElement]: 

852 return self._elements 

853 

854 def __str__(self) -> str: 

855 choices = [str(element) for element in self._elements] 

856 return "({choices})".format( 

857 choices=", ".join(choices) 

858 )