Coverage for pyVHDLModel/Type.py: 98%

287 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-10-25 10:05 +0000

1# ==================================================================================================================== # 

2# __ ___ _ ____ _ __ __ _ _ # 

3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | # 

4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | # 

5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | # 

6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| # 

7# |_| |___/ # 

8# ==================================================================================================================== # 

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

13# ==================================================================================================================== # 

14# Copyright 2017-2026 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 

35Types. 

36""" 

37from __future__ import annotations 

38 

39from typing import TYPE_CHECKING, Union, Iterator, Iterable, Optional as Nullable, Self 

40 

41from pyTooling.Decorators import export, readonly 

42from pyTooling.MetaClasses import ExtendedType, abstractclass 

43from pyTooling.Graph import Vertex 

44 

45from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin, Range 

46from pyVHDLModel.Symbol import Symbol, SimpleSubtypeSymbol 

47from pyVHDLModel.Expression import EnumerationLiteral, PhysicalIntegerLiteral 

48from pyVHDLModel.Regions import ProtectedTypeDeclarationRegionMixin, SequentialDeclarationRegionMixin, \ 

49 WithoutStatementsMixin 

50 

51if TYPE_CHECKING: 51 ↛ 52line 51 didn't jump to line 52 because the condition on line 51 was never true

52 from pyVHDLModel.Visitor import Visitor 

53 

54 

55@export 

56@abstractclass 

57class BaseType(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): 

58 """ 

59 Represents the base-class of all type entities: full types, subtypes and anonymous types. 

60 

61 Every type is a named entity (:data:`Identifier`, :data:`NormalizedIdentifier`) and can carry 

62 documentation (:data:`Documentation`). 

63 

64 .. seealso:: 

65 

66 * :class:`Type <pyVHDLModel.Type.Type>` 

67 * :class:`Full type <pyVHDLModel.Type.FullType>` 

68 * :class:`Subtype <pyVHDLModel.Type.Subtype>` 

69 """ 

70 

71 _objectVertex: Vertex #: The vertex representing this type in the design's object graph. 

72 

73 def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

74 """ 

75 Initializes underlying ``BaseType``. 

76 

77 :param identifier: Name of the type. 

78 :param documentation: The documentation comment associated with this declaration. 

79 :param parent: Reference to the logical parent in the model hierarchy. 

80 """ 

81 super().__init__(parent) 

82 NamedEntityMixin.__init__(self, identifier) 

83 DocumentedEntityMixin.__init__(self, documentation) 

84 

85 self._objectVertex = None 

86 

87 def __str__(self) -> str: 

88 """ 

89 Formats the type declaration. 

90 

91 **Format:** ``type myType`` 

92 

93 :returns: Formatted type declaration. 

94 """ 

95 return f"type {self._identifier}" 

96 

97 

98@export 

99@abstractclass 

100class Type(BaseType): 

101 """ 

102 Represents a base-class for types introduced by a type declaration. 

103 

104 Besides real type declarations, this is also the base-class of a generic type interface item, which 

105 introduces a type name without defining the type itself. 

106 

107 .. seealso:: 

108 

109 * :class:`Generic type interface item <pyVHDLModel.Interface.GenericTypeInterfaceItem>` 

110 * :class:`Anonymous type <pyVHDLModel.Type.AnonymousType>` 

111 """ 

112 pass 

113 

114 

115@export 

116class AnonymousType(Type): 

117 """ 

118 Represents a base-class for types without a type definition of their own. 

119 

120 An incomplete type is the typical case: it names a type (:data:`Identifier`) whose full 

121 definition follows later in the same declarative part. 

122 

123 .. admonition:: Example 

124 

125 .. code-block:: VHDL 

126 

127 type node; 

128 -- ^^^^ <- Identifier 

129 type ptr is access node; 

130 type node is record 

131 value : integer; 

132 nextNode : ptr; 

133 end record; 

134 """ 

135 

136 def Visit(self, visitor: Visitor) -> None: 

137 """ 

138 Walk this incomplete type declaration with a visitor. 

139 

140 :param visitor: The visitor receiving the events. 

141 """ 

142 visitor.VisitAnonymousType(self) 

143 visitor.DepartAnonymousType(self) 

144 

145 

146@export 

147class FullType(BaseType): 

148 """ 

149 Represents a base-class for all full type definitions, as opposed to a :class:`Subtype`. 

150 

151 This is the distinction the declaration regions index on: a full type is registered in ``Types``, a 

152 subtype in ``Subtypes``. 

153 

154 .. seealso:: 

155 

156 * :class:`Scalar type <pyVHDLModel.Type.ScalarType>` 

157 * :class:`Composite type <pyVHDLModel.Type.CompositeType>` 

158 * :class:`Protected type <pyVHDLModel.Type.ProtectedType>` 

159 * :class:`Protected type body <pyVHDLModel.Type.ProtectedTypeBody>` 

160 * :class:`Access type <pyVHDLModel.Type.AccessType>` 

161 * :class:`File type <pyVHDLModel.Type.FileType>` 

162 """ 

163 pass 

164 

165 

166@export 

167class Subtype(BaseType): 

168 """ 

169 Represents a subtype declaration. 

