Coverage for pyVHDLModel/Type.py: 99%

194 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-11 23:50 +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 typing import Union, List, Iterator, Iterable, Tuple, Optional as Nullable, Dict, Mapping 

38 

39from pyTooling.Decorators import export, readonly 

40from pyTooling.MetaClasses import ExtendedType 

41from pyTooling.Graph import Vertex 

42 

43from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin, ExpressionUnion, Range 

44from pyVHDLModel.Symbol import Symbol 

45from pyVHDLModel.Expression import EnumerationLiteral, PhysicalIntegerLiteral 

46from pyVHDLModel.Regions import ProtectedTypeDeclarationRegionMixin, SequentialDeclarationRegionMixin 

47 

48 

49@export 

50class BaseType(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): 

51 """ 

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

53 

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

55 documentation (:data:`Documentation`). 

56 

57 .. seealso:: 

58 

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

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

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

62 """ 

63 

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

65 

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

67 """ 

68 Initializes underlying ``BaseType``. 

69 

70 :param identifier: Name of the type. 

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

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

73 """ 

74 super().__init__(parent) 

75 NamedEntityMixin.__init__(self, identifier) 

76 DocumentedEntityMixin.__init__(self, documentation) 

77 

78 self._objectVertex = None 

79 

80 def __str__(self) -> str: 

81 """ 

82 Formats the type declaration. 

83 

84 **Format:** ``type myType`` 

85 

86 :returns: Formatted type declaration. 

87 """ 

88 return f"type {self._identifier}" 

89 

90 

91@export 

92class Type(BaseType): 

93 """ 

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

95 

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

97 introduces a type name without defining the type itself. 

98 

99 .. seealso:: 

100 

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

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

103 """ 

104 pass 

105 

106 

107@export 

108class AnonymousType(Type): 

109 """ 

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

111 

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

113 definition follows later in the same declarative part. 

114 

115 .. admonition:: Example 

116 

117 .. code-block:: VHDL 

118 

119 type node; 

120 -- ^^^^ <- Identifier 

121 type ptr is access node; 

122 type node is record 

123 value : integer; 

124 nextNode : ptr; 

125 end record; 

126 """ 

127 pass 

128 

129 

130@export 

131class FullType(BaseType): 

132 """ 

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

134 

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

136 subtype in ``Subtypes``. 

137 

138 .. seealso:: 

139 

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

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

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

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

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

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

146 """ 

147 pass 

148 

149 

150@export 

151class Subtype(BaseType): 

152 """ 

153 Represents a subtype declaration. 

154 

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

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

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

158 

159 .. admonition:: Example 

160 

161 Without a constraint: 

162 

163 .. code-block:: VHDL 

164 

165 subtype byte is bit_vector; 

166 -- ^^^^ <- Identifier 

167 -- ^^^^^^^^^^ <- Type 

168 

169 With a constraint: 

170 

171 .. code-block:: VHDL 

172 

173 subtype nibble is bit_vector(3 downto 0); 

174 -- ^^^^^^^^^^^^ <- Range 

175 

176 With a resolution function: 

177 

178 .. code-block:: VHDL 

179 

180 subtype wired is resolved std_ulogic; 

181 -- ^^^^^^^^ <- ResolutionFunction 

182 

183 .. seealso:: 

184 

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

186 """ 

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

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

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

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

191 

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

193 """ 

194 Initializes a subtype declaration. 

195 

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

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

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

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

200 """ 

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

202 

203 self._type = symbol 

204 self._baseType = None 

205 self._range = None 

206 self._resolutionFunction = None 

207 

208 @readonly 

209 def Type(self) -> Symbol: 

210 """ 

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

212 

213 :returns: The type. 

214 """ 

215 return self._type 

216 

217 @readonly 

218 def BaseType(self) -> BaseType: 

219 """ 

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

221 

222 :returns: The base type. 

223 """ 

224 return self._baseType 