170 

171 A subtype is a named entity (:data:`Identifier`, :data:`NormalizedIdentifier`) referencing a type 

172 (:data:`Type`). Optionally, the subtype can be narrowed by a constraint (:data:`Range`) and/or 

173 resolved by a resolution function (:data:`ResolutionFunction`). 

174 

175 .. admonition:: Example 

176 

177 Without a constraint: 

178 

179 .. code-block:: VHDL 

180 

181 subtype byte is bit_vector; 

182 -- ^^^^ <- Identifier 

183 -- ^^^^^^^^^^ <- Type 

184 

185 With a constraint: 

186 

187 .. code-block:: VHDL 

188 

189 subtype nibble is bit_vector(3 downto 0); 

190 -- ^^^^^^^^^^^^ <- Range 

191 

192 With a resolution function: 

193 

194 .. code-block:: VHDL 

195 

196 subtype wired is resolved std_ulogic; 

197 -- ^^^^^^^^ <- ResolutionFunction 

198 

199 .. seealso:: 

200 

201 * :class:`Reference to a type or subtype <pyVHDLModel.Symbol.SubtypeSymbol>` 

202 """ 

203 _type: Symbol #: Reference to the type or subtype this subtype is derived from. 

204 _baseType: BaseType #: The resolved base type of this subtype. 

205 _range: Range #: The constraint narrowing the base type, or ``None`` if unconstrained. 

206 _resolutionFunction: Function #: The resolution function, or ``None`` if the subtype is unresolved. 

207 

208 def __init__(self, identifier: str, symbol: Symbol, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

209 """ 

210 Initializes a subtype declaration. 

211 

212 :param identifier: The identifier of a model entity. 

213 :param symbol: Reference to the type or subtype this subtype is derived from. 

214 :param documentation: The documentation comment associated with this declaration. 

215 :param parent: The parent model entity of this entity. 

216 """ 

217 super().__init__(identifier, documentation, parent) 

218 

219 self._type = symbol 

220 self._baseType = None 

221 self._range = None 

222 self._resolutionFunction = None 

223 

224 @readonly 

225 def Type(self) -> Symbol: 

226 """ 

227 Read-only property to access the type (:attr:`_type`). 

228 

229 :returns: The type. 

230 """ 

231 return self._type 

232 

233 @readonly 

234 def BaseType(self) -> BaseType: 

235 """ 

236 Read-only property to access the base type (:attr:`_baseType`). 

237 

238 :returns: The base type. 

239 """ 

240 return self._baseType 

241 

242 @readonly 

243 def Range(self) -> Range: 

244 """ 

245 Read-only property to access the range (:attr:`_range`). 

246 

247 :returns: The range. 

248 """ 

249 return self._range 

250 

251 @readonly 

252 def ResolutionFunction(self) -> Function: 

253 """ 

254 Read-only property to access the resolution function (:attr:`_resolutionFunction`). 

255 

256 :returns: The resolution function. 

257 """ 

258 return self._resolutionFunction 

259 

260 def Visit(self, visitor: Visitor) -> None: 

261 """ 

262 Walk this subtype declaration and its subtype indication with a visitor. 

263 

264 :param visitor: The visitor receiving the events. 

265 """ 

266 visitor.VisitSubtype(self) 

267 self._type.Visit(visitor) 

268 visitor.DepartSubtype(self) 

269 

270 def __str__(self) -> str: 

271 """ 

272 Formats the subtype declaration. 

273 

274 **Format:** ``subtype byte is bit_vector`` 

275 

276 The *base type* is rendered, so an unlinked subtype shows ``None``. 

277 

278 :returns: Formatted subtype declaration. 

279 """ 

280 return f"subtype {self._identifier} is {self._baseType}" 

281 

282 

283@export 

284@abstractclass 

285class ScalarType(FullType): 

286 """ 

287 Represents a base-class for all scalar types: enumerated, integer, real and physical types. 

288 

289 .. seealso:: 

290 

291 * :class:`Ranged scalar type <pyVHDLModel.Type.RangedScalarType>` 

292 * :class:`Enumerated type <pyVHDLModel.Type.EnumeratedType>` 

293 """ 

294 

295 

296@export 

297@abstractclass 

298class RangedScalarType(ScalarType): 

299 """ 

300 Represents a base-class for all scalar types constrained by a range (:data:`Range`). 

301 

302 Integer, real and physical types are ranged. An enumerated type is scalar but not ranged, so it 

303 derives from :class:`ScalarType` directly. 

304 

305 .. seealso:: 

306 

307 * :class:`Integer type <pyVHDLModel.Type.IntegerType>` 

308 * :class:`Real type <pyVHDLModel.Type.RealType>` 

309 * :class:`Physical type <pyVHDLModel.Type.PhysicalType>` 

310 """ 

311 

312 _range: Range #: The range constraining this scalar type. 

313 

314 def __init__(self, identifier: str, rng: Range, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

315 """ 

316 Initialize a scalar type with a range. 

317 

318 :param identifier: The type's identifier. 

319 :param rng: The type's range. 

320 :param documentation: The type's documentation. 

321 :param parent: The parent model entity. 

322 """ 

323 super().__init__(identifier, documentation, parent) 

324 self._range = rng 

325 

326 @readonly 

327 def Range(self) -> Range: 

328 """ 

329 Read-only property to access the type's range (:attr:`_range`). 

330 

331 :returns: The range. 

332 """ 

333 return self._range 

334 

335 

336@export 

337class NumericTypeMixin(metaclass=ExtendedType, mixin=True): 

338 """ 

339 A mixin-class for all numeric types: integer, real and physical types. 

340 

341 .. seealso:: 

342 

343 * :class:`Integer type <pyVHDLModel.Type.IntegerType>` 

344 * :class:`Real type <pyVHDLModel.Type.RealType>` 

345 * :class:`Physical type <pyVHDLModel.Type.PhysicalType>` 

346 """ 

347 

348 def __init__(self) -> None: 

349 """ 

350 Initializes a numeric type. 

351 """ 

352 pass 

353 

354 

355@export 

356class DiscreteTypeMixin(metaclass=ExtendedType, mixin=True): 

357 """ 

358 A mixin-class for all discrete types: enumerated and integer types. 

359 

360 .. seealso:: 

361 

362 * :class:`Enumerated type <pyVHDLModel.Type.EnumeratedType>` 

363 * :class:`Integer type <pyVHDLModel.Type.IntegerType>` 

364 """ 

365 

366 def __init__(self) -> None: 

367 """ 

368 Initializes a discrete type. 

369 """ 

370 pass 

371 

372 

373@export 

374class EnumeratedType(ScalarType, DiscreteTypeMixin): 

375 """ 

376 Represents an enumerated type definition. 

377 

378 An enumerated type is a named entity (:data:`Identifier`) listing its enumeration literals 

379 (:data:`Literals`) in declaration order. 

380 

381 .. admonition:: Example 

382 

383 .. code-block:: VHDL 

384 

385 type state is (Idle, Running, Done); 

386 -- ^^^^^ <- Identifier 

387 -- ^^^^^^^^^^^^^^^^^^^ <- Literals 

388 """ 

389 _literals: list[EnumerationLiteral] #: List of all enumeration literals, in declaration order. 

390 

391 def __init__(self, identifier: str, literals: Iterable[EnumerationLiteral], documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

392 """ 

393 Initializes an enumerated type definition. 

394 

395 :param identifier: The identifier of a model entity. 

396 :param literals: List of all enumeration literals, in declaration order. 

397 :param documentation: The documentation comment associated with this declaration. 

398 :param parent: The parent model entity of this entity. 

399 """ 

400 super().__init__(identifier, documentation, parent) 

401 

402 self._literals = literalList = [] 

403 if literals is not None: 

404 for literal in literals: 

405 literalList.append(literal) 

406 literal.Parent = self 

407 

408 @readonly 

409 def Literals(self) -> list[EnumerationLiteral]: 

410 """ 

411 Read-only property to access the literals (:attr:`_literals`). 

412 

413 :returns: List of literals. 

414 """ 

415 return self._literals 

416 

417 def Visit(self, visitor: Visitor) -> None: 

418 """ 

419 Walk this enumerated type and its literals with a visitor. 

420 

421 :param visitor: The visitor receiving the events. 

422 """ 

423 visitor.VisitEnumeratedType(self) 

424 for index, literal in enumerate(self._literals): 

425 if index > 0: 

426 visitor.VisitComma(self) 

427 

428 literal.Visit(visitor) 

429 

430 visitor.DepartEnumeratedType(self) 

431 

432 def __str__(self) -> str: 

433 """ 

434 Formats the enumerated type definition. 

435 

436 **Format:** ``state is (idle, run)`` 

437 

438 :returns: Formatted enumerated type definition. 

439 """ 

440 return f"{self._identifier} is ({', '.join(str(l) for l in self._literals)})" 

441 

442 

443@export 

444class IntegerType(RangedScalarType, NumericTypeMixin, DiscreteTypeMixin): 

445 """ 

446 Represents an integer type definition. 

447 

448 An integer type is a named entity (:data:`Identifier`) constrained by a range (:data:`Range`). 

449 

450 .. admonition:: Example 

451 

452 .. code-block:: VHDL 

453 

454 type nibble is range 0 to 15; 

455 -- ^^^^^^ <- Identifier 

456 -- ^^^^^^^ <- Range 

457 """ 

458 def __init__(self, identifier: str, rng: Range, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

459 """ 

460 Initializes an integer type definition. 

461 

462 :param identifier: The identifier of a model entity. 

463 :param rng: The range constraining this scalar type. 

464 :param documentation: The documentation comment associated with this declaration. 

465 :param parent: The parent model entity of this entity. 

466 """ 

467 super().__init__(identifier, rng, documentation, parent) 

468 

469 def Visit(self, visitor: Visitor) -> None: 

470 """ 

471 Walk this integer type and its range with a visitor. 

472 

473 :param visitor: The visitor receiving the events. 

474 """ 

475 visitor.VisitIntegerType(self) 

476 self._range.Visit(visitor) 

477 visitor.DepartIntegerType(self) 

478 

479 def __str__(self) -> str: 

480 """ 

481 Formats the integer type definition. 