225 

226 @readonly 

227 def Range(self) -> Range: 

228 """ 

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

230 

231 :returns: The range. 

232 """ 

233 return self._range 

234 

235 @readonly 

236 def ResolutionFunction(self) -> 'Function': 

237 """ 

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

239 

240 :returns: The resolution function. 

241 """ 

242 return self._resolutionFunction 

243 

244 def __str__(self) -> str: 

245 """ 

246 Formats the subtype declaration. 

247 

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

249 

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

251 

252 :returns: Formatted subtype declaration. 

253 """ 

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

255 

256 

257@export 

258class ScalarType(FullType): 

259 """ 

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

261 

262 .. seealso:: 

263 

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

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

266 """ 

267 

268 

269@export 

270class RangedScalarType(ScalarType): 

271 """ 

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

273 

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

275 derives from :class:`ScalarType` directly. 

276 

277 .. seealso:: 

278 

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

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

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

282 """ 

283 

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

285 

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

287 """ 

288 Initialize a scalar type with a range. 

289 

290 :param identifier: The type's identifier. 

291 :param rng: The type's range. 

292 :param documentation: The type's documentation. 

293 :param parent: The parent model entity. 

294 """ 

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

296 self._range = rng 

297 

298 @readonly 

299 def Range(self) -> Range: 

300 """ 

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

302 

303 :returns: The range. 

304 """ 

305 return self._range 

306 

307 

308@export 

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

310 """ 

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

312 

313 .. seealso:: 

314 

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

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

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

318 """ 

319 

320 def __init__(self) -> None: 

321 """ 

322 Initializes a numeric type. 

323 """ 

324 pass 

325 

326 

327@export 

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

329 """ 

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

331 

332 .. seealso:: 

333 

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

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

336 """ 

337 

338 def __init__(self) -> None: 

339 """ 

340 Initializes a discrete type. 

341 """ 

342 pass 

343 

344 

345@export 

346class EnumeratedType(ScalarType, DiscreteTypeMixin): 

347 """ 

348 Represents an enumerated type definition. 

349 

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

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

352 

353 .. admonition:: Example 

354 

355 .. code-block:: VHDL 

356 

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

358 -- ^^^^^ <- Identifier 

359 -- ^^^^^^^^^^^^^^^^^^^ <- Literals 

360 """ 

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

362 

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

364 """ 

365 Initializes an enumerated type definition. 

366 

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

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

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

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

371 """ 

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

373 

374 self._literals = [] 

375 if literals is not None: 

376 for literal in literals: 

377 self._literals.append(literal) 

378 literal.Parent = self 

379 

380 @readonly 

381 def Literals(self) -> List[EnumerationLiteral]: 

382 """ 

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

384 

385 :returns: List of literals. 

386 """ 

387 return self._literals 

388 

389 def __str__(self) -> str: 

390 """ 

391 Formats the enumerated type definition. 

392 

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

394 

395 :returns: Formatted enumerated type definition. 

396 """ 

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

398 

399 

400@export 

401class IntegerType(RangedScalarType, NumericTypeMixin, DiscreteTypeMixin): 

402 """ 

403 Represents an integer type definition. 

404 

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

406 

407 .. admonition:: Example 

408 

409 .. code-block:: VHDL 

410 

411 type nibble is range 0 to 15; 

412 -- ^^^^^^ <- Identifier 

413 -- ^^^^^^^ <- Range 

414 """ 

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

416 """ 

417 Initializes an integer type definition. 

418 

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

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

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

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

423 """ 

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

425 

426 def __str__(self) -> str: 

427 """ 

428 Formats the integer type definition. 

429 

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

431 

432 :returns: Formatted integer type definition. 

433 """ 

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

435 

436 

437@export 

438class RealType(RangedScalarType, NumericTypeMixin): 