482 

483 **Format:** ``byte_count is range 0 to 7`` 

484 

485 :returns: Formatted integer type definition. 

486 """ 

487 return f"{self._identifier} is range {self._range}" 

488 

489 

490@export 

491class RealType(RangedScalarType, NumericTypeMixin): 

492 """ 

493 Represents a floating-point type definition. 

494 

495 A floating-point type is a named entity (:data:`Identifier`) constrained by a range 

496 (:data:`Range`). 

497 

498 .. admonition:: Example 

499 

500 .. code-block:: VHDL 

501 

502 type fraction is range 0.0 to 1.0; 

503 -- ^^^^^^^^ <- Identifier 

504 -- ^^^^^^^^^^ <- Range 

505 """ 

506 def __init__(self, identifier: str, rng: Range, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

507 """ 

508 Initializes a floating-point type definition. 

509 

510 :param identifier: The identifier of a model entity. 

511 :param rng: The range constraining this scalar type. 

512 :param documentation: The documentation comment associated with this declaration. 

513 :param parent: The parent model entity of this entity. 

514 """ 

515 super().__init__(identifier, rng, documentation, parent) 

516 

517 def Visit(self, visitor: Visitor) -> None: 

518 """ 

519 Walk this floating-point type and its range with a visitor. 

520 

521 :param visitor: The visitor receiving the events. 

522 """ 

523 visitor.VisitRealType(self) 

524 self._range.Visit(visitor) 

525 visitor.DepartRealType(self) 

526 

527 def __str__(self) -> str: 

528 """ 

529 Formats the floating-point type definition. 

530 

531 **Format:** ``gain is range 0.0 to 1.0`` 

532 

533 :returns: Formatted floating-point type definition. 

534 """ 

535 return f"{self._identifier} is range {self._range}" 

536 

537 

538@export 

539class PhysicalType(RangedScalarType, NumericTypeMixin): 

540 """ 

541 Represents a physical type definition. 

542 

543 A physical type is a named entity (:data:`Identifier`) constrained by a range (:data:`Range`), and 

544 defines a primary unit (:data:`PrimaryUnit`) plus any number of secondary units 

545 (:data:`SecondaryUnits`). The model holds the secondary units in a list and has no distinct field 

546 per unit, so the markers below name list elements. 

547 

548 .. admonition:: Example 

549 

550 .. code-block:: VHDL 

551 

552 type distance is range 0 to 1000000 units 

553 -- ^^^^^^^^ <- Identifier 

554 -- ^^^^^^^^^^^^ <- Range 

555 um; 

556 --^^^ <- PrimaryUnit 

557 mm = 1000 um; 

558 --^^^^^^^^^^^^^ <- SecondaryUnits[0] 

559 m = 1000 mm; 

560 --^^^^^^^^^^^^^ <- SecondaryUnits[1] 

561 end units; 

562 """ 

563 _primaryUnit: str #: The name of the type's primary unit. 

564 _secondaryUnits: list[tuple[str, PhysicalIntegerLiteral]] #: Secondary units as (name, value) pairs. 

565 

566 def __init__( 

567 self, 

568 identifier: str, 

569 rng: Range, 

570 primaryUnit: str, 

571 units: Iterable[tuple[str, PhysicalIntegerLiteral]], 

572 documentation: Nullable[str] = None, 

573 parent: Nullable[ModelEntity] = None 

574 ) -> None: 

575 """ 

576 Initializes a physical type definition. 

577 

578 :param identifier: The identifier of a model entity. 

579 :param rng: The range constraining this scalar type. 

580 :param primaryUnit: The name of the type's primary unit. 

581 :param units: Iterable of the secondary units as (name, value) pairs. 

582 :param documentation: The documentation comment associated with this declaration. 

583 :param parent: The parent model entity of this entity. 

584 """ 

585 super().__init__(identifier, rng, documentation, parent) 

586 

587 self._primaryUnit = primaryUnit 

588 

589 self._secondaryUnits = secondaryUnits = [] # TODO: convert to dict 

590 for unit in units: 

591 secondaryUnits.append(unit) 

592 unit[1].Parent = self 

593 

594 @readonly 

595 def PrimaryUnit(self) -> str: 

596 """ 

597 Read-only property to access the primary unit (:attr:`_primaryUnit`). 

598 

599 :returns: The primary unit. 

600 """ 

601 return self._primaryUnit 

602 

603 @readonly 

604 def SecondaryUnits(self) -> list[tuple[str, PhysicalIntegerLiteral]]: 

605 """ 

606 Read-only property to access the secondary units (:attr:`_secondaryUnits`). 

607 

608 :returns: List of secondary units. 

609 """ 

610 return self._secondaryUnits 

611 

612 def Visit(self, visitor: Visitor) -> None: 

613 """ 

614 Walk this physical type, its range and its secondary units with a visitor. 

615 

616 :param visitor: The visitor receiving the events. 

617 """ 

618 visitor.VisitPhysicalType(self) 

619 self._range.Visit(visitor) 

620 visitor.VisitUnits(self) 

621 for identifier, value in self._secondaryUnits: 

622 visitor.VisitSecondaryUnitDeclaration(self, identifier) 

623 value.Visit(visitor) 

624 visitor.DepartSecondaryUnitDeclaration(self, identifier) 

625 

626 visitor.DepartPhysicalType(self) 

627 

628 def __str__(self) -> str: 

629 """ 

630 Formats the physical type definition. 

631 

632 **Format:** ``distance is range 0 to 1000 units um; mm = 1000 um;`` 

633 

634 :returns: Formatted physical type definition. 

635 """ 

636 return f"{self._identifier} is range {self._range} units {self._primaryUnit}; {'; '.join(su + ' = ' + str(pu) for su, pu in self._secondaryUnits)};" 

637 

638 

639@export 

640@abstractclass 

641class CompositeType(FullType): 

642 """ 

643 Represents a base-class for all composite types: array and record types. 

644 

645 .. seealso:: 

646 

647 * :class:`Array type <pyVHDLModel.Type.ArrayType>` 

648 * :class:`Record type <pyVHDLModel.Type.RecordType>` 

649 """ 

650 

651 

652@export 

653class ArrayType(CompositeType): 

654 """ 

655 Represents an array type definition. 

656 

657 An array type is a named entity (:data:`Identifier`) defining one or more index ranges 

658 (:data:`Dimensions`) and the subtype of its elements (:data:`ElementType`). 

659 

660 .. admonition:: Example 

661 

662 One dimension: 

663 

664 .. code-block:: VHDL 

665 

666 type memory is array (0 to 255) of bit_vector(7 downto 0); 

667 -- ^^^^^^ <- Identifier 

668 -- ^^^^^^^^ <- Dimensions 

669 -- ^^^^^^^^^^^^^^^^^^^^^^ <- ElementType 

670 

671 Two dimensions, both unconstrained: 

672 

673 .. code-block:: VHDL 

674 

675 type matrix is array (natural range <>, natural range <>) of bit; 

676 -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- Dimensions 

677 

678 .. seealso:: 

679 

680 * :class:`Reference to a constrained array subtype <pyVHDLModel.Symbol.ConstrainedArraySubtypeSymbol>` 

681 """ 

682 _dimensions: list[Range] #: List of all index ranges, one per dimension. 

683 _elementType: Symbol #: Reference to the subtype of the array's elements. 

684 

685 def __init__( 

686 self, 

687 identifier: str, 

688 indices: Iterable, 

689 elementSubtype: Symbol, 

690 documentation: Nullable[str] = None, 

691 parent: Nullable[ModelEntity] = None 

692 ) -> None: 

693 """ 

694 Initializes an array type definition. 

695 

696 :param identifier: The identifier of a model entity. 

697 :param indices: List of all index ranges, one per dimension. 

698 :param elementSubtype: Reference to the subtype of the array's elements. 

699 :param documentation: The documentation comment associated with this declaration. 

700 :param parent: The parent model entity of this entity. 

701 """ 

702 super().__init__(identifier, documentation, parent) 

703 

704 self._dimensions = dimensions = [] 

705 for index in indices: 

706 dimensions.append(index) 

707 # index.Parent = self # FIXME: indices are provided as empty list 

708 

709 self._elementType = elementSubtype 

710 # elementSubtype.Parent = self # FIXME: subtype is provided as None 

711 

712 @readonly 

713 def Dimensions(self) -> list[Range]: 

714 """ 

715 Read-only property to access the dimensions (:attr:`_dimensions`). 

716 

717 :returns: List of dimensions. 

718 """ 

719 return self._dimensions 

720 

721 @readonly 

722 def ElementType(self) -> Symbol: 

723 """ 

724 Read-only property to access the element type (:attr:`_elementType`). 

725 

726 :returns: The element type. 

727 """ 

728 return self._elementType 

729 

730 def Visit(self, visitor: Visitor) -> None: 

731 """ 

732 Walk this array type, its index ranges and its element subtype with a visitor. 

733 

734 :param visitor: The visitor receiving the events. 

735 """ 

736 visitor.VisitArrayType(self) 

737 visitor.VisitIndexConstraint(self) 

738 for index, dimension in enumerate(self._dimensions): 

739 if index > 0: 

740 visitor.VisitComma(self) 

741 

742 dimension.Visit(visitor) 

743 if isinstance(dimension, SimpleSubtypeSymbol): 

744 visitor.VisitBox(self) 

745 

746 visitor.DepartIndexConstraint(self) 

747 visitor.VisitOf(self) 

748 self._elementType.Visit(visitor) 

749 visitor.DepartArrayType(self) 

750 

751 def __str__(self) -> str: 

752 """ 

753 Formats the array type definition. 

754 

755 **Format:** ``memory is array(0 to 7) of bit`` 

756 

757 :returns: Formatted array type definition. 

758 """ 

759 return f"{self._identifier} is array({'; '.join(str(r) for r in self._dimensions)}) of {self._elementType}" 

760 

761 

762@export 

763class RecordTypeElement(ModelEntity, MultipleNamedEntityMixin, DocumentedEntityMixin): 

764 """ 

765 Represents one element declaration inside a record type definition. 

766 

767 A single declaration may name several elements at once, hence :data:`Identifiers` rather than one 