439 """ 

440 Represents a floating-point type definition. 

441 

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

443 (:data:`Range`). 

444 

445 .. admonition:: Example 

446 

447 .. code-block:: VHDL 

448 

449 type fraction is range 0.0 to 1.0; 

450 -- ^^^^^^^^ <- Identifier 

451 -- ^^^^^^^^^^ <- Range 

452 """ 

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

454 """ 

455 Initializes a floating-point type definition. 

456 

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

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

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

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

461 """ 

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

463 

464 def __str__(self) -> str: 

465 """ 

466 Formats the floating-point type definition. 

467 

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

469 

470 :returns: Formatted floating-point type definition. 

471 """ 

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

473 

474 

475@export 

476class PhysicalType(RangedScalarType, NumericTypeMixin): 

477 """ 

478 Represents a physical type definition. 

479 

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

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

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

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

484 

485 .. admonition:: Example 

486 

487 .. code-block:: VHDL 

488 

489 type distance is range 0 to 1000000 units 

490 -- ^^^^^^^^ <- Identifier 

491 -- ^^^^^^^^^^^^ <- Range 

492 um; 

493 --^^^ <- PrimaryUnit 

494 mm = 1000 um; 

495 --^^^^^^^^^^^^^ <- SecondaryUnits[0] 

496 m = 1000 mm; 

497 --^^^^^^^^^^^^^ <- SecondaryUnits[1] 

498 end units; 

499 """ 

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

501 _secondaryUnits: List[Tuple[str, PhysicalIntegerLiteral]] #: Secondary units as (name, value) pairs. 

502 

503 def __init__( 

504 self, 

505 identifier: str, 

506 rng: Range, 

507 primaryUnit: str, 

508 units: Iterable[Tuple[str, PhysicalIntegerLiteral]], 

509 documentation: Nullable[str] = None, 

510 parent: Nullable[ModelEntity] = None 

511 ) -> None: 

512 """ 

513 Initializes a physical type definition. 

514 

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

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

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

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

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

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

521 """ 

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

523 

524 self._primaryUnit = primaryUnit 

525 

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

527 for unit in units: 

528 self._secondaryUnits.append(unit) 

529 unit[1].Parent = self 

530 

531 @readonly 

532 def PrimaryUnit(self) -> str: 

533 """ 

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

535 

536 :returns: The primary unit. 

537 """ 

538 return self._primaryUnit 

539 

540 @readonly 

541 def SecondaryUnits(self) -> List[Tuple[str, PhysicalIntegerLiteral]]: 

542 """ 

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

544 

545 :returns: List of secondary units. 

546 """ 

547 return self._secondaryUnits 

548 

549 def __str__(self) -> str: 

550 """ 

551 Formats the physical type definition. 

552 

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

554 

555 :returns: Formatted physical type definition. 

556 """ 

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

558 

559 

560@export 

561class CompositeType(FullType): 

562 """ 

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

564 

565 .. seealso:: 

566 

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

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

569 """ 

570 

571 

572@export 

573class ArrayType(CompositeType): 

574 """ 

575 Represents an array type definition. 

576 

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

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

579 

580 .. admonition:: Example 

581 

582 One dimension: 

583 

584 .. code-block:: VHDL 

585 

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

587 -- ^^^^^^ <- Identifier 

588 -- ^^^^^^^^ <- Dimensions 

589 -- ^^^^^^^^^^^^^^^^^^^^^^ <- ElementType 

590 

591 Two dimensions, both unconstrained: 

592 

593 .. code-block:: VHDL 

594 

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

596 -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- Dimensions 

597 

598 .. seealso:: 

599 

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

601 """ 

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

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

604 

605 def __init__( 

606 self, 

607 identifier: str, 

608 indices: Iterable, 

609 elementSubtype: Symbol, 

610 documentation: Nullable[str] = None, 

611 parent: Nullable[ModelEntity] = None 

612 ) -> None: 

613 """ 

614 Initializes an array type definition. 

615 

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

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

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

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

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

621 """ 

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