768 identifier. All of them share the same subtype (:data:`Subtype`). 

769 

770 .. admonition:: Example 

771 

772 .. code-block:: VHDL 

773 

774 type frame is record 

775 --! The first fields. 

776 --^^^^^^^^^^^^^^^^^^^^^ <- Documentation 

777 a, b : bit; 

778 --^^^^ <- Identifiers 

779 -- ^^^ <- Subtype 

780 end record; 

781 

782 .. seealso:: 

783 

784 * :class:`Record type <pyVHDLModel.Type.RecordType>` 

785 """ 

786 _subtype: Symbol #: Reference to the subtype shared by all identifiers of this element declaration. 

787 

788 def __init__( 

789 self, 

790 identifiers: Iterable[str], 

791 subtype: Symbol, 

792 documentation: Nullable[str] = None, 

793 parent: Nullable[ModelEntity] = None 

794 ) -> None: 

795 """ 

796 Initializes a record type element. 

797 

798 :param identifiers: A list of identifiers. 

799 :param subtype: Reference to the subtype shared by all identifiers of this element declaration. 

800 :param documentation: The documentation comment associated with this declaration. 

801 :param parent: The parent model entity of this entity. 

802 """ 

803 super().__init__(parent) 

804 MultipleNamedEntityMixin.__init__(self, identifiers) 

805 DocumentedEntityMixin.__init__(self, documentation) 

806 

807 self._subtype = subtype 

808 subtype.Parent = self 

809 

810 @readonly 

811 def Subtype(self) -> Symbol: 

812 """ 

813 Read-only property to access the subtype (:attr:`_subtype`). 

814 

815 :returns: The subtype. 

816 """ 

817 return self._subtype 

818 

819 def Copy(self) -> Self: 

820 """ 

821 Create a copy of this record type element. 

822 

823 The copy has no parent. Its subtype is a copy of this element's subtype. 

824 

825 :returns: The new record type element. 

826 """ 

827 return self.__class__(self._identifiers, self._subtype.Copy(), self._documentation) 

828 

829 def Visit(self, visitor: Visitor) -> None: 

830 """ 

831 Walk this record element declaration and its subtype with a visitor. 

832 

833 :param visitor: The visitor receiving the events. 

834 """ 

835 visitor.VisitRecordTypeElement(self) 

836 self._subtype.Visit(visitor) 

837 visitor.DepartRecordTypeElement(self) 

838 

839 def __str__(self) -> str: 

840 """ 

841 Formats the record element declaration. 

842 

843 **Format:** ``a, b : bit`` 

844 

845 :returns: Formatted record element declaration. 

846 """ 

847 return f"{', '.join(self._identifiers)} : {self._subtype}" 

848 

849 

850@export 

851class RecordType(CompositeType): 

852 """ 

853 Represents a record type definition. 

854 

855 A record type is a named entity (:data:`Identifier`) holding its element declarations 

856 (:data:`Elements`) in declaration order. The model holds them in a list and has no distinct 

857 field per element, so the markers below name list elements. 

858 

859 .. admonition:: Example 

860 

861 .. code-block:: VHDL 

862 

863 type frame is record 

864 -- ^^^^^ <- Identifier 

865 a, b : bit; 

866 --^^^^^^^^^^^^^^ <- Elements[0] 

867 payload : bit_vector(31 downto 0); 

868 --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- Elements[1] 

869 end record; 

870 

871 .. seealso:: 

872 

873 * :class:`Record element <pyVHDLModel.Type.RecordTypeElement>` 

874 * :class:`Reference to a record element <pyVHDLModel.Symbol.RecordElementSymbol>` 

875 """ 

876 _elements: list[RecordTypeElement] #: List of all element declarations, in declaration order. 

877 

878 def __init__(self, identifier: str, elements: Nullable[Iterable[RecordTypeElement]] = None, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

879 """ 

880 Initializes a record type definition. 

881 

882 :param identifier: The identifier of a model entity. 

883 :param elements: List of all element declarations, in declaration order. 

884 :param documentation: The documentation comment associated with this declaration. 

885 :param parent: The parent model entity of this entity. 

886 """ 

887 super().__init__(identifier, documentation, parent) 

888 

889 self._elements = elementList = [] # TODO: convert to dict 

890 if elements is not None: 

891 for element in elements: 

892 elementList.append(element) 

893 element.Parent = self 

894 

895 @readonly 

896 def Elements(self) -> list[RecordTypeElement]: 

897 """ 

898 Read-only property to access the elements (:attr:`_elements`). 

899 

900 :returns: List of elements. 

901 """ 

902 return self._elements 

903 

904 def Visit(self, visitor: Visitor) -> None: 

905 """ 

906 Walk this record type and its element declarations with a visitor. 

907 

908 :param visitor: The visitor receiving the events. 

909 """ 

910 visitor.VisitRecordType(self) 

911 for element in self._elements: 

912 element.Visit(visitor) 

913 

914 visitor.DepartRecordType(self) 

915 

916 def __str__(self) -> str: 

917 """ 

918 Formats the record type definition. 

919 

920 **Format:** ``frame is record a : bit;`` 

921 

922 :returns: Formatted record type definition. 

923 """ 

924 return f"{self._identifier} is record {'; '.join(str(re) for re in self._elements)};" 

925 

926 

927@export 

928class ProtectedType(FullType, ProtectedTypeDeclarationRegionMixin, WithoutStatementsMixin): 

929 """ 

930 Represents a protected type declaration. 

931 

932 A protected type is a named entity (:data:`Identifier`) exposing only its methods 

933 (:data:`Methods`). The implementation lives in a separate :class:`ProtectedTypeBody`. 

934 

935 It is a declarative region and owns a namespace. VHDL's ``protected_type_declarative_item`` admits 

936 subprogram declarations and nothing else - the narrowest declarative region in the language - so 

937 :data:`DeclaredItems` and :data:`Methods` hold the same items. The markers below name list elements, 

938 because the model has no distinct field per method. 

939 

940 .. admonition:: Example 

941 

942 .. code-block:: VHDL 

943 

944 type counter is protected 

945 -- ^^^^^^^ <- Identifier 

946 procedure increment; 

947 --^^^^^^^^^^^^^^^^^^^^ <- Methods[0] 

948 impure function value return natural; 

949 --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- Methods[1] 

950 end protected; 

951 

952 .. seealso:: 

953 

954 * :class:`Protected type body <pyVHDLModel.Type.ProtectedTypeBody>` 

955 * :class:`Method of a protected type <pyVHDLModel.Subprogram.ProcedureMethod>` 

956 """ 

957 def __init__(self, identifier: str, declaredItems: Union[list, Iterator] = None, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

958 """ 

959 Initializes a protected type declaration. 

960 

961 :param identifier: The identifier of a model entity. 

962 :param declaredItems: All items declared by this protected type; only subprograms are legal. 

963 :param documentation: The documentation comment associated with this declaration. 

964 :param parent: The parent model entity of this entity. 

965 """ 

966 super().__init__(identifier, documentation, parent) 

967 ProtectedTypeDeclarationRegionMixin.__init__(self, self._normalizedIdentifier, declaredItems) 

968 

969 def Visit(self, visitor: Visitor) -> None: 

970 """ 

971 Walk this protected type declaration and its methods with a visitor. 

972 

973 :param visitor: The visitor receiving the events. 

974 """ 

975 visitor.VisitProtectedType(self) 

976 self._VisitDeclaredItems(visitor) 

977 visitor.DepartProtectedType(self) 

978 

979 @readonly 

980 def Methods(self) -> list[Union[Procedure, Function]]: 

981 """ 

982 Read-only property to access the declared methods, in declaration order. 

983 

984 A protected type declares nothing but subprograms, so this is every declared item 

985 (:attr:`_declaredItems`). It is kept as a named view because "method" is the VHDL term for a 

986 protected type's subprograms. 

987 

988 :returns: List of methods, in declaration order. 

989 """ 

990 from pyVHDLModel.Subprogram import Function, Procedure 

991 

992 return [item for item in self._declaredItems if isinstance(item, (Function, Procedure))] 

993 

994 

995@export 

996class ProtectedTypeBody(FullType, SequentialDeclarationRegionMixin, WithoutStatementsMixin): 

997 """ 

998 Represents a protected type body. 

999 

1000 A protected type body implements the methods (:data:`Methods`) declared by the 

1001 :class:`ProtectedType` of the same identifier (:data:`Identifier`). 

1002 

1003 It is a declarative region and owns a namespace. Its declarative part matches a subprogram's, so it 

1004 shares :class:`~pyVHDLModel.Regions.SequentialDeclarationRegionMixin` with subprogram bodies. 

1005 Everything declared is available as :data:`DeclaredItems`; :data:`Methods` is its subprogram subset. 

1006 

1007 .. admonition:: Example 

1008 

1009 .. code-block:: VHDL 

1010 

1011 type counter is protected body 

1012 -- ^^^^^^^ <- Identifier 

1013 variable count : natural := 0; 

1014 procedure increment is 

1015 --^^^^^^^^^^^^^^^^^^^^^^ <- Methods[0] 

1016 begin 

1017 count := count + 1; 

1018 end procedure; 

1019 end protected body; 

1020 

1021 .. seealso:: 

1022 

1023 * :class:`Protected type declaration <pyVHDLModel.Type.ProtectedType>` 

1024 """ 

1025 def __init__(self, identifier: str, declaredItems: Union[list, Iterator] = None, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

1026 """ 

1027 Initializes a protected type body. 

1028 

1029 :param identifier: The identifier of a model entity. 

1030 :param declaredItems: Iterable of all items declared in this body. 

1031 :param documentation: The documentation comment associated with this declaration. 

1032 :param parent: The parent model entity of this entity. 

1033 """ 

1034 super().__init__(identifier, documentation, parent) 

1035 SequentialDeclarationRegionMixin.__init__(self, self._normalizedIdentifier, declaredItems) 

1036 

1037 def Visit(self, visitor: Visitor) -> None: 

1038 """ 

1039 Walk this protected type body and its declared items with a visitor. 

1040 

1041 :param visitor: The visitor receiving the events. 