623 

624 self._dimensions = [] 

625 for index in indices: 

626 self._dimensions.append(index) 

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

628 

629 self._elementType = elementSubtype 

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

631 

632 @readonly 

633 def Dimensions(self) -> List[Range]: 

634 """ 

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

636 

637 :returns: List of dimensions. 

638 """ 

639 return self._dimensions 

640 

641 @readonly 

642 def ElementType(self) -> Symbol: 

643 """ 

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

645 

646 :returns: The element type. 

647 """ 

648 return self._elementType 

649 

650 def __str__(self) -> str: 

651 """ 

652 Formats the array type definition. 

653 

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

655 

656 :returns: Formatted array type definition. 

657 """ 

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

659 

660 

661@export 

662class RecordTypeElement(ModelEntity, MultipleNamedEntityMixin, DocumentedEntityMixin): 

663 """ 

664 Represents one element declaration inside a record type definition. 

665 

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

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

668 

669 .. admonition:: Example 

670 

671 .. code-block:: VHDL 

672 

673 type frame is record 

674 --! The first fields. 

675 --^^^^^^^^^^^^^^^^^^^^^ <- Documentation 

676 a, b : bit; 

677 --^^^^ <- Identifiers 

678 -- ^^^ <- Subtype 

679 end record; 

680 

681 .. seealso:: 

682 

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

684 """ 

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

686 

687 def __init__( 

688 self, 

689 identifiers: Iterable[str], 

690 subtype: Symbol, 

691 documentation: Nullable[str] = None, 

692 parent: Nullable[ModelEntity] = None 

693 ) -> None: 

694 """ 

695 Initializes a record type element. 

696 

697 :param identifiers: A list of identifiers. 

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

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

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

701 """ 

702 super().__init__(parent) 

703 MultipleNamedEntityMixin.__init__(self, identifiers) 

704 DocumentedEntityMixin.__init__(self, documentation) 

705 

706 self._subtype = subtype 

707 subtype.Parent = self 

708 

709 @readonly 

710 def Subtype(self) -> Symbol: 

711 """ 

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

713 

714 :returns: The subtype. 

715 """ 

716 return self._subtype 

717 

718 def __str__(self) -> str: 

719 """ 

720 Formats the record element declaration. 

721 

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

723 

724 :returns: Formatted record element declaration. 

725 """ 

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

727 

728 

729@export 

730class RecordType(CompositeType): 

731 """ 

732 Represents a record type definition. 

733 

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

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

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

737 

738 .. admonition:: Example 

739 

740 .. code-block:: VHDL 

741 

742 type frame is record 

743 -- ^^^^^ <- Identifier 

744 a, b : bit; 

745 --^^^^^^^^^^^^^^ <- Elements[0] 

746 payload : bit_vector(31 downto 0); 

747 --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- Elements[1] 

748 end record; 

749 

750 .. seealso:: 

751 

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

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

754 """ 

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

756 

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

758 """ 

759 Initializes a record type definition. 

760 

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

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

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

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

765 """ 

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

767 

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

769 if elements is not None: 

770 for element in elements: 

771 self._elements.append(element) 

772 element.Parent = self 

773 

774 @readonly 

775 def Elements(self) -> List[RecordTypeElement]: 

776 """ 

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

778 

779 :returns: List of elements. 

780 """ 

781 return self._elements 

782 

783 def __str__(self) -> str: 

784 """ 

785 Formats the record type definition. 

786 

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

788 

789 :returns: Formatted record type definition. 

790 """ 

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

792 

793 

794@export 

795class ProtectedType(FullType, ProtectedTypeDeclarationRegionMixin): 

796 """ 

797 Represents a protected type declaration. 

798 

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

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

801 

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

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

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

805 because the model has no distinct field per method. 

806 

807 .. admonition:: Example 

808 

809 .. code-block:: VHDL 

810 

811 type counter is protected 

812 -- ^^^^^^^ <- Identifier 

813 procedure increment; 

814 --^^^^^^^^^^^^^^^^^^^^ <- Methods[0] 

815 impure function value return natural; 

816 --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- Methods[1] 

817 end protected; 

818 

819 .. seealso:: 

820 

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

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

823 """ 

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

825 """ 

826 Initializes a protected type declaration. 

827 

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

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

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

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

832 """ 

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

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

835 

836 @readonly 

837 def Methods(self) -> List[Union['Procedure', 'Function']]: 

838 """ 

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

840 

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

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

843 protected type's subprograms. 

844 

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

846 """ 

847 from pyVHDLModel.Subprogram import Function, Procedure 

848 

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

850 

851 

852@export 

853class ProtectedTypeBody(FullType, SequentialDeclarationRegionMixin): 

854 """ 

855 Represents a protected type body. 

856 

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

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

859 

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

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

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

863 

864 .. admonition:: Example 

865 

866 .. code-block:: VHDL 

867 

868 type counter is protected body 

869 -- ^^^^^^^ <- Identifier 

870 variable count : natural := 0; 

871 procedure increment is 

872 --^^^^^^^^^^^^^^^^^^^^^^ <- Methods[0] 

873 begin 

874 count := count + 1; 

875 end procedure; 

876 end protected body; 

877 

878 .. seealso:: 

879 

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

881 """ 

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

883 """ 

884 Initializes a protected type body. 

885 

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

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

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

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

890 """ 

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

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

893 

894 # FIXME: needs to be declared items or so 

895 @readonly 

896 def Methods(self) -> List[Union['Procedure', 'Function']]: 

897 """ 

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

899 

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

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

902 

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

904 """ 

905 from pyVHDLModel.Subprogram import Function, Procedure 

906 

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

908 

909 

910@export 

911class AccessType(FullType): 

912 """ 

913 Represents an access type definition. 

914 

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

916 (:data:`DesignatedSubtype`). 

917 

918 .. admonition:: Example 

919 

920 .. code-block:: VHDL 

921 

922 type ptr is access integer; 

923 -- ^^^ <- Identifier 

924 -- ^^^^^^^ <- DesignatedSubtype 

925 """ 

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

927 

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

929 """ 

930 Initializes an access type definition. 

931 

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

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

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

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

936 """ 

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

938 

939 self._designatedSubtype = designatedSubtype 

940 designatedSubtype.Parent = self 

941 

942 @readonly 

943 def DesignatedSubtype(self) -> Symbol: 

944 """ 

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

946 

947 :returns: The designated subtype. 

948 """ 

949 return self._designatedSubtype 

950 

951 def __str__(self) -> str: 

952 """ 

953 Formats the access type definition. 

954 

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

956 

957 :returns: Formatted access type definition. 

958 """ 

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

960 

961 

962@export 

963class FileType(FullType): 

964 """ 

965 Represents a file type definition. 

966 

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

968 (:data:`DesignatedSubtype`). 

969 

970 .. admonition:: Example 

971 

972 .. code-block:: VHDL 

973 

974 type text_file is file of string; 

975 -- ^^^^^^^^^ <- Identifier 

976 -- ^^^^^^ <- DesignatedSubtype 

977 """ 

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

979 

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

981 """ 

982 Initializes a file type definition. 

983 

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

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

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

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

988 """ 

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

990 

991 self._designatedSubtype = designatedSubtype 

992 designatedSubtype.Parent = self 

993 

994 @readonly 

995 def DesignatedSubtype(self) -> Symbol: 

996 """ 

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

998 

999 :returns: The designated subtype. 

1000 """ 

1001 return self._designatedSubtype 

1002 

1003 def __str__(self) -> str: 

1004 """ 

1005 Formats the file type definition. 

1006 

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

1008 

1009 :returns: Formatted file type definition. 

1010 """ 

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