1042 """ 

1043 visitor.VisitProtectedTypeBody(self) 

1044 self._VisitDeclaredItems(visitor) 

1045 visitor.DepartProtectedTypeBody(self) 

1046 

1047 # FIXME: needs to be declared items or so 

1048 @readonly 

1049 def Methods(self) -> list[Union[Procedure, Function]]: 

1050 """ 

1051 Read-only property to access the implemented methods, in declaration order. 

1052 

1053 A protected type body may also declare variables, types, subtypes, aliases and files, so this is 

1054 the subprogram subset of :attr:`_declaredItems` rather than all of them. 

1055 

1056 :returns: List of methods, in declaration order. 

1057 """ 

1058 from pyVHDLModel.Subprogram import Function, Procedure 

1059 

1060 return [item for item in self._declaredItems if isinstance(item, (Function, Procedure))] 

1061 

1062 

1063@export 

1064class AccessType(FullType): 

1065 """ 

1066 Represents an access type definition. 

1067 

1068 An access type is a named entity (:data:`Identifier`) pointing at values of its designated subtype 

1069 (:data:`DesignatedSubtype`). 

1070 

1071 .. admonition:: Example 

1072 

1073 .. code-block:: VHDL 

1074 

1075 type ptr is access integer; 

1076 -- ^^^ <- Identifier 

1077 -- ^^^^^^^ <- DesignatedSubtype 

1078 """ 

1079 _designatedSubtype: Symbol #: Reference to the subtype the access values designate. 

1080 

1081 def __init__(self, identifier: str, designatedSubtype: Symbol, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

1082 """ 

1083 Initializes an access type definition. 

1084 

1085 :param identifier: The identifier of a model entity. 

1086 :param designatedSubtype: Reference to the subtype the access values designate. 

1087 :param documentation: The documentation comment associated with this declaration. 

1088 :param parent: The parent model entity of this entity. 

1089 """ 

1090 super().__init__(identifier, documentation, parent) 

1091 

1092 self._designatedSubtype = designatedSubtype 

1093 designatedSubtype.Parent = self 

1094 

1095 @readonly 

1096 def DesignatedSubtype(self) -> Symbol: 

1097 """ 

1098 Read-only property to access the designated subtype (:attr:`_designatedSubtype`). 

1099 

1100 :returns: The designated subtype. 

1101 """ 

1102 return self._designatedSubtype 

1103 

1104 def Visit(self, visitor: Visitor) -> None: 

1105 """ 

1106 Walk this access type and its designated subtype with a visitor. 

1107 

1108 :param visitor: The visitor receiving the events. 

1109 """ 

1110 visitor.VisitAccessType(self) 

1111 self._designatedSubtype.Visit(visitor) 

1112 visitor.DepartAccessType(self) 

1113 

1114 def __str__(self) -> str: 

1115 """ 

1116 Formats the access type definition. 

1117 

1118 **Format:** ``ptr is access node`` 

1119 

1120 :returns: Formatted access type definition. 

1121 """ 

1122 return f"{self._identifier} is access {self._designatedSubtype}" 

1123 

1124 

1125@export 

1126class FileType(FullType): 

1127 """ 

1128 Represents a file type definition. 

1129 

1130 A file type is a named entity (:data:`Identifier`) holding values of its designated subtype 

1131 (:data:`DesignatedSubtype`). 

1132 

1133 .. admonition:: Example 

1134 

1135 .. code-block:: VHDL 

1136 

1137 type text_file is file of string; 

1138 -- ^^^^^^^^^ <- Identifier 

1139 -- ^^^^^^ <- DesignatedSubtype 

1140 """ 

1141 _designatedSubtype: Symbol #: Reference to the subtype of the values stored in the file. 

1142 

1143 def __init__(self, identifier: str, designatedSubtype: Symbol, documentation: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

1144 """ 

1145 Initializes a file type definition. 

1146 

1147 :param identifier: The identifier of a model entity. 

1148 :param designatedSubtype: Reference to the subtype of the values stored in the file. 

1149 :param documentation: The documentation comment associated with this declaration. 

1150 :param parent: The parent model entity of this entity. 

1151 """ 

1152 super().__init__(identifier, documentation, parent) 

1153 

1154 self._designatedSubtype = designatedSubtype 

1155 designatedSubtype.Parent = self 

1156 

1157 @readonly 

1158 def DesignatedSubtype(self) -> Symbol: 

1159 """ 

1160 Read-only property to access the designated subtype (:attr:`_designatedSubtype`). 

1161 

1162 :returns: The designated subtype. 

1163 """ 

1164 return self._designatedSubtype 

1165 

1166 def Visit(self, visitor: Visitor) -> None: 

1167 """ 

1168 Walk this file type and its designated subtype with a visitor. 

1169 

1170 :param visitor: The visitor receiving the events. 

1171 """ 

1172 visitor.VisitFileType(self) 

1173 self._designatedSubtype.Visit(visitor) 

1174 visitor.DepartFileType(self) 

1175 

1176 def __str__(self) -> str: 

1177 """ 

1178 Formats the file type definition. 

1179 

1180 **Format:** ``ft is file of character`` 

1181 

1182 :returns: Formatted file type definition. 

1183 """ 

1184 return f"{self._identifier} is file of {self._designatedSubtype}"