Coverage for pyVHDLModel/Formatting/VHDL.py: 99%

1103 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 2026-2026 Patrick Lehmann - Bötzingen, Germany # 

15# # 

16# Licensed under the Apache License, Version 2.0 (the "License"); # 

17# you may not use this file except in compliance with the License. # 

18# You may obtain a copy of the License at # 

19# # 

20# http://www.apache.org/licenses/LICENSE-2.0 # 

21# # 

22# Unless required by applicable law or agreed to in writing, software # 

23# distributed under the License is distributed on an "AS IS" BASIS, # 

24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

25# See the License for the specific language governing permissions and # 

26# limitations under the License. # 

27# # 

28# SPDX-License-Identifier: Apache-2.0 # 

29# ==================================================================================================================== # 

30# 

31""" 

32This module contains a writer, which formats a VHDL language model as VHDL source text. 

33 

34The writer is a :class:`~pyVHDLModel.Visitor.Visitor`: a model element walks itself and the writer appends the VHDL 

35source text of each event to a buffer. A parser's subclass of a model class (e.g. from ``pyGHDL.dom``) is written like 

36that model class. Writing is a re-format: comments, blank lines and the letter case of reserved words in a parsed source 

37are not preserved. 

38""" 

39from __future__ import annotations 

40 

41from enum import Enum, unique 

42from math import copysign, isfinite 

43from typing import ClassVar, Iterable, Optional as Nullable 

44 

45from pyTooling.Common import getFullyQualifiedName 

46from pyTooling.Decorators import export, readonly 

47from pyTooling.MetaClasses import ExtendedType 

48 

49from pyVHDLModel.Association import AssociationItem, GenericMapAspectMixin, PortMapAspectMixin 

50from pyVHDLModel.Base import ModelElementUnion, ModelEntity, Mode, ReservedWord, SimpleRange, RangeFromName, \ 

51 WaveformElement, ReportStatementMixin 

52from pyVHDLModel.Common import Statement, ProcedureCallMixin, SignalAssignmentMixin, WaveformMixin, \ 

53 ConditionalWaveform, SelectedWaveform, OthersSelectedWaveform, \ 

54 ConditionalWaveformsMixin, SelectedWaveformsMixin, AssignmentMixin, \ 

55 ConditionalExpression, SelectedExpression, OthersSelectedExpression, \ 

56 SelectedExpressionsMixin 

57from pyVHDLModel.Concurrent import ProcessStatement, ConcurrentProcedureCall, ConcurrentSimpleSignalAssignment, \ 

58 ConcurrentSelectedSignalAssignment, ConcurrentConditionalSignalAssignment, \ 

59 ConcurrentAssertStatement, ComponentInstantiation, EntityInstantiation, \ 

60 ConfigurationInstantiation, ConcurrentBlockStatement, GenerateBranch, \ 

61 IfGenerateBranch, ElsifGenerateBranch, ElseGenerateBranch, IfGenerateStatement, \ 

62 IndexedGenerateChoice, ConcurrentCase, GenerateCase, OthersGenerateCase, \ 

63 CaseGenerateStatement, ForGenerateStatement 

64from pyVHDLModel.Configuration import EntityAspectEntity, EntityAspectConfiguration, EntityAspectOpen, \ 

65 BindingIndication, AllInstantiationList, OthersInstantiationList, \ 

66 ComponentConfiguration, BlockConfiguration 

67from pyVHDLModel.Declaration import EntityClass, Attribute, AttributeSpecification, Alias 

68from pyVHDLModel.DesignUnit import Reference, LibraryClause, UseClause, ContextReference, DesignUnit, Context, \ 

69 Package, PackageBody, Entity, Architecture, Configuration, Component 

70from pyVHDLModel.Exception import VHDLWriterError 

71from pyVHDLModel.Expression import OperatorPrecedence, NullLiteral, EnumerationLiteral, IntegerLiteral, \ 

72 FloatingPointLiteral, PhysicalIntegerLiteral, PhysicalFloatingLiteral, \ 

73 CharacterLiteral, StringLiteral, BitStringBase, BitStringLiteral, \ 

74 UnaryExpression, NegationExpression, IdentityExpression, TypeConversion, \ 

75 SubExpression, BinaryExpression, RangeExpression, AddingExpression, \ 

76 MultiplyingExpression, ExponentiationExpression, LogicalExpression, \ 

77 AndExpression, OrExpression, XorExpression, XnorExpression, \ 

78 RelationalExpression, ShiftExpression, QualifiedExpression, WhenElseExpression, \ 

79 SubtypeAllocation, QualifiedExpressionAllocation, SimpleAggregateElement, \ 

80 IndexedAggregateElement, RangedAggregateElement, NamedAggregateElement, \ 

81 OthersAggregateElement, Aggregate 

82from pyVHDLModel.Name import SimpleName, ParenthesisName, IndexedName, SlicedName, SelectedName, \ 

83 AttributeName, AllName, OpenName 

84from pyVHDLModel.Interface import ModeViewDeclaration, SimpleModeViewElement, CompositeModeViewElement, \ 

85 GenericConstantInterfaceItem, GenericTypeInterfaceItem, \ 

86 PortSimpleSignalInterfaceItem, PortViewSignalInterfaceItem, \ 

87 ParameterConstantInterfaceItem, ParameterVariableInterfaceItem, \ 

88 ParameterSimpleSignalInterfaceItem, ParameterViewSignalInterfaceItem, \ 

89 ParameterFileInterfaceItem, GenericProcedureInterfaceItem, \ 

90 GenericFunctionInterfaceItem 

91from pyVHDLModel.Instantiation import ProcedureInstantiation, FunctionInstantiation, PackageInstantiation 

92from pyVHDLModel.Object import Obj, WithDefaultExpressionMixin, Constant, DeferredConstant, Variable, \ 

93 SharedVariable, Signal, File 

94from pyVHDLModel.Regions import WithGenericsMixin, WithPortsMixin, WithParametersMixin 

95from pyVHDLModel.Sequential import IndexedChoice, SequentialProcedureCall, SequentialSimpleSignalAssignment, \ 

96 SequentialVariableAssignment, SequentialConditionalVariableAssignment, \ 

97 SequentialConditionalSignalAssignment, SequentialSelectedVariableAssignment, \ 

98 SequentialSelectedSignalAssignment, SignalForceAssignment, \ 

99 SignalReleaseAssignment, SequentialReportStatement, SequentialAssertStatement, \ 

100 NullStatement, ReturnStatement, WaitStatement, IfBranch, ElsifBranch, \ 

101 ElseBranch, IfStatement, SequentialCase, Case, OthersCase, CaseStatement, \ 

102 LoopStatement, EndlessLoopStatement, ForLoopStatement, WhileLoopStatement, \ 

103 LoopControlStatement, NextStatement, ExitStatement 

104from pyVHDLModel.Subprogram import Subprogram, Procedure, Function 

105from pyVHDLModel.Symbol import Symbol, ConstrainedScalarSubtypeSymbol, ConstrainedArraySubtypeSymbol, \ 

106 ConstrainedRecordSubtypeSymbol 

107from pyVHDLModel.Type import AnonymousType, FullType, Subtype, EnumeratedType, IntegerType, RealType, \ 

108 PhysicalType, ArrayType, RecordTypeElement, RecordType, AccessType, FileType, \ 

109 ProtectedType, ProtectedTypeBody 

110from pyVHDLModel.Visitor import Visitor 

111 

112 

113@export 

114@unique 

115class KeywordCase(Enum): 

116 """ 

117 An enumeration of letter cases for VHDL reserved words in the written source text. 

118 

119 .. seealso:: 

120 

121 :ref:`vsg:configuring-uppercase-and-lowercase-rules` 

122 |rarr| vhdl-style-guide's option ``case``. 

123 """ 

124 

125 Lower = 0 #: Lower case, e.g. ``downto``. 

126 Upper = 1 #: Upper case, e.g. ``DOWNTO``. 

127 

128 

129@export 

130@unique 

131class IndentStyle(Enum): 

132 """ 

133 An enumeration of indentation styles of the written source text, as vhdl-style-guide's option ``indent_style``. 

134 

135 .. seealso:: 

136 

137 :ref:`vsg:configuring-indent-rules` 

138 |rarr| vhdl-style-guide's options ``indent_style`` and ``indent_size``, with an example of smart tabs. 

139 """ 

140 

141 Spaces = 0 #: Spaces, ``indent_size`` per indentation level (VSG: ``spaces``). 

142 SmartTabs = 1 #: One tab per indentation level (VSG: ``smart_tabs`` - tabs indent, spaces align). 

143 

144 

145@export 

146class VHDLStyle(metaclass=ExtendedType, slots=True): 

147 """ 

148 Represents the formatting options of the :class:`VHDL writer <VHDLWriter>`. 

149 

150 The options follow vhdl-style-guide's names and values. 

151 

152 .. seealso:: 

153 

154 :ref:`vsg:configuring-uppercase-and-lowercase-rules` 

155 |rarr| vhdl-style-guide's option ``case``. 

156 :ref:`vsg:configuring-indent-rules` 

157 |rarr| vhdl-style-guide's options ``indent_style`` and ``indent_size``. 

158 """ 

159 

160 _keywordCase: KeywordCase #: Letter case of reserved words. 

161 _indentStyle: IndentStyle #: Indentation style. 

162 _indentSize: int #: Number of spaces per indentation level. 

163 

164 def __init__( 

165 self, 

166 keywordCase: KeywordCase = KeywordCase.Lower, 

167 indentStyle: IndentStyle = IndentStyle.Spaces, 

168 indentSize: int = 2 

169 ) -> None: 

170 """ 

171 Initializes the formatting options. 

172 

173 :param keywordCase: Optional, letter case of reserved words. Default: ``KeywordCase.Lower``. 

174 :param indentStyle: Optional, indentation style. Default: ``IndentStyle.Spaces``. 

175 :param indentSize: Optional, number of spaces per indentation level. Default: ``2``. 

176 :raises ValueError: If parameter 'keywordCase' is None. 

177 :raises TypeError: If parameter 'keywordCase' is not of type :class:`KeywordCase`. 

178 :raises ValueError: If parameter 'indentStyle' is None. 

179 :raises TypeError: If parameter 'indentStyle' is not of type :class:`IndentStyle`. 

180 :raises ValueError: If parameter 'indentSize' is None. 

181 :raises TypeError: If parameter 'indentSize' is not of type :class:`int`. 

182 :raises ValueError: If parameter 'indentSize' is less than 1. 

183 """ 

184 if keywordCase is None: 

185 raise ValueError("Parameter 'keywordCase' is None.") 

186 elif not isinstance(keywordCase, KeywordCase): 

187 ex = TypeError("Parameter 'keywordCase' is not of type 'KeywordCase'.") 

188 ex.add_note(f"Got type '{getFullyQualifiedName(keywordCase)}'.") 

189 raise ex 

190 

191 if indentStyle is None: 

192 raise ValueError("Parameter 'indentStyle' is None.") 

193 elif not isinstance(indentStyle, IndentStyle): 

194 ex = TypeError("Parameter 'indentStyle' is not of type 'IndentStyle'.") 

195 ex.add_note(f"Got type '{getFullyQualifiedName(indentStyle)}'.") 

196 raise ex 

197 

198 if indentSize is None: 

199 raise ValueError("Parameter 'indentSize' is None.") 

200 elif not isinstance(indentSize, int) or isinstance(indentSize, bool): 

201 ex = TypeError("Parameter 'indentSize' is not of type 'int'.") 

202 ex.add_note(f"Got type '{getFullyQualifiedName(indentSize)}'.") 

203 raise ex 

204 elif indentSize < 1: 

205 ex = ValueError("Parameter 'indentSize' is less than 1.") 

206 ex.add_note(f"Got value '{indentSize}'.") 

207 raise ex 

208 

209 self._keywordCase = keywordCase 

210 self._indentStyle = indentStyle 

211 self._indentSize = indentSize 

212 

213 @readonly 

214 def KeywordCase(self) -> KeywordCase: 

215 """ 

216 Read-only property to access the letter case of reserved words (:attr:`_keywordCase`). 

217 

218 :returns: The letter case of reserved words. 

219 """ 

220 return self._keywordCase 

221 

222 @readonly 

223 def IndentStyle(self) -> IndentStyle: 

224 """ 

225 Read-only property to access the indentation style (:attr:`_indentStyle`). 

226 

227 :returns: The indentation style. 

228 """ 

229 return self._indentStyle 

230 

231 @readonly 

232 def IndentSize(self) -> int: 

233 """ 

234 Read-only property to access the number of spaces per indentation level (:attr:`_indentSize`). 

235 

236 :returns: The number of spaces per indentation level. 

237 """ 

238 return self._indentSize 

239 

240 

241 

242 

243@export 

244class VHDLWriter(Visitor): 

245 """ 

246 A writer formatting VHDL language model elements as VHDL source text. 

247 

248 The writer handles the :mod:`visitor events <pyVHDLModel.Visitor>` of each supported model class. An element of a 

249 class without a walk of its own raises :exc:`NotImplementedError`; nothing is skipped. 

250 

251 Expressions are written with the parentheses VHDL's operator precedence requires (IEEE Std 1076-2008, clause 9.2). 

252 Parentheses from the source (:class:`~pyVHDLModel.Expression.SubExpression`) are kept. Symbols are written from their 

253 :attr:`~pyVHDLModel.Symbol.Symbol.Name`, whether resolved or not. 

254 """ 

255 

256 _BASE_SPECIFIERS: ClassVar[dict[BitStringBase, str]] = { 

257 BitStringBase.Binary: "b", 

258 BitStringBase.Octal: "o", 

259 BitStringBase.Decimal: "d", 

260 BitStringBase.Hexadecimal: "x", 

261 } #: Dictionary of base specifiers, indexed by bit string base. 

262 

263 _style: VHDLStyle #: Formatting options. 

264 _buffer: list[str] #: Fragments of the VHDL source text written by :meth:`Format`. 

265 _minimum: OperatorPrecedence #: Loosest precedence of the next operand without parentheses. 

266 _frames: list[tuple[OperatorPrecedence, bool]] #: Stack of entered operands: precedence and if in parentheses. 

267 _indentation: int #: Indentation level of the next line. 

268 

269 def __init__(self, style: Nullable[VHDLStyle] = None) -> None: 

270 """ 

271 Initializes a VHDL writer. 

272 

273 :param style: Optional, formatting options. Default: ``VHDLStyle()``. 

274 :raises TypeError: If parameter 'style' is not of type :class:`VHDLStyle`. 

275 """ 

276 super().__init__() 

277 

278 if style is None: 

279 style = VHDLStyle() 

280 elif not isinstance(style, VHDLStyle): 

281 ex = TypeError("Parameter 'style' is not of type 'VHDLStyle'.") 

282 ex.add_note(f"Got type '{getFullyQualifiedName(style)}'.") 

283 raise ex 

284 

285 self._style = style 

286 self._buffer = [] 

287 self._minimum = OperatorPrecedence.Range 

288 self._frames = [] 

289 self._indentation = 0 

290 

291 @readonly 

292 def Style(self) -> VHDLStyle: 

293 """ 

294 Read-only property to access the formatting options (:attr:`_style`). 

295 

296 :returns: The formatting options. 

297 """ 

298 return self._style 

299 

300 def Format(self, element: ModelElementUnion) -> str: 

301 """ 

302 Format a model element as VHDL source text. 

303 

304 Each call starts with an empty buffer at indentation level 0. A declaration, a statement or a design unit ends with 

305 a newline. 

306 

307 :param element: The model element to format. 

308 :returns: The VHDL source text. 

309 :raises ValueError: If parameter 'element' is None. 

310 :raises TypeError: If parameter 'element' is not of type :class:`~pyVHDLModel.Base.ModelEntity` or 

311 :class:`~pyVHDLModel.Symbol.Symbol`. 

312 :raises NotImplementedError: If the class of the element or of one of its children has no walk of its own. 

313 :raises VHDLWriterError: If the element or one of its children has no VHDL notation. 

314 """ 

315 if element is None: 

316 raise ValueError("Parameter 'element' is None.") 

317 elif not isinstance(element, (ModelEntity, Symbol)): 

318 ex = TypeError("Parameter 'element' is not of type 'ModelEntity' or 'Symbol'.") 

319 ex.add_note(f"Got type '{getFullyQualifiedName(element)}'.") 

320 raise ex 

321 

322 self._buffer = [] 

323 self._minimum = OperatorPrecedence.Range 

324 self._frames = [] 

325 self._indentation = 0 

326 element.Visit(self) 

327 return "".join(self._buffer) 

328 

329 def VisitLeftParenthesis( 

330 self, 

331 element: IndexedName | ParenthesisName | TypeConversion | EntityAspectEntity | EntityInstantiation 

332 ) -> None: 

333 """ 

334 Write the left parenthesis opening a parenthesized list. 

335 

336 :param element: The element enclosing the list. 

337 """ 

338 self._Write("(") 

339 self._minimum = OperatorPrecedence.Range 

340 

341 def _Write(self, text: str) -> None: 

342 """ 

343 Append VHDL source text to the buffer. 

344 

345 :param text: The VHDL source text. 

346 """ 

347 self._buffer.append(text) 

348 

349 def VisitComma( 

350 self, 

351 element: IndexedName | ParenthesisName | Aggregate | ConstrainedArraySubtypeSymbol | 

352 ConstrainedRecordSubtypeSymbol | EnumeratedType | ArrayType | AttributeSpecification | 

353 GenericMapAspectMixin | PortMapAspectMixin | Reference | ComponentConfiguration | ProcessStatement | 

354 ProcedureCallMixin | WaveformMixin | SelectedWaveformsMixin | SelectedExpressionsMixin | WaitStatement 

355 ) -> None: 

356 """ 

357 Write the comma between two items of a list. 

358 

359 In a map aspect, the next association starts on a new line. 

360 

361 :param element: The element containing the list. 

362 """ 

363 if isinstance(element, (GenericMapAspectMixin, PortMapAspectMixin)): 

364 self._Write(",\n") 

365 self._WriteIndentation() 

366 else: 

367 self._Write(", ") 

368 

369 self._minimum = OperatorPrecedence.Range 

370 

371 def VisitArrow( 

372 self, 

373 element: AssociationItem | IndexedAggregateElement | RangedAggregateElement | NamedAggregateElement | 

374 ConcurrentCase | SequentialCase 

375 ) -> None: 

376 """ 

377 Write the arrow (``=>``) between a choice or formal and its value. 

378 

379 After the choices of a case or case-generate alternative, the alternative's body follows on new lines, indented. 

380 

381 :param element: The element containing the arrow. 

382 """ 

383 if isinstance(element, (ConcurrentCase, SequentialCase)): 

384 self._Write(" =>\n") 

385 self._indentation += 1 

386 else: 

387 self._Write(" => ") 

388 self._minimum = OperatorPrecedence.Range 

389 

390 def VisitApostrophe(self, expression: QualifiedExpression) -> None: 

391 """ 

392 Write the apostrophe of a qualified expression and, unless the operand brings its own, a left parenthesis. 

393 

394 An aggregate or a parenthesized sub-expression brings its own parentheses. 

395 

396 :param expression: The qualified expression. 

397 """ 

398 if isinstance(expression.Operand, (Aggregate, SubExpression)): 

399 self._Write("'") 

400 else: 

401 self._Write("'(") 

402 

403 self._minimum = OperatorPrecedence.Range 

404 

405 def VisitWhen( 

406 self, 

407 element: WhenElseExpression | ConditionalWaveform | SelectedWaveform | OthersSelectedWaveform | 

408 ConditionalExpression | SelectedExpression | OthersSelectedExpression | LoopControlStatement 

409 ) -> None: 

410 """ 

411 Write the reserved word ``when`` of a conditional expression or waveform, or of a selected waveform or expression. 

412 

413 :param element: The conditional expression, the conditional waveform or the selected waveform or expression. 

414 """ 

415 self._Write(f" {self._Keyword(ReservedWord.When)} ") 

416 if isinstance(element, WhenElseExpression): 

417 self._minimum = OperatorPrecedence.Logical 

418 else: 

419 self._minimum = OperatorPrecedence.Range 

420 

421 def _Keyword(self, keyword: ReservedWord) -> str: 

422 """ 

423 Apply the keyword case of the formatting options to a reserved word. 

424 

425 :param keyword: The reserved word. 

426 :returns: The reserved word in the configured letter case. 

427 """ 

428 if self._style.KeywordCase is KeywordCase.Upper: 

429 return keyword.value.upper() 

430 

431 return keyword.value 

432 

433 def _Keywords(self, keywords: Iterable[ReservedWord]) -> str: 

434 """ 

435 Apply the keyword case of the formatting options to reserved words and join them by spaces. 

436 

437 **Format:** ``shared variable``, ``protected body`` 

438 

439 :param keywords: The reserved words. 

440 :returns: The reserved words in the configured letter case, separated by spaces. 

441 """ 

442 return " ".join(self._Keyword(keyword) for keyword in keywords) 

443 

444 def VisitElse( 

445 self, 

446 element: WhenElseExpression | ConditionalWaveformsMixin | SequentialConditionalVariableAssignment 

447 ) -> None: 

448 """ 

449 Write the reserved word ``else`` of a conditional expression or between the alternatives of an assignment. 

450 

451 :param element: The conditional expression or the conditional assignment. 

452 """ 

453 self._Write(f" {self._Keyword(ReservedWord.Else)} ") 

454 if isinstance(element, WhenElseExpression): 

455 self._minimum = OperatorPrecedence.Conditional 

456 else: 

457 self._minimum = OperatorPrecedence.Range 

458 

459 def VisitOperator(self, expression: BinaryExpression) -> None: 

460 """ 

461 Write the operator of a binary expression. 

462 

463 The right operand binds tighter than the operator, unless it's a primary. 

464 

465 :param expression: The binary expression. 

466 """ 

467 precedence, _ = self._frames[-1] 

468 if (reservedWord := expression._RESERVED_WORD) is None: 

469 self._Write(f" {expression._FORMAT[1].strip()} ") 

470 else: 

471 self._Write(f" {self._Keyword(reservedWord)} ") 

472 

473 self._minimum = OperatorPrecedence(min(precedence + 1, OperatorPrecedence.Primary)) 

474 

475 def VisitDirection(self, rng: RangeExpression | SimpleRange) -> None: 

476 """ 

477 Write the direction of a range. 

478 

479 :param rng: The range. 

480 """ 

481 self._Write(f" {self._Keyword(rng.Direction.ReservedWord)} ") 

482 self._minimum = OperatorPrecedence.Adding 

483 

484 def VisitNullLiteral(self, literal: NullLiteral) -> None: 

485 """ 

486 Write a null literal. 

487 

488 **Format:** ``null`` 

489 

490 :param literal: The null literal. 

491 """ 

492 self._Write(self._Keyword(ReservedWord.Null)) 

493 

494 def VisitEnumerationLiteral(self, literal: EnumerationLiteral) -> None: 

495 """ 

496 Write an enumeration literal. 

497 

498 **Format:** ``Idle`` 

499 

500 :param literal: The enumeration literal. 

501 """ 

502 self._Write(literal.Value) 

503 

504 def VisitIntegerLiteral(self, literal: IntegerLiteral) -> None: 

505 """ 

506 Write an integer literal. 

507 

508 **Format:** ``42`` 

509 

510 A negative value is written with a sign, so it binds like a sign. 

511 

512 :param literal: The integer literal. 

513 """ 

514 self._Enter(OperatorPrecedence.Adding if literal.Value < 0 else OperatorPrecedence.Primary) 

515 self._Write(str(literal.Value)) 

516 

517 def _Enter(self, precedence: OperatorPrecedence) -> None: 

518 """ 

519 Enter an operand and write a left parenthesis, if it binds looser than its position allows. 

520 

521 :param precedence: The precedence level of the operand. 

522 """ 

523 parenthesized = precedence < self._minimum 

524 if parenthesized: 

525 self._Write("(") 

526 

527 self._frames.append((precedence, parenthesized)) 

528 

529 def DepartIntegerLiteral(self, literal: IntegerLiteral) -> None: 

530 """ 

531 Leave an integer literal. 

532 

533 :param literal: The integer literal. 

534 """ 

535 self._Leave() 

536 

537 def _Leave(self) -> None: 

538 """ 

539 Leave an operand and write a right parenthesis, if it was entered with a left parenthesis. 

540 """ 

541 _, parenthesized = self._frames.pop() 

542 if parenthesized: 

543 self._Write(")") 

544 

545 def VisitFloatingPointLiteral(self, literal: FloatingPointLiteral) -> None: 

546 """ 

547 Write a floating-point literal. 

548 

549 **Format:** ``3.5`` 

550 

551 A negative value is written with a sign, so it binds like a sign. 

552 

553 :param literal: The floating-point literal. 

554 """ 

555 self._Enter(self._PrecedenceOfReal(literal.Value)) 

556 self._Write(self._FormatReal(literal, literal.Value)) 

557 

558 def DepartFloatingPointLiteral(self, literal: FloatingPointLiteral) -> None: 

559 """ 

560 Leave a floating-point literal. 

561 

562 :param literal: The floating-point literal. 

563 """ 

564 self._Leave() 

565 

566 @staticmethod 

567 def _PrecedenceOfReal(value: float) -> OperatorPrecedence: 

568 """ 

569 Determine how tight a floating-point value binds as an operand. 

570 

571 A negative value, ``-0.0`` included, is written with a sign, so it binds like a sign. 

572 

573 :param value: The floating-point value. 

574 :returns: The precedence level. 

575 """ 

576 if copysign(1.0, value) < 0.0: 

577 return OperatorPrecedence.Adding 

578 

579 return OperatorPrecedence.Primary 

580 

581 def _FormatReal(self, element: ModelEntity, value: float) -> str: 

582 """ 

583 Format a floating-point value as VHDL abstract literal with a decimal point. 

584 

585 **Format:** ``1.0e-09`` 

586 

587 :param element: The model element carrying the value. 

588 :param value: The floating-point value. 

589 :returns: The VHDL source text. 

590 :raises VHDLWriterError: If the value is infinite or not a number. 

591 """ 

592 if not isfinite(value): 

593 ex = VHDLWriterError("Floating-point value has no VHDL notation.", element) 

594 ex.add_note(f"Got value '{value}'.") 

595 raise ex 

596 

597 mantissa, separator, exponent = repr(float(value)).partition("e") 

598 if "." not in mantissa: 

599 mantissa = f"{mantissa}.0" 

600 

601 return f"{mantissa}{separator}{exponent}" 

602 

603 def VisitPhysicalIntegerLiteral(self, literal: PhysicalIntegerLiteral) -> None: 

604 """ 

605 Write a physical literal with an integer value. 

606 

607 **Format:** ``10 ns`` 

608 

609 :param literal: The physical literal. 

610 """ 

611 self._Enter(OperatorPrecedence.Adding if literal.Value < 0 else OperatorPrecedence.Primary) 

612 self._Write(f"{literal.Value} {literal.UnitName}") 

613 

614 def DepartPhysicalIntegerLiteral(self, literal: PhysicalIntegerLiteral) -> None: 

615 """ 

616 Leave a physical literal with an integer value. 

617 

618 :param literal: The physical literal. 

619 """ 

620 self._Leave() 

621 

622 def VisitPhysicalFloatingLiteral(self, literal: PhysicalFloatingLiteral) -> None: 

623 """ 

624 Write a physical literal with a floating-point value. 

625 

626 **Format:** ``1.5 ns`` 

627 

628 :param literal: The physical literal. 

629 """ 

630 self._Enter(self._PrecedenceOfReal(literal.Value)) 

631 self._Write(f"{self._FormatReal(literal, literal.Value)} {literal.UnitName}") 

632 

633 def DepartPhysicalFloatingLiteral(self, literal: PhysicalFloatingLiteral) -> None: 

634 """ 

635 Leave a physical literal with a floating-point value. 

636 

637 :param literal: The physical literal. 

638 """ 

639 self._Leave() 

640 

641 def VisitCharacterLiteral(self, literal: CharacterLiteral) -> None: 

642 """ 

643 Write a character literal. 

644 

645 **Format:** ``'a'`` 

646 

647 :param literal: The character literal. 

648 :raises VHDLWriterError: If the value is not a single graphic character. 

649 """ 

650 if len(literal.Value) != 1 or not self._IsGraphic(literal.Value): 

651 ex = VHDLWriterError("Character literal is not a single graphic character.", literal) 

652 ex.add_note(f"Got value {literal.Value!r}.") 

653 raise ex 

654 

655 self._Write(f"'{literal.Value}'") 

656 

657 @staticmethod 

658 def _IsGraphic(text: str) -> bool: 

659 """ 

660 Check if all characters are VHDL graphic characters (ISO/IEC 8859-1 without control characters). 

661 

662 :param text: The text to check. 

663 :returns: ``True``, if all characters are graphic characters. 

664 """ 

665 return all(32 <= ord(character) <= 126 or 160 <= ord(character) <= 255 for character in text) 

666 

667 def VisitStringLiteral(self, literal: StringLiteral) -> None: 

668 """ 

669 Write a string literal and double each enclosed quotation mark. 

670 

671 **Format:** ``"say ""hi"" twice"`` 

672 

673 :param literal: The string literal. 

674 :raises VHDLWriterError: If the value contains a non-graphic character. 

675 """ 

676 if not self._IsGraphic(literal.Value): 

677 ex = VHDLWriterError("String literal contains a non-graphic character.", literal) 

678 ex.add_note(f"Got value {literal.Value!r}.") 

679 raise ex 

680 

681 value = literal.Value.replace("\"", "\"\"") 

682 self._Write(f"\"{value}\"") 

683 

684 def VisitBitStringLiteral(self, literal: BitStringLiteral) -> None: 

685 """ 

686 Write a bit string literal. 

687 

688 **Format:** ``8ux"A0"`` 

689 

690 :param literal: The bit string literal. 

691 :raises VHDLWriterError: If the literal's class has no base specifier. 

692 :raises VHDLWriterError: If a decimal bit string literal is signed or unsigned. 

693 :raises VHDLWriterError: If the value contains a quotation mark or a non-graphic character. 

694 """ 

695 base = self._BASE_SPECIFIERS.get(literal._BASE) 

696 if base is None: 696 ↛ 697line 696 didn't jump to line 697 because the condition on line 696 was never true

697 ex = VHDLWriterError("Model element is not supported by the VHDL writer.", literal) 

698 ex.add_note(f"Got type '{getFullyQualifiedName(literal)}'.") 

699 raise ex 

700 

701 if literal.IsSigned is None: 

702 signedness = "" 

703 elif literal._BASE is BitStringBase.Decimal: 

704 raise VHDLWriterError("Decimal bit string literal can't be signed or unsigned.", literal) 

705 elif literal.IsSigned: 

706 signedness = "s" 

707 else: 

708 signedness = "u" 

709 

710 if "\"" in literal.Value or not self._IsGraphic(literal.Value): 

711 ex = VHDLWriterError("Bit string literal contains a quotation mark or a non-graphic character.", literal) 

712 ex.add_note(f"Got value {literal.Value!r}.") 

713 raise ex 

714 

715 length = "" if literal.Length is None else str(literal.Length) 

716 self._Write(f"{length}{signedness}{base}\"{literal.Value}\"") 

717 

718 def VisitUnaryExpression(self, expression: UnaryExpression) -> None: 

719 """ 

720 Write the operator of a unary expression with a reserved word as operator; its operand is a primary. 

721 

722 **Format:** ``not (a and b)`` 

723 

724 :param expression: The unary expression. 

725 """ 

726 self._Enter(expression._PRECEDENCE) 

727 self._Write(f"{self._Keyword(expression._RESERVED_WORD)} ") 

728 self._minimum = OperatorPrecedence.Primary 

729 

730 def DepartUnaryExpression(self, expression: UnaryExpression) -> None: 

731 """ 

732 Leave a unary expression with a reserved word as operator. 

733 

734 :param expression: The unary expression. 

735 """ 

736 self._Leave() 

737 

738 def VisitNegationExpression(self, expression: NegationExpression) -> None: 

739 """ 

740 Write the sign of a negation; its operand is a term. 

741 

742 **Format:** ``-a`` 

743 

744 :param expression: The negation. 

745 """ 

746 self._Enter(expression._PRECEDENCE) 

747 self._Write(expression._FORMAT[0]) 

748 self._minimum = OperatorPrecedence.Multiplying 

749 

750 def DepartNegationExpression(self, expression: NegationExpression) -> None: 

751 """ 

752 Leave a negation. 

753 

754 :param expression: The negation. 

755 """ 

756 self._Leave() 

757 

758 def VisitIdentityExpression(self, expression: IdentityExpression) -> None: 

759 """ 

760 Write the sign of an identity; its operand is a term. 

761 

762 **Format:** ``+a`` 

763 

764 :param expression: The identity. 

765 """ 

766 self._Enter(expression._PRECEDENCE) 

767 self._Write(expression._FORMAT[0]) 

768 self._minimum = OperatorPrecedence.Multiplying 

769 

770 def DepartIdentityExpression(self, expression: IdentityExpression) -> None: 

771 """ 

772 Leave an identity. 

773 

774 :param expression: The identity. 

775 """ 

776 self._Leave() 

777 

778 def DepartTypeConversion(self, conversion: TypeConversion) -> None: 

779 """ 

780 Write the right parenthesis closing the operand of a type conversion. 

781 

782 **Format:** ``integer(r)`` 

783 

784 :param conversion: The type conversion. 

785 """ 

786 self._Write(")") 

787 

788 def VisitSubExpression(self, expression: SubExpression) -> None: 

789 """ 

790 Write the left parenthesis of a parenthesized sub-expression from the source. 

791 

792 **Format:** ``(a + b)`` 

793 

794 :param expression: The sub-expression. 

795 """ 

796 self._Write("(") 

797 self._minimum = OperatorPrecedence.Range 

798 

799 def DepartSubExpression(self, expression: SubExpression) -> None: 

800 """ 

801 Write the right parenthesis of a parenthesized sub-expression from the source. 

802 

803 :param expression: The sub-expression. 

804 """ 

805 self._Write(")") 

806 

807 def VisitLogicalExpression(self, expression: LogicalExpression) -> None: 

808 """ 

809 Enter a binary logical expression; its left operand is a relation or a chain of the same associative operator. 

810 

811 The associative operators are ``and``, ``or``, ``xor`` and ``xnor``. 

812 

813 **Format:** ``a and b and c`` or ``(a and b) or c`` 

814 

815 :param expression: The logical expression. 

816 """ 

817 self._Enter(expression._PRECEDENCE) 

818 left = expression.LeftOperand 

819 if any( 

820 isinstance(expression, operator) and isinstance(left, operator) 

821 for operator in (AndExpression, OrExpression, XorExpression, XnorExpression) 

822 ): 

823 self._minimum = OperatorPrecedence.Logical 

824 else: 

825 self._minimum = OperatorPrecedence.Relational 

826 

827 def DepartLogicalExpression(self, expression: LogicalExpression) -> None: 

828 """ 

829 Leave a binary logical expression. 

830 

831 :param expression: The logical expression. 

832 """ 

833 self._Leave() 

834 

835 def VisitRelationalExpression(self, expression: RelationalExpression) -> None: 

836 """ 

837 Enter a relational expression; its left operand is a shift expression. 

838 

839 **Format:** ``a = b`` 

840 

841 :param expression: The relational expression. 

842 """ 

843 self._Enter(expression._PRECEDENCE) 

844 self._minimum = OperatorPrecedence.Shift 

845 

846 def DepartRelationalExpression(self, expression: RelationalExpression) -> None: 

847 """ 

848 Leave a relational expression. 

849 

850 :param expression: The relational expression. 

851 """ 

852 self._Leave() 

853 

854 def VisitShiftExpression(self, expression: ShiftExpression) -> None: 

855 """ 

856 Enter a shift or rotate expression; its left operand is a simple expression. 

857 

858 **Format:** ``a sll 2`` 

859 

860 :param expression: The shift or rotate expression. 

861 """ 

862 self._Enter(expression._PRECEDENCE) 

863 self._minimum = OperatorPrecedence.Adding 

864 

865 def DepartShiftExpression(self, expression: ShiftExpression) -> None: 

866 """ 

867 Leave a shift or rotate expression. 

868 

869 :param expression: The shift or rotate expression. 

870 """ 

871 self._Leave() 

872 

873 def VisitAddingExpression(self, expression: AddingExpression) -> None: 

874 """ 

875 Enter an adding expression; it associates to the left. 

876 

877 **Format:** ``a - b - c`` or ``a - (b - c)`` 

878 

879 :param expression: The adding expression. 

880 """ 

881 self._Enter(expression._PRECEDENCE) 

882 self._minimum = OperatorPrecedence.Adding 

883 

884 def DepartAddingExpression(self, expression: AddingExpression) -> None: 

885 """ 

886 Leave an adding expression. 

887 

888 :param expression: The adding expression. 

889 """ 

890 self._Leave() 

891 

892 def VisitMultiplyingExpression(self, expression: MultiplyingExpression) -> None: 

893 """ 

894 Enter a multiplying expression; it associates to the left. 

895 

896 **Format:** ``(a + b) * c`` 

897 

898 :param expression: The multiplying expression. 

899 """ 

900 self._Enter(expression._PRECEDENCE) 

901 self._minimum = OperatorPrecedence.Multiplying 

902 

903 def DepartMultiplyingExpression(self, expression: MultiplyingExpression) -> None: 

904 """ 

905 Leave a multiplying expression. 

906 

907 :param expression: The multiplying expression. 

908 """ 

909 self._Leave() 

910 

911 def VisitExponentiationExpression(self, expression: ExponentiationExpression) -> None: 

912 """ 

913 Enter an exponentiation; both operands are primaries. 

914 

915 **Format:** ``a ** (b ** c)`` 

916 

917 :param expression: The exponentiation. 

918 """ 

919 self._Enter(expression._PRECEDENCE) 

920 self._minimum = OperatorPrecedence.Primary 

921 

922 def DepartExponentiationExpression(self, expression: ExponentiationExpression) -> None: 

923 """ 

924 Leave an exponentiation. 

925 

926 :param expression: The exponentiation. 

927 """ 

928 self._Leave() 

929 

930 def VisitRangeExpression(self, expression: RangeExpression) -> None: 

931 """ 

932 Enter a range expression; its bounds are simple expressions. 

933 

934 **Format:** ``7 downto 0`` 

935 

936 :param expression: The range expression. 

937 """ 

938 self._Enter(expression._PRECEDENCE) 

939 self._minimum = OperatorPrecedence.Adding 

940 

941 def DepartRangeExpression(self, expression: RangeExpression) -> None: 

942 """ 

943 Leave a range expression. 

944 

945 :param expression: The range expression. 

946 """ 

947 self._Leave() 

948 

949 def VisitWhenElseExpression(self, expression: WhenElseExpression) -> None: 

950 """ 

951 Enter a conditional expression; its value and condition are logical expressions. 

952 

953 **Format:** ``a when c else b`` 

954 

955 :param expression: The conditional expression. 

956 """ 

957 self._Enter(expression._PRECEDENCE) 

958 self._minimum = OperatorPrecedence.Logical 

959 

960 def DepartWhenElseExpression(self, expression: WhenElseExpression) -> None: 

961 """ 

962 Leave a conditional expression. 

963 

964 :param expression: The conditional expression. 

965 """ 

966 self._Leave() 

967 

968 def DepartQualifiedExpression(self, expression: QualifiedExpression) -> None: 

969 """ 

970 Write the right parenthesis closing the operand of a qualified expression, unless the operand brings its own. 

971 

972 **Format:** ``byte'(others => '0')`` 

973 

974 :param expression: The qualified expression. 

975 """ 

976 if not isinstance(expression.Operand, (Aggregate, SubExpression)): 

977 self._Write(")") 

978 

979 def VisitSubtypeAllocation(self, allocation: SubtypeAllocation) -> None: 

980 """ 

981 Write the reserved word ``new`` of an allocation of a subtype. 

982 

983 **Format:** ``new node`` 

984 

985 :param allocation: The allocation. 

986 """ 

987 self._Write(f"{self._Keyword(ReservedWord.New)} ") 

988 

989 def VisitQualifiedExpressionAllocation(self, allocation: QualifiedExpressionAllocation) -> None: 

990 """ 

991 Write the reserved word ``new`` of an allocation initialized by a qualified expression. 

992 

993 **Format:** ``new integer'(5)`` 

994 

995 :param allocation: The allocation. 

996 """ 

997 self._Write(f"{self._Keyword(ReservedWord.New)} ") 

998 

999 def VisitAggregate(self, aggregate: Aggregate) -> None: 

1000 """ 

1001 Write the left parenthesis of an aggregate. 

1002 

1003 **Format:** ``(0 => '1', others => '0')`` 

1004 

1005 :param aggregate: The aggregate. 

1006 :raises VHDLWriterError: If the aggregate has no elements. 

1007 :raises VHDLWriterError: If the aggregate has a single positional element (it would read as parentheses). |br| 

1008 Use a named element, e.g. ``others => value``. 

1009 """ 

1010 elements = aggregate.Elements 

1011 if len(elements) == 0: 

1012 raise VHDLWriterError("Aggregate has no elements.", aggregate) 

1013 elif len(elements) == 1 and isinstance(elements[0], SimpleAggregateElement): 

1014 ex = VHDLWriterError("Aggregate with a single positional element has no VHDL notation.", aggregate) 

1015 ex.add_note("Use a named element, e.g. 'others => value'.") 

1016 raise ex 

1017 

1018 self._Write("(") 

1019 self._minimum = OperatorPrecedence.Range 

1020 

1021 def DepartAggregate(self, aggregate: Aggregate) -> None: 

1022 """ 

1023 Write the right parenthesis of an aggregate. 

1024 

1025 :param aggregate: The aggregate. 

1026 """ 

1027 self._Write(")") 

1028 

1029 def VisitIndexedAggregateElement(self, element: IndexedAggregateElement) -> None: 

1030 """ 

1031 Enter an aggregate element chosen by an index; the index is a simple expression. 

1032 

1033 **Format:** ``0 => '1'`` 

1034 

1035 :param element: The aggregate element. 

1036 """ 

1037 self._minimum = OperatorPrecedence.Adding 

1038 

1039 def VisitOthersAggregateElement(self, element: OthersAggregateElement) -> None: 

1040 """ 

1041 Write the choice ``others`` of an aggregate element. 

1042 

1043 **Format:** ``others => '0'`` 

1044 

1045 :param element: The aggregate element. 

1046 """ 

1047 self._Write(f"{self._Keyword(ReservedWord.Others)} => ") 

1048 self._minimum = OperatorPrecedence.Range 

1049 

1050 def VisitSimpleRange(self, rng: SimpleRange) -> None: 

1051 """ 

1052 Enter a range given by its bounds; its bounds are simple expressions. 

1053 

1054 **Format:** ``0 to 7`` 

1055 

1056 :param rng: The range. 

1057 """ 

1058 self._Enter(OperatorPrecedence.Range) 

1059 self._minimum = OperatorPrecedence.Adding 

1060 

1061 def DepartSimpleRange(self, rng: SimpleRange) -> None: 

1062 """ 

1063 Leave a range given by its bounds. 

1064 

1065 :param rng: The range. 

1066 """ 

1067 self._Leave() 

1068 

1069 def VisitRangeFromName(self, rng: RangeFromName) -> None: 

1070 """ 

1071 Enter a range denoted by a name. 

1072 

1073 **Format:** ``v'range`` 

1074 

1075 :param rng: The range. 

1076 """ 

1077 self._Enter(OperatorPrecedence.Range) 

1078 

1079 def DepartRangeFromName(self, rng: RangeFromName) -> None: 

1080 """ 

1081 Leave a range denoted by a name. 

1082 

1083 :param rng: The range. 

1084 """ 

1085 self._Leave() 

1086 

1087 def VisitSimpleName(self, name: SimpleName) -> None: 

1088 """ 

1089 Write a simple name. 

1090 

1091 **Format:** ``clk`` 

1092 

1093 :param name: The simple name. 

1094 """ 

1095 self._Write(name.Identifier) 

1096 

1097 def DepartSelectedName(self, name: SelectedName) -> None: 

1098 """ 

1099 Write the suffix of a selected name after its prefix. 

1100 

1101 **Format:** ``ieee.numeric_std`` 

1102 

1103 :param name: The selected name. 

1104 """ 

1105 self._Write(f".{name.Identifier}") 

1106 

1107 def DepartAllName(self, name: AllName) -> None: 

1108 """ 

1109 Write the suffix ``all`` of a selected name after its prefix, or the reserved word ``all`` without a prefix. 

1110 

1111 **Format:** ``ieee.numeric_std.all`` or ``all`` 

1112 

1113 :param name: The ``all`` name. 

1114 """ 

1115 if name.Prefix is None: 

1116 self._Write(self._Keyword(ReservedWord.All)) 

1117 else: 

1118 self._Write(f".{self._Keyword(ReservedWord.All)}") 

1119 

1120 def DepartAttributeName(self, name: AttributeName) -> None: 

1121 """ 

1122 Write the attribute designator of an attribute name after its prefix. 

1123 

1124 **Format:** ``v'range`` 

1125 

1126 :param name: The attribute name. 

1127 """ 

1128 self._Write(f"'{name.Identifier}") 

1129 

1130 def DepartIndexedName(self, name: IndexedName) -> None: 

1131 """ 

1132 Write the right parenthesis closing the indices of an indexed name. 

1133 

1134 **Format:** ``m(i, j)`` 

1135 

1136 :param name: The indexed name. 

1137 """ 

1138 self._Write(")") 

1139 

1140 def DepartParenthesisName(self, name: ParenthesisName) -> None: 

1141 """ 

1142 Write the right parenthesis closing the associations of a parenthesis name (index, slice or function call). 

1143 

1144 **Format:** ``resize(a, 8)`` 

1145 

1146 :param name: The parenthesis name. 

1147 """ 

1148 self._Write(")") 

1149 

1150 def VisitSlicedName(self, name: SlicedName) -> None: 

1151 """ 

1152 Reject a sliced name, because it carries no discrete range. 

1153 

1154 :param name: The sliced name. 

1155 :raises VHDLWriterError: Always, because a sliced name carries no discrete range. |br| 

1156 Use a :class:`~pyVHDLModel.Name.ParenthesisName` with a range expression as association. 

1157 """ 

1158 ex = VHDLWriterError("Sliced name carries no discrete range.", name) 

1159 ex.add_note("Use a 'ParenthesisName' with a range expression as association.") 

1160 raise ex 

1161 

1162 def VisitOpenName(self, name: OpenName) -> None: 

1163 """ 

1164 Write the reserved word ``open``. 

1165 

1166 **Format:** ``open`` 

1167 

1168 :param name: The ``open`` name. 

1169 """ 

1170 self._Write(self._Keyword(ReservedWord.Open)) 

1171 

1172 def VisitAssociationItem(self, item: AssociationItem) -> None: 

1173 """ 

1174 Check an association item before its formal and actual are written. 

1175 

1176 **Format:** ``formal => actual`` or ``actual`` 

1177 

1178 :param item: The association item. 

1179 :raises VHDLWriterError: If the association item has no actual. 

1180 """ 

1181 if item.Actual is None: 

1182 raise VHDLWriterError("Association item has no actual.", item) 

1183 

1184 def VisitSemicolon(self, element: WithGenericsMixin | WithPortsMixin | WithParametersMixin) -> None: 

1185 """ 

1186 Write the semicolon between two items of an interface list; the next item starts on a new line. 

1187 

1188 :param element: The element containing the interface list. 

1189 """ 

1190 self._Write(";\n") 

1191 self._WriteIndentation() 

1192 

1193 def _WriteIndentation(self) -> None: 

1194 """ 

1195 Write the indentation of the current indentation level. 

1196 """ 

1197 if self._style.IndentStyle is IndentStyle.SmartTabs: 

1198 self._Write("\t" * self._indentation) 

1199 else: 

1200 self._Write(" " * (self._indentation * self._style.IndentSize)) 

1201 

1202 def VisitVariableAssignment(self, element: WithDefaultExpressionMixin | AssignmentMixin) -> None: 

1203 """ 

1204 Write the variable assignment delimiter (``:=``) before a default expression or the value of a variable assignment. 

1205 

1206 :param element: The element with the default expression or the variable assignment. 

1207 """ 

1208 self._Write(" := ") 

1209 self._minimum = OperatorPrecedence.Range 

1210 

1211 def VisitIs( 

1212 self, 

1213 element: ModeViewDeclaration | Alias | AttributeSpecification | Subprogram | Architecture | Configuration | 

1214 ProcessStatement | CaseStatement 

1215 ) -> None: 

1216 """ 

1217 Write the reserved word ``is`` ending the header of a declaration; its body is indented. 

1218 

1219 In an alias declaration and an attribute specification, the name or the expression follows on the same line. A 

1220 subprogram without declared items and statements is a subprogram declaration, which has no ``is``. 

1221 

1222 :param element: The declaration. 

1223 """ 

1224 if isinstance(element, (Alias, AttributeSpecification)): 

1225 self._Write(f" {self._Keyword(ReservedWord.Is)} ") 

1226 self._minimum = OperatorPrecedence.Range 

1227 elif isinstance(element, Subprogram) and not self._IsSubprogramBody(element): 

1228 return 

1229 else: 

1230 self._Write(f" {self._Keyword(ReservedWord.Is)}\n") 

1231 self._indentation += 1 

1232 

1233 def VisitRangeConstraint(self, symbol: ConstrainedScalarSubtypeSymbol) -> None: 

1234 """ 

1235 Write the reserved word ``range`` of a range constraint. 

1236 

1237 **Format:** ``integer range 0 to 7`` 

1238 

1239 :param symbol: The constrained subtype symbol. 

1240 """ 

1241 self._Write(f" {self._Keyword(ReservedWord.Range)} ") 

1242 self._minimum = OperatorPrecedence.Range 

1243 

1244 def VisitIndexConstraint( 

1245 self, 

1246 element: ConstrainedArraySubtypeSymbol | ConstrainedRecordSubtypeSymbol | ArrayType 

1247 ) -> None: 

1248 """ 

1249 Write the left parenthesis of an index constraint. 

1250 

1251 **Format:** ``bit_vector(7 downto 0)`` 

1252 

1253 :param element: The constrained subtype symbol or the array type. 

1254 """ 

1255 self._Write("(") 

1256 self._minimum = OperatorPrecedence.Range 

1257 

1258 def DepartIndexConstraint( 

1259 self, 

1260 element: ConstrainedArraySubtypeSymbol | ConstrainedRecordSubtypeSymbol | ArrayType 

1261 ) -> None: 

1262 """ 

1263 Write the right parenthesis of an index constraint. 

1264 

1265 :param element: The constrained subtype symbol or the array type. 

1266 """ 

1267 self._Write(")") 

1268 

1269 def VisitRecordConstraint(self, symbol: ConstrainedRecordSubtypeSymbol) -> None: 

1270 """ 

1271 Write the left parenthesis of a record constraint. 

1272 

1273 **Format:** ``frame(data(7 downto 0), mask(3 downto 0))`` 

1274 

1275 :param symbol: The constrained subtype symbol. 

1276 """ 

1277 self._Write("(") 

1278 

1279 def DepartRecordConstraint(self, symbol: ConstrainedRecordSubtypeSymbol) -> None: 

1280 """ 

1281 Write the right parenthesis of a record constraint. 

1282 

1283 :param symbol: The constrained subtype symbol. 

1284 """ 

1285 self._Write(")") 

1286 

1287 def VisitGenericClause(self, element: WithGenericsMixin) -> None: 

1288 """ 

1289 Write the reserved word ``generic`` and the left parenthesis of a generic clause; each generic is on its own line. 

1290 

1291 **Format:** ``generic (`` ... ``);`` 

1292 

1293 The generic clause of a subprogram follows its designator on the same line and ends without a semicolon. 

1294 

1295 :param element: The element with generics. 

1296 """ 

1297 if isinstance(element, Subprogram): 

1298 self._Write(" ") 

1299 else: 

1300 self._WriteIndentation() 

1301 

1302 self._Write(f"{self._Keyword(ReservedWord.Generic)} (\n") 

1303 self._indentation += 1 

1304 self._WriteIndentation() 

1305 

1306 def DepartGenericClause(self, element: WithGenericsMixin) -> None: 

1307 """ 

1308 Write the right parenthesis of a generic clause on its own line. 

1309 

1310 :param element: The element with generics. 

1311 """ 

1312 if isinstance(element, Subprogram): 

1313 self._WriteClosingParenthesis("") 

1314 else: 

1315 self._WriteClosingParenthesis(";\n") 

1316 

1317 def _WriteClosingParenthesis(self, terminator: str) -> None: 

1318 """ 

1319 Write the right parenthesis closing a list on its own line, one indentation level up. 

1320 

1321 :param terminator: The text following the right parenthesis. 

1322 """ 

1323 self._Write("\n") 

1324 self._indentation -= 1 

1325 self._WriteIndentation() 

1326 self._Write(f"){terminator}") 

1327 

1328 def VisitPortClause(self, element: WithPortsMixin) -> None: 

1329 """ 

1330 Write the reserved word ``port`` and the left parenthesis of a port clause; each port is on its own line. 

1331 

1332 **Format:** ``port (`` ... ``);`` 

1333 

1334 :param element: The element with ports. 

1335 """ 

1336 self._WriteIndentation() 

1337 self._Write(f"{self._Keyword(ReservedWord.Port)} (\n") 

1338 self._indentation += 1 

1339 self._WriteIndentation() 

1340 

1341 def DepartPortClause(self, element: WithPortsMixin) -> None: 

1342 """ 

1343 Write the right parenthesis of a port clause on its own line. 

1344 

1345 :param element: The element with ports. 

1346 """ 

1347 self._WriteClosingParenthesis(";\n") 

1348 

1349 def VisitConstant(self, constant: Constant) -> None: 

1350 """ 

1351 Write the reserved word ``constant`` and the identifiers of a constant declaration. 

1352 

1353 **Format:** ``constant BITS : positive := 8;`` 

1354 

1355 :param constant: The constant declaration. 

1356 """ 

1357 self._WriteObjectDeclaration(constant) 

1358 

1359 def _WriteObjectDeclaration(self, obj: Obj) -> None: 

1360 """ 

1361 Write the indentation, the object class reserved word and the identifiers of an object declaration. 

1362 

1363 :param obj: The object declaration. 

1364 """ 

1365 self._WriteIndentation() 

1366 self._Write(f"{self._Keywords(obj._OBJECT_KEYWORD)} {', '.join(obj.Identifiers)} : ") 

1367 

1368 def DepartConstant(self, constant: Constant) -> None: 

1369 """ 

1370 Write the semicolon ending a constant declaration. 

1371 

1372 :param constant: The constant declaration. 

1373 """ 

1374 self._Write(";\n") 

1375 

1376 def VisitDeferredConstant(self, constant: DeferredConstant) -> None: 

1377 """ 

1378 Write the reserved word ``constant`` and the identifiers of a deferred constant declaration. 

1379 

1380 **Format:** ``constant BITS : positive;`` 

1381 

1382 :param constant: The deferred constant declaration. 

1383 """ 

1384 self._WriteObjectDeclaration(constant) 

1385 

1386 def DepartDeferredConstant(self, constant: DeferredConstant) -> None: 

1387 """ 

1388 Write the semicolon ending a deferred constant declaration. 

1389 

1390 :param constant: The deferred constant declaration. 

1391 """ 

1392 self._Write(";\n") 

1393 

1394 def VisitVariable(self, variable: Variable) -> None: 

1395 """ 

1396 Write the reserved word ``variable`` and the identifiers of a variable declaration. 

1397 

1398 **Format:** ``variable count : natural := 0;`` 

1399 

1400 :param variable: The variable declaration. 

1401 """ 

1402 self._WriteObjectDeclaration(variable) 

1403 

1404 def DepartVariable(self, variable: Variable) -> None: 

1405 """ 

1406 Write the semicolon ending a variable declaration. 

1407 

1408 :param variable: The variable declaration. 

1409 """ 

1410 self._Write(";\n") 

1411 

1412 def VisitSharedVariable(self, variable: SharedVariable) -> None: 

1413 """ 

1414 Write the reserved words ``shared variable`` and the identifiers of a shared variable declaration. 

1415 

1416 **Format:** ``shared variable counter : counter_t;`` 

1417 

1418 :param variable: The shared variable declaration. 

1419 """ 

1420 self._WriteObjectDeclaration(variable) 

1421 

1422 def DepartSharedVariable(self, variable: SharedVariable) -> None: 

1423 """ 

1424 Write the semicolon ending a shared variable declaration. 

1425 

1426 :param variable: The shared variable declaration. 

1427 """ 

1428 self._Write(";\n") 

1429 

1430 def VisitSignal(self, signal: Signal) -> None: 

1431 """ 

1432 Write the reserved word ``signal`` and the identifiers of a signal declaration. 

1433 

1434 **Format:** ``signal a, b : bit := '0';`` 

1435 

1436 :param signal: The signal declaration. 

1437 """ 

1438 self._WriteObjectDeclaration(signal) 

1439 

1440 def DepartSignal(self, signal: Signal) -> None: 

1441 """ 

1442 Write the semicolon ending a signal declaration. 

1443 

1444 :param signal: The signal declaration. 

1445 """ 

1446 self._Write(";\n") 

1447 

1448 def VisitFile(self, file: File) -> None: 

1449 """ 

1450 Write the reserved word ``file`` and the identifiers of a file declaration. 

1451 

1452 **Format:** ``file input : text;`` 

1453 

1454 The model carries no file open information, so none is written. 

1455 

1456 :param file: The file declaration. 

1457 """ 

1458 self._WriteObjectDeclaration(file) 

1459 

1460 def DepartFile(self, file: File) -> None: 

1461 """ 

1462 Write the semicolon ending a file declaration. 

1463 

1464 :param file: The file declaration. 

1465 """ 

1466 self._Write(";\n") 

1467 

1468 def VisitGenericConstantInterfaceItem(self, item: GenericConstantInterfaceItem) -> None: 

1469 """ 

1470 Write the identifiers and the mode of a generic constant. 

1471 

1472 **Format:** ``BITS : positive := 8`` 

1473 

1474 :param item: The generic constant. 

1475 """ 

1476 self._WriteInterfaceItem(item, (), item.Mode) 

1477 

1478 def _WriteInterfaceItem(self, item: Obj, keywords: tuple[ReservedWord, ...], mode: Mode) -> None: 

1479 """ 

1480 Write the object class reserved words (if any), the identifiers and the mode (if any) of an interface item. 

1481 

1482 :param item: The interface item. 

1483 :param keywords: The object class reserved words, or an empty tuple. 

1484 :param mode: The mode; ``Mode.Default`` writes none. 

1485 """ 

1486 if len(keywords) > 0: 

1487 self._Write(f"{self._Keywords(keywords)} ") 

1488 

1489 self._Write(f"{', '.join(item.Identifiers)} : ") 

1490 if mode is not Mode.Default: 

1491 self._Write(f"{self._Keyword(mode.ReservedWord)} ") 

1492 

1493 def VisitGenericTypeInterfaceItem(self, item: GenericTypeInterfaceItem) -> None: 

1494 """ 

1495 Write a generic type. 

1496 

1497 **Format:** ``type T`` 

1498 

1499 :param item: The generic type. 

1500 """ 

1501 self._Write(f"{self._Keyword(ReservedWord.Type)} {item.Identifier}") 

1502 

1503 def VisitPortSimpleSignalInterfaceItem(self, item: PortSimpleSignalInterfaceItem) -> None: 

1504 """ 

1505 Write the identifiers and the mode of a port. 

1506 

1507 **Format:** ``clk : in std_logic`` 

1508 

1509 :param item: The port. 

1510 """ 

1511 self._WriteInterfaceItem(item, (), item.Mode) 

1512 

1513 def VisitPortViewSignalInterfaceItem(self, item: PortViewSignalInterfaceItem) -> None: 

1514 """ 

1515 Write the identifiers and the reserved word ``view`` of a port with a mode view. 

1516 

1517 **Format:** ``link : view master`` 

1518 

1519 :param item: The port. 

1520 """ 

1521 self._WriteInterfaceItem(item, (), Mode.Default) 

1522 self._Write(f"{self._Keyword(ReservedWord.View)} ") 

1523 

1524 def VisitParameterConstantInterfaceItem(self, item: ParameterConstantInterfaceItem) -> None: 

1525 """ 

1526 Write the reserved word ``constant``, the identifiers and the mode of a constant parameter. 

1527 

1528 **Format:** ``constant value : in integer`` 

1529 

1530 :param item: The constant parameter. 

1531 """ 

1532 self._WriteInterfaceItem(item, item._OBJECT_KEYWORD, item.Mode) 

1533 

1534 def VisitParameterVariableInterfaceItem(self, item: ParameterVariableInterfaceItem) -> None: 

1535 """ 

1536 Write the reserved word ``variable``, the identifiers and the mode of a variable parameter. 

1537 

1538 **Format:** ``variable result : out integer`` 

1539 

1540 :param item: The variable parameter. 

1541 """ 

1542 self._WriteInterfaceItem(item, item._OBJECT_KEYWORD, item.Mode) 

1543 

1544 def VisitParameterSimpleSignalInterfaceItem(self, item: ParameterSimpleSignalInterfaceItem) -> None: 

1545 """ 

1546 Write the reserved word ``signal``, the identifiers and the mode of a signal parameter. 

1547 

1548 **Format:** ``signal clk : in std_logic`` 

1549 

1550 :param item: The signal parameter. 

1551 """ 

1552 self._WriteInterfaceItem(item, item._OBJECT_KEYWORD, item.Mode) 

1553 

1554 def VisitParameterViewSignalInterfaceItem(self, item: ParameterViewSignalInterfaceItem) -> None: 

1555 """ 

1556 Write the reserved word ``signal``, the identifiers and the reserved word ``view`` of a signal parameter. 

1557 

1558 **Format:** ``signal link : view master`` 

1559 

1560 :param item: The signal parameter. 

1561 """ 

1562 self._WriteInterfaceItem(item, item._OBJECT_KEYWORD, Mode.Default) 

1563 self._Write(f"{self._Keyword(ReservedWord.View)} ") 

1564 

1565 def VisitParameterFileInterfaceItem(self, item: ParameterFileInterfaceItem) -> None: 

1566 """ 

1567 Write the reserved word ``file`` and the identifiers of a file parameter. 

1568 

1569 **Format:** ``file input : text`` 

1570 

1571 :param item: The file parameter. 

1572 """ 

1573 self._WriteInterfaceItem(item, item._OBJECT_KEYWORD, Mode.Default) 

1574 

1575 def VisitModeViewDeclaration(self, declaration: ModeViewDeclaration) -> None: 

1576 """ 

1577 Write the reserved word ``view``, the identifier and the reserved word ``of`` of a mode view declaration. 

1578 

1579 **Format:** ``view master of bus_t is`` ... ``end view master;`` 

1580 

1581 :param declaration: The mode view declaration. 

1582 """ 

1583 self._WriteIndentation() 

1584 self._Write(f"{self._Keyword(ReservedWord.View)} {declaration.Identifier} {self._Keyword(ReservedWord.Of)} ") 

1585 

1586 def DepartModeViewDeclaration(self, declaration: ModeViewDeclaration) -> None: 

1587 """ 

1588 Write the end of a mode view declaration. 

1589 

1590 :param declaration: The mode view declaration. 

1591 """ 

1592 self._WriteEnd((ReservedWord.View,), declaration.Identifier) 

1593 

1594 def _WriteEnd(self, keywords: tuple[ReservedWord, ...], identifier: Nullable[str]) -> None: 

1595 """ 

1596 Leave the indented body and write the reserved word ``end``, the given reserved words and the identifier. 

1597 

1598 :param keywords: The reserved words after ``end``. 

1599 :param identifier: The identifier or label of the declaration or statement, or ``None`` if it has none. 

1600 """ 

1601 self._indentation -= 1 

1602 self._WriteEndLine(keywords, identifier) 

1603 

1604 def _WriteEndLine(self, keywords: tuple[ReservedWord, ...], identifier: Nullable[str]) -> None: 

1605 """ 

1606 Write the reserved word ``end``, the given reserved words and the identifier on a line of the current level. 

1607 

1608 :param keywords: The reserved words after ``end``. 

1609 :param identifier: The identifier or label of the declaration or statement, or ``None`` if it has none. 

1610 """ 

1611 self._WriteIndentation() 

1612 if identifier is None: 

1613 self._Write(f"{self._Keyword(ReservedWord.End)} {self._Keywords(keywords)};\n") 

1614 else: 

1615 self._Write(f"{self._Keyword(ReservedWord.End)} {self._Keywords(keywords)} {identifier};\n") 

1616 

1617 def VisitSimpleModeViewElement(self, element: SimpleModeViewElement) -> None: 

1618 """ 

1619 Write an element of a mode view with a mode. 

1620 

1621 **Format:** ``valid, data : out;`` 

1622 

1623 :param element: The mode view element. 

1624 :raises VHDLWriterError: If the mode view element has no mode. 

1625 """ 

1626 if element.Mode is Mode.Default: 

1627 raise VHDLWriterError("Mode view element has no mode.", element) 

1628 

1629 self._WriteIndentation() 

1630 self._Write(f"{', '.join(element.Identifiers)} : {self._Keyword(element.Mode.ReservedWord)};\n") 

1631 

1632 def VisitCompositeModeViewElement(self, element: CompositeModeViewElement) -> None: 

1633 """ 

1634 Write the identifiers and the reserved word ``view`` of an element of a mode view with a mode view. 

1635 

1636 **Format:** ``request : view master;`` 

1637 

1638 :param element: The mode view element. 

1639 """ 

1640 self._WriteIndentation() 

1641 self._Write(f"{', '.join(element.Identifiers)} : {self._Keyword(ReservedWord.View)} ") 

1642 

1643 def DepartCompositeModeViewElement(self, element: CompositeModeViewElement) -> None: 

1644 """ 

1645 Write the semicolon ending an element of a mode view with a mode view. 

1646 

1647 :param element: The mode view element. 

1648 """ 

1649 self._Write(";\n") 

1650 

1651 def VisitComponent(self, component: Component) -> None: 

1652 """ 

1653 Write the header of a component declaration; its generic and port clauses are indented. 

1654 

1655 **Format:** ``component counter is`` ... ``end component counter;`` 

1656 

1657 :param component: The component declaration. 

1658 """ 

1659 self._WriteIndentation() 

1660 self._Write(f"{self._Keyword(ReservedWord.Component)} {component.Identifier} {self._Keyword(ReservedWord.Is)}\n") 

1661 self._indentation += 1 

1662 

1663 def DepartComponent(self, component: Component) -> None: 

1664 """ 

1665 Write the end of a component declaration. 

1666 

1667 :param component: The component declaration. 

1668 """ 

1669 self._WriteEnd((ReservedWord.Component,), component.Identifier) 

1670 

1671 def VisitBox(self, arrayType: ArrayType) -> None: 

1672 """ 

1673 Write the reserved word ``range`` and the box (``<>``) of an unbounded index of an array type. 

1674 

1675 **Format:** ``natural range <>`` 

1676 

1677 :param arrayType: The array type. 

1678 """ 

1679 self._Write(f" {self._Keyword(ReservedWord.Range)} <>") 

1680 

1681 def VisitOf(self, arrayType: ArrayType) -> None: 

1682 """ 

1683 Write the reserved word ``of`` before the element subtype of an array type. 

1684 

1685 :param arrayType: The array type. 

1686 """ 

1687 self._Write(f" {self._Keyword(ReservedWord.Of)} ") 

1688 

1689 def VisitUnits(self, physicalType: PhysicalType) -> None: 

1690 """ 

1691 Write the reserved word ``units`` and the primary unit of a physical type on their own lines. 

1692 

1693 :param physicalType: The physical type. 

1694 """ 

1695 self._Write("\n") 

1696 self._indentation += 1 

1697 self._WriteIndentation() 

1698 self._Write(f"{self._Keyword(ReservedWord.Units)}\n") 

1699 self._indentation += 1 

1700 self._WriteIndentation() 

1701 self._Write(f"{physicalType.PrimaryUnit};\n") 

1702 

1703 def VisitSecondaryUnitDeclaration(self, physicalType: PhysicalType, identifier: str) -> None: 

1704 """ 

1705 Write the identifier of a secondary unit declaration. 

1706 

1707 **Format:** ``mm = 1000 um;`` 

1708 

1709 :param physicalType: The physical type. 

1710 :param identifier: The identifier of the secondary unit. 

1711 """ 

1712 self._WriteIndentation() 

1713 self._Write(f"{identifier} = ") 

1714 self._minimum = OperatorPrecedence.Range 

1715 

1716 def DepartSecondaryUnitDeclaration(self, physicalType: PhysicalType, identifier: str) -> None: 

1717 """ 

1718 Write the semicolon ending a secondary unit declaration. 

1719 

1720 :param physicalType: The physical type. 

1721 :param identifier: The identifier of the secondary unit. 

1722 """ 

1723 self._Write(";\n") 

1724 

1725 def VisitEntitySpecification(self, specification: AttributeSpecification) -> None: 

1726 """ 

1727 Write the reserved word ``of`` before the names of an attribute specification. 

1728 

1729 :param specification: The attribute specification. 

1730 """ 

1731 self._Write(f" {self._Keyword(ReservedWord.Of)} ") 

1732 

1733 def DepartEntitySpecification(self, specification: AttributeSpecification) -> None: 

1734 """ 

1735 Write the entity class after the names of an attribute specification. 

1736 

1737 :param specification: The attribute specification. 

1738 """ 

1739 self._Write(f" : {self._Keyword(specification.EntityClass.ReservedWord)}") 

1740 

1741 def VisitAnonymousType(self, declaration: AnonymousType) -> None: 

1742 """ 

1743 Write an incomplete type declaration. 

1744 

1745 **Format:** ``type node;`` 

1746 

1747 :param declaration: The incomplete type declaration. 

1748 """ 

1749 self._WriteIndentation() 

1750 self._Write(f"{self._Keyword(ReservedWord.Type)} {declaration.Identifier};\n") 

1751 

1752 def VisitSubtype(self, subtype: Subtype) -> None: 

1753 """ 

1754 Write the reserved word ``subtype``, the identifier and the reserved word ``is`` of a subtype declaration. 

1755 

1756 **Format:** ``subtype byte is bit_vector(7 downto 0);`` 

1757 

1758 The model's resolution function of a subtype is not written. 

1759 

1760 :param subtype: The subtype declaration. 

1761 """ 

1762 self._WriteIndentation() 

1763 self._Write(f"{self._Keyword(ReservedWord.Subtype)} {subtype.Identifier} {self._Keyword(ReservedWord.Is)} ") 

1764 

1765 def DepartSubtype(self, subtype: Subtype) -> None: 

1766 """ 

1767 Write the semicolon ending a subtype declaration. 

1768 

1769 :param subtype: The subtype declaration. 

1770 """ 

1771 self._Write(";\n") 

1772 

1773 def VisitEnumeratedType(self, enumeratedType: EnumeratedType) -> None: 

1774 """ 

1775 Write the header and the left parenthesis of an enumerated type declaration. 

1776 

1777 **Format:** ``type state is (Idle, Busy, Done);`` 

1778 

1779 :param enumeratedType: The enumerated type. 

1780 """ 

1781 self._WriteTypeHeader(enumeratedType) 

1782 self._Write("(") 

1783 

1784 def _WriteTypeHeader(self, declaration: FullType) -> None: 

1785 """ 

1786 Write the indentation, the reserved word ``type``, the identifier and the reserved word ``is`` of a type. 

1787 

1788 :param declaration: The type declaration. 

1789 """ 

1790 self._WriteIndentation() 

1791 self._Write(f"{self._Keyword(ReservedWord.Type)} {declaration.Identifier} {self._Keyword(ReservedWord.Is)} ") 

1792 

1793 def DepartEnumeratedType(self, enumeratedType: EnumeratedType) -> None: 

1794 """ 

1795 Write the right parenthesis ending an enumerated type declaration. 

1796 

1797 :param enumeratedType: The enumerated type. 

1798 """ 

1799 self._Write(");\n") 

1800 

1801 def VisitIntegerType(self, integerType: IntegerType) -> None: 

1802 """ 

1803 Write the header and the reserved word ``range`` of an integer type declaration. 

1804 

1805 **Format:** ``type nibble is range 0 to 15;`` 

1806 

1807 :param integerType: The integer type. 

1808 """ 

1809 self._WriteTypeHeader(integerType) 

1810 self._Write(f"{self._Keyword(ReservedWord.Range)} ") 

1811 self._minimum = OperatorPrecedence.Range 

1812 

1813 def DepartIntegerType(self, integerType: IntegerType) -> None: 

1814 """ 

1815 Write the semicolon ending an integer type declaration. 

1816 

1817 :param integerType: The integer type. 

1818 """ 

1819 self._Write(";\n") 

1820 

1821 def VisitRealType(self, realType: RealType) -> None: 

1822 """ 

1823 Write the header and the reserved word ``range`` of a floating-point type declaration. 

1824 

1825 **Format:** ``type fraction is range 0.0 to 1.0;`` 

1826 

1827 :param realType: The floating-point type. 

1828 """ 

1829 self._WriteTypeHeader(realType) 

1830 self._Write(f"{self._Keyword(ReservedWord.Range)} ") 

1831 self._minimum = OperatorPrecedence.Range 

1832 

1833 def DepartRealType(self, realType: RealType) -> None: 

1834 """ 

1835 Write the semicolon ending a floating-point type declaration. 

1836 

1837 :param realType: The floating-point type. 

1838 """ 

1839 self._Write(";\n") 

1840 

1841 def VisitPhysicalType(self, physicalType: PhysicalType) -> None: 

1842 """ 

1843 Write the header and the reserved word ``range`` of a physical type declaration; its units are indented. 

1844 

1845 **Format:** ``type distance is range 0 to 1000000`` ... ``units`` ... ``end units distance;`` 

1846 

1847 :param physicalType: The physical type. 

1848 """ 

1849 self._WriteTypeHeader(physicalType) 

1850 self._Write(f"{self._Keyword(ReservedWord.Range)} ") 

1851 self._minimum = OperatorPrecedence.Range 

1852 

1853 def DepartPhysicalType(self, physicalType: PhysicalType) -> None: 

1854 """ 

1855 Write the end of the units of a physical type declaration. 

1856 

1857 :param physicalType: The physical type. 

1858 """ 

1859 self._WriteEnd((ReservedWord.Units,), physicalType.Identifier) 

1860 self._indentation -= 1 

1861 

1862 def VisitArrayType(self, arrayType: ArrayType) -> None: 

1863 """ 

1864 Write the header and the reserved word ``array`` of an array type declaration. 

1865 

1866 **Format:** ``type memory is array (0 to 255) of byte;`` or ``type bits is array (natural range <>) of bit;`` 

1867 

1868 :param arrayType: The array type. 

1869 """ 

1870 self._WriteTypeHeader(arrayType) 

1871 self._Write(f"{self._Keyword(ReservedWord.Array)} ") 

1872 

1873 def DepartArrayType(self, arrayType: ArrayType) -> None: 

1874 """ 

1875 Write the semicolon ending an array type declaration. 

1876 

1877 :param arrayType: The array type. 

1878 """ 

1879 self._Write(";\n") 

1880 

1881 def VisitRecordType(self, recordType: RecordType) -> None: 

1882 """ 

1883 Write the header of a record type declaration; its element declarations are indented. 

1884 

1885 **Format:** ``type frame is record`` ... ``end record frame;`` 

1886 

1887 :param recordType: The record type. 

1888 """ 

1889 self._WriteTypeHeader(recordType) 

1890 self._Write(f"{self._Keyword(ReservedWord.Record)}\n") 

1891 self._indentation += 1 

1892 

1893 def DepartRecordType(self, recordType: RecordType) -> None: 

1894 """ 

1895 Write the end of a record type declaration. 

1896 

1897 :param recordType: The record type. 

1898 """ 

1899 self._WriteEnd((ReservedWord.Record,), recordType.Identifier) 

1900 

1901 def VisitRecordTypeElement(self, element: RecordTypeElement) -> None: 

1902 """ 

1903 Write the identifiers of an element declaration of a record type. 

1904 

1905 **Format:** ``valid, last : bit;`` 

1906 

1907 :param element: The record element declaration. 

1908 """ 

1909 self._WriteIndentation() 

1910 self._Write(f"{', '.join(element.Identifiers)} : ") 

1911 

1912 def DepartRecordTypeElement(self, element: RecordTypeElement) -> None: 

1913 """ 

1914 Write the semicolon ending an element declaration of a record type. 

1915 

1916 :param element: The record element declaration. 

1917 """ 

1918 self._Write(";\n") 

1919 

1920 def VisitAccessType(self, accessType: AccessType) -> None: 

1921 """ 

1922 Write the header and the reserved word ``access`` of an access type declaration. 

1923 

1924 **Format:** ``type pointer is access node;`` 

1925 

1926 :param accessType: The access type. 

1927 """ 

1928 self._WriteTypeHeader(accessType) 

1929 self._Write(f"{self._Keyword(ReservedWord.Access)} ") 

1930 

1931 def DepartAccessType(self, accessType: AccessType) -> None: 

1932 """ 

1933 Write the semicolon ending an access type declaration. 

1934 

1935 :param accessType: The access type. 

1936 """ 

1937 self._Write(";\n") 

1938 

1939 def VisitFileType(self, fileType: FileType) -> None: 

1940 """ 

1941 Write the header and the reserved words ``file of`` of a file type declaration. 

1942 

1943 **Format:** ``type text_file is file of string;`` 

1944 

1945 :param fileType: The file type. 

1946 """ 

1947 self._WriteTypeHeader(fileType) 

1948 self._Write(f"{self._Keyword(ReservedWord.File)} {self._Keyword(ReservedWord.Of)} ") 

1949 

1950 def DepartFileType(self, fileType: FileType) -> None: 

1951 """ 

1952 Write the semicolon ending a file type declaration. 

1953 

1954 :param fileType: The file type. 

1955 """ 

1956 self._Write(";\n") 

1957 

1958 def VisitAlias(self, alias: Alias) -> None: 

1959 """ 

1960 Write the reserved word ``alias`` and the identifier of an alias declaration. 

1961 

1962 **Format:** ``alias low : bit_vector(3 downto 0) is data(3 downto 0);`` or ``alias clock is clk;`` 

1963 

1964 :param alias: The alias declaration. 

1965 """ 

1966 self._WriteIndentation() 

1967 self._Write(f"{self._Keyword(ReservedWord.Alias)} {alias.Identifier}") 

1968 if alias.Subtype is not None: 

1969 self._Write(" : ") 

1970 

1971 def DepartAlias(self, alias: Alias) -> None: 

1972 """ 

1973 Write the semicolon ending an alias declaration. 

1974 

1975 :param alias: The alias declaration. 

1976 """ 

1977 self._Write(";\n") 

1978 

1979 def VisitAttribute(self, attribute: Attribute) -> None: 

1980 """ 

1981 Write the reserved word ``attribute`` and the identifier of an attribute declaration. 

1982 

1983 **Format:** ``attribute keep : boolean;`` 

1984 

1985 :param attribute: The attribute declaration. 

1986 """ 

1987 self._WriteIndentation() 

1988 self._Write(f"{self._Keyword(ReservedWord.Attribute)} {attribute.Identifier} : ") 

1989 

1990 def DepartAttribute(self, attribute: Attribute) -> None: 

1991 """ 

1992 Write the semicolon ending an attribute declaration. 

1993 

1994 :param attribute: The attribute declaration. 

1995 """ 

1996 self._Write(";\n") 

1997 

1998 def VisitAttributeSpecification(self, specification: AttributeSpecification) -> None: 

1999 """ 

2000 Write the reserved word ``attribute`` of an attribute specification. 

2001 

2002 **Format:** ``attribute keep of valid, ready : signal is true;`` 

2003 

2004 :param specification: The attribute specification. 

2005 :raises VHDLWriterError: If the entity class is ``EntityClass.Others``. 

2006 """ 

2007 if specification.EntityClass is EntityClass.Others: 

2008 raise VHDLWriterError("Entity class 'Others' has no VHDL notation.", specification) 

2009 

2010 self._WriteIndentation() 

2011 self._Write(f"{self._Keyword(ReservedWord.Attribute)} ") 

2012 

2013 def DepartAttributeSpecification(self, specification: AttributeSpecification) -> None: 

2014 """ 

2015 Write the semicolon ending an attribute specification. 

2016 

2017 :param specification: The attribute specification. 

2018 """ 

2019 self._Write(";\n") 

2020 

2021 def VisitBegin( 

2022 self, 

2023 element: Subprogram | Entity | Architecture | ProcessStatement | ConcurrentBlockStatement | GenerateBranch | 

2024 ConcurrentCase | ForGenerateStatement 

2025 ) -> None: 

2026 """ 

2027 Write the reserved word ``begin`` before the statement part on its own line. 

2028 

2029 A subprogram declaration, an entity without statements and the body of a generate statement without declared items 

2030 have no ``begin``. 

2031 

2032 :param element: The element with a statement part. 

2033 """ 

2034 if isinstance(element, Subprogram) and not self._IsSubprogramBody(element): 

2035 return 

2036 elif isinstance(element, Entity) and len(element.Statements) == 0: 

2037 return 

2038 elif isinstance(element, (GenerateBranch, ConcurrentCase, ForGenerateStatement)): 

2039 if len(element.DeclaredItems) == 0: 

2040 return 

2041 

2042 self._indentation -= 1 

2043 self._WriteIndentation() 

2044 self._Write(f"{self._Keyword(ReservedWord.Begin)}\n") 

2045 self._indentation += 1 

2046 

2047 @staticmethod 

2048 def _IsSubprogramBody(subprogram: Subprogram) -> bool: 

2049 """ 

2050 Check if a subprogram is written as a subprogram body. 

2051 

2052 A subprogram is a body, if it has declared items or statements, or if its parent is neither a package declaration 

2053 nor a protected type declaration (e.g. a package body or an architecture). 

2054 

2055 :param subprogram: The subprogram. 

2056 :returns: ``True``, if the subprogram is written as a subprogram body. 

2057 """ 

2058 if len(subprogram.DeclaredItems) > 0 or len(subprogram.Statements) > 0: 

2059 return True 

2060 

2061 return subprogram.Parent is not None and not isinstance(subprogram.Parent, (Package, ProtectedType)) 

2062 

2063 def VisitReturn(self, function: Function | GenericFunctionInterfaceItem) -> None: 

2064 """ 

2065 Write the reserved word ``return`` before the return type of a function. 

2066 

2067 :param function: The function. 

2068 """ 

2069 self._Write(f" {self._Keyword(ReservedWord.Return)} ") 

2070 

2071 def VisitFormalParameterList(self, element: WithParametersMixin) -> None: 

2072 """ 

2073 Write the left parenthesis of a formal parameter list; each parameter is on its own line. 

2074 

2075 **Format:** ``procedure p (`` ... ``)`` 

2076 

2077 After a generic clause, the reserved word ``parameter`` precedes the left parenthesis. 

2078 

2079 :param element: The element with parameters. 

2080 """ 

2081 if isinstance(element, WithGenericsMixin) and len(element.GenericItems) > 0: 

2082 self._Write(f" {self._Keyword(ReservedWord.Parameter)} (\n") 

2083 else: 

2084 self._Write(" (\n") 

2085 

2086 self._indentation += 1 

2087 self._WriteIndentation() 

2088 

2089 def DepartFormalParameterList(self, element: WithParametersMixin) -> None: 

2090 """ 

2091 Write the right parenthesis of a formal parameter list on its own line. 

2092 

2093 :param element: The element with parameters. 

2094 """ 

2095 self._WriteClosingParenthesis("") 

2096 

2097 def VisitGenericMapAspect(self, element: GenericMapAspectMixin) -> None: 

2098 """ 

2099 Write the reserved words ``generic map`` and the left parenthesis on a new line; each association is on its own 

2100 line. 

2101 

2102 **Format:** ``generic map (`` ... ``)`` 

2103 

2104 The generic map aspect of a block statement is written like its generic clause and ends with a semicolon. 

2105 

2106 :param element: The element with a generic map aspect. 

2107 """ 

2108 self._WriteMapAspect(ReservedWord.Generic, element) 

2109 

2110 def _WriteMapAspect(self, keyword: ReservedWord, element: GenericMapAspectMixin | PortMapAspectMixin) -> None: 

2111 """ 

2112 Write the reserved words of a map aspect and the left parenthesis on a new line, one indentation level deeper. 

2113 

2114 In a block statement, the map aspect starts its own line at the block header's indentation level. 

2115 

2116 :param keyword: The reserved word ``generic`` or ``port``. 

2117 :param element: The element with the map aspect. 

2118 """ 

2119 if not isinstance(element, ConcurrentBlockStatement): 

2120 self._Write("\n") 

2121 self._indentation += 1 

2122 

2123 self._WriteIndentation() 

2124 self._Write(f"{self._Keyword(keyword)} {self._Keyword(ReservedWord.Map)} (\n") 

2125 self._indentation += 1 

2126 self._WriteIndentation() 

2127 

2128 def DepartGenericMapAspect(self, element: GenericMapAspectMixin) -> None: 

2129 """ 

2130 Write the right parenthesis of a generic map aspect on its own line. 

2131 

2132 :param element: The element with a generic map aspect. 

2133 """ 

2134 self._WriteMapAspectEnd(element) 

2135 

2136 def _WriteMapAspectEnd(self, element: GenericMapAspectMixin | PortMapAspectMixin) -> None: 

2137 """ 

2138 Write the right parenthesis of a map aspect on its own line and leave its indentation level. 

2139 

2140 In a block statement, a semicolon follows the right parenthesis. 

2141 

2142 :param element: The element with the map aspect. 

2143 """ 

2144 if isinstance(element, ConcurrentBlockStatement): 

2145 self._WriteClosingParenthesis(";\n") 

2146 else: 

2147 self._WriteClosingParenthesis("") 

2148 self._indentation -= 1 

2149 

2150 def VisitProcedure(self, procedure: Procedure) -> None: 

2151 """ 

2152 Write the reserved word ``procedure`` and the designator of a procedure declaration or body. 

2153 

2154 **Format:** ``procedure reset;`` or ``procedure reset is`` ... ``begin`` ... ``end procedure reset;`` 

2155 

2156 A procedure without declared items and statements is written as a procedure declaration. 

2157 

2158 :param procedure: The procedure. 

2159 """ 

2160 self._WriteIndentation() 

2161 self._Write(f"{self._Keyword(ReservedWord.Procedure)} {procedure.Identifier}") 

2162 

2163 def DepartProcedure(self, procedure: Procedure) -> None: 

2164 """ 

2165 Write the semicolon ending a procedure declaration, or the end of a procedure body. 

2166 

2167 :param procedure: The procedure. 

2168 """ 

2169 if self._IsSubprogramBody(procedure): 

2170 self._WriteEnd((ReservedWord.Procedure,), procedure.Identifier) 

2171 else: 

2172 self._Write(";\n") 

2173 

2174 def VisitFunction(self, function: Function) -> None: 

2175 """ 

2176 Write the reserved word ``impure``, if impure, ``function`` and the designator of a function declaration or body. 

2177 

2178 **Format:** ``function parity return bit;`` or ``function parity return bit is`` ... ``end function parity;`` 

2179 

2180 A function without declared items and statements is written as a function declaration. 

2181 

2182 :param function: The function. 

2183 """ 

2184 self._WriteIndentation() 

2185 self._WriteFunctionDesignator(function) 

2186 

2187 def _WriteFunctionDesignator(self, function: Function) -> None: 

2188 """ 

2189 Write the reserved word ``impure``, if impure, the reserved word ``function`` and the designator of a function. 

2190 

2191 :param function: The function. 

2192 """ 

2193 if not function.IsPure: 

2194 self._Write(f"{self._Keyword(ReservedWord.Impure)} ") 

2195 

2196 self._Write(f"{self._Keyword(ReservedWord.Function)} {function.Identifier}") 

2197 

2198 def DepartFunction(self, function: Function) -> None: 

2199 """ 

2200 Write the semicolon ending a function declaration, or the end of a function body. 

2201 

2202 :param function: The function. 

2203 """ 

2204 if self._IsSubprogramBody(function): 

2205 self._WriteEnd((ReservedWord.Function,), function.Identifier) 

2206 else: 

2207 self._Write(";\n") 

2208 

2209 def VisitGenericProcedureInterfaceItem(self, item: GenericProcedureInterfaceItem) -> None: 

2210 """ 

2211 Write the reserved word ``procedure`` and the designator of a generic procedure. 

2212 

2213 **Format:** ``procedure log (`` ... ``)`` 

2214 

2215 :param item: The generic procedure. 

2216 """ 

2217 self._Write(f"{self._Keyword(ReservedWord.Procedure)} {item.Identifier}") 

2218 

2219 def VisitGenericFunctionInterfaceItem(self, item: GenericFunctionInterfaceItem) -> None: 

2220 """ 

2221 Write the reserved word ``impure``, if impure, ``function`` and the designator of a generic function. 

2222 

2223 **Format:** ``function compare (`` ... ``) return boolean`` 

2224 

2225 :param item: The generic function. 

2226 """ 

2227 self._WriteFunctionDesignator(item) 

2228 

2229 def VisitProcedureInstantiation(self, instantiation: ProcedureInstantiation) -> None: 

2230 """ 

2231 Write the reserved word ``procedure``, the designator and the reserved words ``is new`` of a procedure 

2232 instantiation. 

2233 

2234 **Format:** ``procedure log_byte is new log`` ... ``;`` 

2235 

2236 :param instantiation: The procedure instantiation. 

2237 """ 

2238 self._WriteIndentation() 

2239 self._Write(f"{self._Keyword(ReservedWord.Procedure)} {instantiation.Identifier} ") 

2240 self._Write(f"{self._Keyword(ReservedWord.Is)} {self._Keyword(ReservedWord.New)} ") 

2241 

2242 def DepartProcedureInstantiation(self, instantiation: ProcedureInstantiation) -> None: 

2243 """ 

2244 Write the semicolon ending a procedure instantiation. 

2245 

2246 :param instantiation: The procedure instantiation. 

2247 """ 

2248 self._Write(";\n") 

2249 

2250 def VisitFunctionInstantiation(self, instantiation: FunctionInstantiation) -> None: 

2251 """ 

2252 Write the reserved word ``function``, the designator and the reserved words ``is new`` of a function instantiation. 

2253 

2254 **Format:** ``function maximum_byte is new maximum`` ... ``;`` 

2255 

2256 :param instantiation: The function instantiation. 

2257 """ 

2258 self._WriteIndentation() 

2259 self._Write(f"{self._Keyword(ReservedWord.Function)} {instantiation.Identifier} ") 

2260 self._Write(f"{self._Keyword(ReservedWord.Is)} {self._Keyword(ReservedWord.New)} ") 

2261 

2262 def DepartFunctionInstantiation(self, instantiation: FunctionInstantiation) -> None: 

2263 """ 

2264 Write the semicolon ending a function instantiation. 

2265 

2266 :param instantiation: The function instantiation. 

2267 """ 

2268 self._Write(";\n") 

2269 

2270 def VisitProtectedType(self, protectedType: ProtectedType) -> None: 

2271 """ 

2272 Write the header of a protected type declaration; its methods are indented. 

2273 

2274 **Format:** ``type counter is protected`` ... ``end protected counter;`` 

2275 

2276 :param protectedType: The protected type. 

2277 """ 

2278 self._WriteTypeHeader(protectedType) 

2279 self._Write(f"{self._Keyword(ReservedWord.Protected)}\n") 

2280 self._indentation += 1 

2281 

2282 def DepartProtectedType(self, protectedType: ProtectedType) -> None: 

2283 """ 

2284 Write the end of a protected type declaration. 

2285 

2286 :param protectedType: The protected type. 

2287 """ 

2288 self._WriteEnd((ReservedWord.Protected,), protectedType.Identifier) 

2289 

2290 def VisitProtectedTypeBody(self, body: ProtectedTypeBody) -> None: 

2291 """ 

2292 Write the header of a protected type body; its declared items are indented. 

2293 

2294 **Format:** ``type counter is protected body`` ... ``end protected body counter;`` 

2295 

2296 :param body: The protected type body. 

2297 """ 

2298 self._WriteTypeHeader(body) 

2299 self._Write(f"{self._Keyword(ReservedWord.Protected)} {self._Keyword(ReservedWord.Body)}\n") 

2300 self._indentation += 1 

2301 

2302 def DepartProtectedTypeBody(self, body: ProtectedTypeBody) -> None: 

2303 """ 

2304 Write the end of a protected type body. 

2305 

2306 :param body: The protected type body. 

2307 """ 

2308 self._WriteEnd((ReservedWord.Protected, ReservedWord.Body), body.Identifier) 

2309 

2310 def VisitPortMapAspect(self, element: PortMapAspectMixin) -> None: 

2311 """ 

2312 Write the reserved words ``port map`` and the left parenthesis on a new line; each association is on its own line. 

2313 

2314 **Format:** ``port map (`` ... ``)`` 

2315 

2316 :param element: The element with a port map aspect. 

2317 """ 

2318 self._WriteMapAspect(ReservedWord.Port, element) 

2319 

2320 def DepartPortMapAspect(self, element: PortMapAspectMixin) -> None: 

2321 """ 

2322 Write the right parenthesis of a port map aspect on its own line. 

2323 

2324 :param element: The element with a port map aspect. 

2325 """ 

2326 self._WriteMapAspectEnd(element) 

2327 

2328 def VisitContextClause(self, designUnit: DesignUnit) -> None: 

2329 """ 

2330 Separate a design unit by a blank line from the text written before it. 

2331 

2332 :param designUnit: The design unit. 

2333 """ 

2334 if len(self._buffer) > 0: 

2335 self._Write("\n") 

2336 

2337 def DepartContextClause(self, designUnit: DesignUnit) -> None: 

2338 """ 

2339 Separate the context items of a design unit by a blank line from the design unit. 

2340 

2341 :param designUnit: The design unit. 

2342 """ 

2343 if len(designUnit.ContextItems) > 0: 

2344 self._Write("\n") 

2345 

2346 def VisitLibraryClause(self, clause: LibraryClause) -> None: 

2347 """ 

2348 Write the reserved word ``library`` of a library clause. 

2349 

2350 **Format:** ``library ieee;`` 

2351 

2352 :param clause: The library clause. 

2353 """ 

2354 self._WriteIndentation() 

2355 self._Write(f"{self._Keyword(ReservedWord.Library)} ") 

2356 

2357 def DepartLibraryClause(self, clause: LibraryClause) -> None: 

2358 """ 

2359 Write the semicolon ending a library clause. 

2360 

2361 :param clause: The library clause. 

2362 """ 

2363 self._Write(";\n") 

2364 

2365 def VisitUseClause(self, clause: UseClause) -> None: 

2366 """ 

2367 Write the reserved word ``use`` of a use clause. 

2368 

2369 **Format:** ``use ieee.numeric_std.all;`` 

2370 

2371 :param clause: The use clause. 

2372 """ 

2373 self._WriteIndentation() 

2374 self._Write(f"{self._Keyword(ReservedWord.Use)} ") 

2375 

2376 def DepartUseClause(self, clause: UseClause) -> None: 

2377 """ 

2378 Write the semicolon ending a use clause. 

2379 

2380 :param clause: The use clause. 

2381 """ 

2382 self._Write(";\n") 

2383 

2384 def VisitContextReference(self, reference: ContextReference) -> None: 

2385 """ 

2386 Write the reserved word ``context`` of a context reference. 

2387 

2388 **Format:** ``context ieee.ieee_std_context;`` 

2389 

2390 :param reference: The context reference. 

2391 """ 

2392 self._WriteIndentation() 

2393 self._Write(f"{self._Keyword(ReservedWord.Context)} ") 

2394 

2395 def DepartContextReference(self, reference: ContextReference) -> None: 

2396 """ 

2397 Write the semicolon ending a context reference. 

2398 

2399 :param reference: The context reference. 

2400 """ 

2401 self._Write(";\n") 

2402 

2403 def VisitContext(self, context: Context) -> None: 

2404 """ 

2405 Write the header of a context declaration; its context items are indented. 

2406 

2407 **Format:** ``context project is`` ... ``end context project;`` 

2408 

2409 :param context: The context declaration. 

2410 """ 

2411 self._WriteUnitHeader((ReservedWord.Context,), context.Identifier) 

2412 

2413 def _WriteUnitHeader(self, keywords: tuple[ReservedWord, ...], identifier: str) -> None: 

2414 """ 

2415 Write the reserved words, the identifier and the reserved word ``is`` of a header; the body is indented. 

2416 

2417 :param keywords: The reserved words before the identifier. 

2418 :param identifier: The identifier. 

2419 """ 

2420 self._WriteIndentation() 

2421 self._Write(f"{self._Keywords(keywords)} {identifier} {self._Keyword(ReservedWord.Is)}\n") 

2422 self._indentation += 1 

2423 

2424 def DepartContext(self, context: Context) -> None: 

2425 """ 

2426 Write the end of a context declaration. 

2427 

2428 :param context: The context declaration. 

2429 """ 

2430 self._WriteEnd((ReservedWord.Context,), context.Identifier) 

2431 

2432 def VisitPackage(self, package: Package) -> None: 

2433 """ 

2434 Write the header of a package declaration; its generic clause and declared items are indented. 

2435 

2436 **Format:** ``package utilities is`` ... ``end package utilities;`` 

2437 

2438 :param package: The package declaration. 

2439 """ 

2440 self._WriteUnitHeader((ReservedWord.Package,), package.Identifier) 

2441 

2442 def DepartPackage(self, package: Package) -> None: 

2443 """ 

2444 Write the end of a package declaration. 

2445 

2446 :param package: The package declaration. 

2447 """ 

2448 self._WriteEnd((ReservedWord.Package,), package.Identifier) 

2449 

2450 def VisitPackageBody(self, body: PackageBody) -> None: 

2451 """ 

2452 Write the header of a package body; its declared items are indented. 

2453 

2454 **Format:** ``package body utilities is`` ... ``end package body utilities;`` 

2455 

2456 :param body: The package body. 

2457 """ 

2458 self._WriteUnitHeader((ReservedWord.Package, ReservedWord.Body), body.Identifier) 

2459 

2460 def DepartPackageBody(self, body: PackageBody) -> None: 

2461 """ 

2462 Write the end of a package body. 

2463 

2464 :param body: The package body. 

2465 """ 

2466 self._WriteEnd((ReservedWord.Package, ReservedWord.Body), body.Identifier) 

2467 

2468 def VisitPackageInstantiation(self, instantiation: PackageInstantiation) -> None: 

2469 """ 

2470 Write the reserved word ``package``, the identifier and the reserved words ``is new`` of a package instantiation. 

2471 

2472 **Format:** ``package fifo_byte is new work.fifo`` ... ``;`` 

2473 

2474 :param instantiation: The package instantiation. 

2475 """ 

2476 self._WriteIndentation() 

2477 self._Write(f"{self._Keyword(ReservedWord.Package)} {instantiation.Identifier} ") 

2478 self._Write(f"{self._Keywords((ReservedWord.Is, ReservedWord.New))} ") 

2479 

2480 def DepartPackageInstantiation(self, instantiation: PackageInstantiation) -> None: 

2481 """ 

2482 Write the semicolon ending a package instantiation. 

2483 

2484 :param instantiation: The package instantiation. 

2485 """ 

2486 self._Write(";\n") 

2487 

2488 def VisitEntity(self, entity: Entity) -> None: 

2489 """ 

2490 Write the header of an entity declaration; its generic and port clauses and its declared items are indented. 

2491 

2492 **Format:** ``entity counter is`` ... ``end entity counter;`` 

2493 

2494 :param entity: The entity declaration. 

2495 """ 

2496 self._WriteUnitHeader((ReservedWord.Entity,), entity.Identifier) 

2497 

2498 def DepartEntity(self, entity: Entity) -> None: 

2499 """ 

2500 Write the end of an entity declaration. 

2501 

2502 :param entity: The entity declaration. 

2503 """ 

2504 self._WriteEnd((ReservedWord.Entity,), entity.Identifier) 

2505 

2506 def VisitArchitecture(self, architecture: Architecture) -> None: 

2507 """ 

2508 Write the reserved word ``architecture``, the identifier and the reserved word ``of`` of an architecture body. 

2509 

2510 **Format:** ``architecture rtl of counter is`` ... ``begin`` ... ``end architecture rtl;`` 

2511 

2512 :param architecture: The architecture body. 

2513 """ 

2514 self._WriteIndentation() 

2515 self._Write(f"{self._Keyword(ReservedWord.Architecture)} {architecture.Identifier} ") 

2516 self._Write(f"{self._Keyword(ReservedWord.Of)} ") 

2517 

2518 def DepartArchitecture(self, architecture: Architecture) -> None: 

2519 """ 

2520 Write the end of an architecture body. 

2521 

2522 :param architecture: The architecture body. 

2523 """ 

2524 self._WriteEnd((ReservedWord.Architecture,), architecture.Identifier) 

2525 

2526 def VisitConfiguration(self, configuration: Configuration) -> None: 

2527 """ 

2528 Write the reserved word ``configuration``, the identifier and the reserved word ``of`` of a configuration. 

2529 

2530 **Format:** ``configuration counter_cfg of counter is`` ... ``end configuration counter_cfg;`` 

2531 

2532 :param configuration: The configuration declaration. 

2533 """ 

2534 self._WriteIndentation() 

2535 self._Write(f"{self._Keyword(ReservedWord.Configuration)} {configuration.Identifier} ") 

2536 self._Write(f"{self._Keyword(ReservedWord.Of)} ") 

2537 

2538 def DepartConfiguration(self, configuration: Configuration) -> None: 

2539 """ 

2540 Write the end of a configuration declaration. 

2541 

2542 :param configuration: The configuration declaration. 

2543 """ 

2544 self._WriteEnd((ReservedWord.Configuration,), configuration.Identifier) 

2545 

2546 def VisitBlockConfiguration(self, configuration: BlockConfiguration) -> None: 

2547 """ 

2548 Write the reserved word ``for`` of a block configuration; its nested configurations are indented. 

2549 

2550 **Format:** ``for rtl`` ... ``end for;`` 

2551 

2552 :param configuration: The block configuration. 

2553 """ 

2554 self._WriteIndentation() 

2555 self._Write(f"{self._Keyword(ReservedWord.For)} ") 

2556 

2557 def DepartBlockSpecification(self, configuration: BlockConfiguration) -> None: 

2558 """ 

2559 End the line of a block specification; the nested configurations are indented. 

2560 

2561 :param configuration: The block configuration. 

2562 """ 

2563 self._Write("\n") 

2564 self._indentation += 1 

2565 

2566 def DepartBlockConfiguration(self, configuration: BlockConfiguration) -> None: 

2567 """ 

2568 Write the end of a block configuration. 

2569 

2570 :param configuration: The block configuration. 

2571 """ 

2572 self._indentation -= 1 

2573 self._WriteIndentation() 

2574 self._Write(f"{self._Keyword(ReservedWord.End)} {self._Keyword(ReservedWord.For)};\n") 

2575 

2576 def VisitComponentConfiguration(self, configuration: ComponentConfiguration) -> None: 

2577 """ 

2578 Write the reserved word ``for`` of a component configuration. 

2579 

2580 **Format:** ``for all : counter use entity work.counter(rtl);`` ... ``end for;`` 

2581 

2582 :param configuration: The component configuration. 

2583 """ 

2584 self._WriteIndentation() 

2585 self._Write(f"{self._Keyword(ReservedWord.For)} ") 

2586 

2587 def DepartInstantiationList(self, configuration: ComponentConfiguration) -> None: 

2588 """ 

2589 Write the colon between the instantiation list and the component name of a component configuration. 

2590 

2591 :param configuration: The component configuration. 

2592 """ 

2593 self._Write(" : ") 

2594 

2595 def DepartComponentConfiguration(self, configuration: ComponentConfiguration) -> None: 

2596 """ 

2597 Write the end of a component configuration on its own line. 

2598 

2599 :param configuration: The component configuration. 

2600 """ 

2601 self._Write("\n") 

2602 self._WriteIndentation() 

2603 self._Write(f"{self._Keyword(ReservedWord.End)} {self._Keyword(ReservedWord.For)};\n") 

2604 

2605 def VisitBindingIndication(self, indication: BindingIndication) -> None: 

2606 """ 

2607 Write the reserved word ``use`` of a binding indication on a new line, one indentation level deeper. 

2608 

2609 **Format:** ``use entity work.counter(rtl)`` ... ``;`` 

2610 

2611 :param indication: The binding indication. 

2612 """ 

2613 self._indentation += 1 

2614 if indication.EntityAspect is not None: 2614 ↛ exitline 2614 didn't return from function 'VisitBindingIndication' because the condition on line 2614 was always true

2615 self._Write("\n") 

2616 self._WriteIndentation() 

2617 self._Write(f"{self._Keyword(ReservedWord.Use)} ") 

2618 

2619 def DepartBindingIndication(self, indication: BindingIndication) -> None: 

2620 """ 

2621 Write the semicolon ending a binding indication. 

2622 

2623 :param indication: The binding indication. 

2624 """ 

2625 self._Write(";") 

2626 self._indentation -= 1 

2627 

2628 def VisitEntityAspectEntity(self, aspect: EntityAspectEntity) -> None: 

2629 """ 

2630 Write the reserved word ``entity`` of an entity aspect naming an entity. 

2631 

2632 **Format:** ``entity work.counter(rtl)`` 

2633 

2634 :param aspect: The entity aspect. 

2635 """ 

2636 self._Write(f"{self._Keyword(ReservedWord.Entity)} ") 

2637 

2638 def VisitEntityAspectConfiguration(self, aspect: EntityAspectConfiguration) -> None: 

2639 """ 

2640 Write the reserved word ``configuration`` of an entity aspect naming a configuration. 

2641 

2642 **Format:** ``configuration work.counter_cfg`` 

2643 

2644 :param aspect: The entity aspect. 

2645 """ 

2646 self._Write(f"{self._Keyword(ReservedWord.Configuration)} ") 

2647 

2648 def VisitEntityAspectOpen(self, aspect: EntityAspectOpen) -> None: 

2649 """ 

2650 Write the reserved word ``open`` of an open entity aspect. 

2651 

2652 **Format:** ``open`` 

2653 

2654 :param aspect: The entity aspect. 

2655 """ 

2656 self._Write(self._Keyword(ReservedWord.Open)) 

2657 

2658 def VisitAllInstantiationList(self, instantiationList: AllInstantiationList) -> None: 

2659 """ 

2660 Write the reserved word ``all`` of an instantiation list. 

2661 

2662 **Format:** ``all`` 

2663 

2664 :param instantiationList: The instantiation list. 

2665 """ 

2666 self._Write(self._Keyword(ReservedWord.All)) 

2667 

2668 def VisitOthersInstantiationList(self, instantiationList: OthersInstantiationList) -> None: 

2669 """ 

2670 Write the reserved word ``others`` of an instantiation list. 

2671 

2672 **Format:** ``others`` 

2673 

2674 :param instantiationList: The instantiation list. 

2675 """ 

2676 self._Write(self._Keyword(ReservedWord.Others)) 

2677 

2678 def VisitSignalAssignment(self, element: SignalAssignmentMixin) -> None: 

2679 """ 

2680 Write the signal assignment delimiter (``<=``) between the target and the waveform of a signal assignment. 

2681 

2682 In a force assignment, the reserved word ``force`` follows. 

2683 

2684 :param element: The signal assignment. 

2685 """ 

2686 if isinstance(element, SignalForceAssignment): 

2687 self._Write(f" <= {self._Keyword(ReservedWord.Force)} ") 

2688 else: 

2689 self._Write(" <= ") 

2690 

2691 self._minimum = OperatorPrecedence.Range 

2692 

2693 def VisitAfter(self, element: WaveformElement) -> None: 

2694 """ 

2695 Write the reserved word ``after`` before the delay of a waveform element. 

2696 

2697 :param element: The waveform element. 

2698 """ 

2699 self._Write(f" {self._Keyword(ReservedWord.After)} ") 

2700 self._minimum = OperatorPrecedence.Range 

2701 

2702 def VisitSelect( 

2703 self, 

2704 element: ConcurrentSelectedSignalAssignment | SequentialSelectedVariableAssignment | 

2705 SequentialSelectedSignalAssignment 

2706 ) -> None: 

2707 """ 

2708 Write the reserved word ``select`` between the selector and the target of a selected assignment. 

2709 

2710 :param element: The selected assignment. 

2711 """ 

2712 self._Write(f" {self._Keyword(ReservedWord.Select)} ") 

2713 

2714 def VisitBar(self, element: SelectedWaveform | GenerateCase | SelectedExpression | Case) -> None: 

2715 """ 

2716 Write the vertical line (``|``) between two choices. 

2717 

2718 :param element: The element with the choices. 

2719 """ 

2720 self._Write(" | ") 

2721 self._minimum = OperatorPrecedence.Range 

2722 

2723 def VisitReport(self, element: ReportStatementMixin) -> None: 

2724 """ 

2725 Write the reserved word ``report`` before the message of an assertion or report. 

2726 

2727 A report statement starts with the reserved word. 

2728 

2729 :param element: The assertion or report. 

2730 """ 

2731 if isinstance(element, SequentialReportStatement): 

2732 self._Write(f"{self._Keyword(ReservedWord.Report)} ") 

2733 else: 

2734 self._Write(f" {self._Keyword(ReservedWord.Report)} ") 

2735 

2736 self._minimum = OperatorPrecedence.Range 

2737 

2738 def VisitSeverity(self, element: ReportStatementMixin) -> None: 

2739 """ 

2740 Write the reserved word ``severity`` before the severity level of an assertion or report. 

2741 

2742 :param element: The assertion or report. 

2743 """ 

2744 self._Write(f" {self._Keyword(ReservedWord.Severity)} ") 

2745 self._minimum = OperatorPrecedence.Range 

2746 

2747 def VisitSensitivityList(self, process: ProcessStatement) -> None: 

2748 """ 

2749 Write the left parenthesis of the sensitivity list of a process. 

2750 

2751 **Format:** ``process (clk, rst)`` or ``process (all)`` 

2752 

2753 :param process: The process. 

2754 """ 

2755 self._Write(" (") 

2756 

2757 def DepartSensitivityList(self, process: ProcessStatement) -> None: 

2758 """ 

2759 Write the right parenthesis of the sensitivity list of a process. 

2760 

2761 :param process: The process. 

2762 """ 

2763 self._Write(")") 

2764 

2765 def VisitActualParameterPart(self, call: ProcedureCallMixin) -> None: 

2766 """ 

2767 Write the left parenthesis of the actual parameter part of a procedure call. 

2768 

2769 :param call: The procedure call. 

2770 """ 

2771 self._Write("(") 

2772 self._minimum = OperatorPrecedence.Range 

2773 

2774 def DepartActualParameterPart(self, call: ProcedureCallMixin) -> None: 

2775 """ 

2776 Write the right parenthesis of the actual parameter part of a procedure call. 

2777 

2778 :param call: The procedure call. 

2779 """ 

2780 self._Write(")") 

2781 

2782 def DepartOthersSelectedWaveform(self, waveform: OthersSelectedWaveform) -> None: 

2783 """ 

2784 Write the choice ``others`` of the ``others`` selected waveform. 

2785 

2786 **Format:** ``'0' when others`` 

2787 

2788 :param waveform: The selected waveform. 

2789 """ 

2790 self._Write(self._Keyword(ReservedWord.Others)) 

2791 

2792 def VisitIndexedChoice(self, choice: IndexedChoice) -> None: 

2793 """ 

2794 Enter a choice given by a value; the value is a simple expression. 

2795 

2796 **Format:** ``'0'`` 

2797 

2798 :param choice: The choice. 

2799 """ 

2800 self._minimum = OperatorPrecedence.Adding 

2801 

2802 def VisitProcessStatement(self, process: ProcessStatement) -> None: 

2803 """ 

2804 Write the label, if any, and the reserved word ``process`` of a process statement. 

2805 

2806 **Format:** ``count : process (clk) is`` ... ``begin`` ... ``end process count;`` 

2807 

2808 A process with ``all`` as sensitivity list has a single :class:`~pyVHDLModel.Name.AllName` without prefix in its 

2809 sensitivity list. 

2810 

2811 :param process: The process. 

2812 """ 

2813 self._WriteStatementStart(process) 

2814 self._Write(self._Keyword(ReservedWord.Process)) 

2815 

2816 def _WriteStatementStart(self, statement: Statement) -> None: 

2817 """ 

2818 Write the indentation and the label, if any, of a statement. 

2819 

2820 :param statement: The statement. 

2821 """ 

2822 self._WriteIndentation() 

2823 if statement.Label is not None: 

2824 self._Write(f"{statement.Label} : ") 

2825 

2826 def DepartProcessStatement(self, process: ProcessStatement) -> None: 

2827 """ 

2828 Write the end of a process statement. 

2829 

2830 :param process: The process. 

2831 """ 

2832 self._WriteEnd((ReservedWord.Process,), process.Label) 

2833 

2834 def VisitConcurrentProcedureCall(self, call: ConcurrentProcedureCall) -> None: 

2835 """ 

2836 Write the label, if any, of a concurrent procedure call. 

2837 

2838 **Format:** ``check(clk, rst);`` 

2839 

2840 :param call: The procedure call. 

2841 """ 

2842 self._WriteStatementStart(call) 

2843 

2844 def DepartConcurrentProcedureCall(self, call: ConcurrentProcedureCall) -> None: 

2845 """ 

2846 Write the semicolon ending a concurrent procedure call. 

2847 

2848 :param call: The procedure call. 

2849 """ 

2850 self._Write(";\n") 

2851 

2852 def VisitConcurrentSimpleSignalAssignment(self, assignment: ConcurrentSimpleSignalAssignment) -> None: 

2853 """ 

2854 Write the label, if any, of a concurrent simple signal assignment. 

2855 

2856 **Format:** ``q <= d after 1 ns;`` 

2857 

2858 :param assignment: The signal assignment. 

2859 """ 

2860 self._WriteStatementStart(assignment) 

2861 

2862 def DepartConcurrentSimpleSignalAssignment(self, assignment: ConcurrentSimpleSignalAssignment) -> None: 

2863 """ 

2864 Write the semicolon ending a concurrent simple signal assignment. 

2865 

2866 :param assignment: The signal assignment. 

2867 """ 

2868 self._Write(";\n") 

2869 

2870 def VisitConcurrentSelectedSignalAssignment(self, assignment: ConcurrentSelectedSignalAssignment) -> None: 

2871 """ 

2872 Write the label, if any, and the reserved word ``with`` of a concurrent selected signal assignment. 

2873 

2874 **Format:** ``with sel select q <= a when '0', b when others;`` 

2875 

2876 :param assignment: The signal assignment. 

2877 """ 

2878 self._WriteStatementStart(assignment) 

2879 self._Write(f"{self._Keyword(ReservedWord.With)} ") 

2880 self._minimum = OperatorPrecedence.Range 

2881 

2882 def DepartConcurrentSelectedSignalAssignment(self, assignment: ConcurrentSelectedSignalAssignment) -> None: 

2883 """ 

2884 Write the semicolon ending a concurrent selected signal assignment. 

2885 

2886 :param assignment: The signal assignment. 

2887 """ 

2888 self._Write(";\n") 

2889 

2890 def VisitConcurrentConditionalSignalAssignment(self, assignment: ConcurrentConditionalSignalAssignment) -> None: 

2891 """ 

2892 Write the label, if any, of a concurrent conditional signal assignment. 

2893 

2894 **Format:** ``q <= a when sel = '0' else b;`` 

2895 

2896 :param assignment: The signal assignment. 

2897 """ 

2898 self._WriteStatementStart(assignment) 

2899 

2900 def DepartConcurrentConditionalSignalAssignment(self, assignment: ConcurrentConditionalSignalAssignment) -> None: 

2901 """ 

2902 Write the semicolon ending a concurrent conditional signal assignment. 

2903 

2904 :param assignment: The signal assignment. 

2905 """ 

2906 self._Write(";\n") 

2907 

2908 def VisitConcurrentAssertStatement(self, assertion: ConcurrentAssertStatement) -> None: 

2909 """ 

2910 Write the label, if any, and the reserved word ``assert`` of a concurrent assertion. 

2911 

2912 **Format:** ``assert BITS > 0 report "no bits" severity failure;`` 

2913 

2914 :param assertion: The assertion. 

2915 """ 

2916 self._WriteStatementStart(assertion) 

2917 self._Write(f"{self._Keyword(ReservedWord.Assert)} ") 

2918 self._minimum = OperatorPrecedence.Range 

2919 

2920 def DepartConcurrentAssertStatement(self, assertion: ConcurrentAssertStatement) -> None: 

2921 """ 

2922 Write the semicolon ending a concurrent assertion. 

2923 

2924 :param assertion: The assertion. 

2925 """ 

2926 self._Write(";\n") 

2927 

2928 def VisitRightParenthesis(self, element: EntityAspectEntity | EntityInstantiation) -> None: 

2929 """ 

2930 Write the right parenthesis after the architecture name of an entity aspect or entity instantiation. 

2931 

2932 :param element: The element enclosing the architecture name. 

2933 """ 

2934 self._Write(")") 

2935 

2936 def VisitGenerate(self, element: GenerateBranch | CaseGenerateStatement | ForGenerateStatement) -> None: 

2937 """ 

2938 Write the reserved word ``generate``; the body of the generate statement or branch is indented. 

2939 

2940 :param element: The generate statement or branch. 

2941 """ 

2942 self._Write(f" {self._Keyword(ReservedWord.Generate)}\n") 

2943 self._indentation += 1 

2944 

2945 def VisitComponentInstantiation(self, instantiation: ComponentInstantiation) -> None: 

2946 """ 

2947 Write the label and the reserved word ``component`` of a component instantiation. 

2948 

2949 **Format:** ``u1 : component counter`` ... ``;`` 

2950 

2951 :param instantiation: The component instantiation. 

2952 :raises VHDLWriterError: If the component instantiation has no label. 

2953 """ 

2954 if instantiation.Label is None: 

2955 raise VHDLWriterError("Component instantiation has no label.", instantiation) 

2956 

2957 self._WriteStatementStart(instantiation) 

2958 self._Write(f"{self._Keyword(ReservedWord.Component)} ") 

2959 

2960 def DepartComponentInstantiation(self, instantiation: ComponentInstantiation) -> None: 

2961 """ 

2962 Write the semicolon ending a component instantiation. 

2963 

2964 :param instantiation: The component instantiation. 

2965 """ 

2966 self._Write(";\n") 

2967 

2968 def VisitEntityInstantiation(self, instantiation: EntityInstantiation) -> None: 

2969 """ 

2970 Write the label and the reserved word ``entity`` of an entity instantiation. 

2971 

2972 **Format:** ``u1 : entity work.counter(rtl)`` ... ``;`` 

2973 

2974 :param instantiation: The entity instantiation. 

2975 :raises VHDLWriterError: If the entity instantiation has no label. 

2976 """ 

2977 if instantiation.Label is None: 2977 ↛ 2978line 2977 didn't jump to line 2978 because the condition on line 2977 was never true

2978 raise VHDLWriterError("Entity instantiation has no label.", instantiation) 

2979 

2980 self._WriteStatementStart(instantiation) 

2981 self._Write(f"{self._Keyword(ReservedWord.Entity)} ") 

2982 

2983 def DepartEntityInstantiation(self, instantiation: EntityInstantiation) -> None: 

2984 """ 

2985 Write the semicolon ending an entity instantiation. 

2986 

2987 :param instantiation: The entity instantiation. 

2988 """ 

2989 self._Write(";\n") 

2990 

2991 def VisitConfigurationInstantiation(self, instantiation: ConfigurationInstantiation) -> None: 

2992 """ 

2993 Write the label and the reserved word ``configuration`` of a configuration instantiation. 

2994 

2995 **Format:** ``u1 : configuration work.counter_cfg`` ... ``;`` 

2996 

2997 :param instantiation: The configuration instantiation. 

2998 :raises VHDLWriterError: If the configuration instantiation has no label. 

2999 """ 

3000 if instantiation.Label is None: 3000 ↛ 3001line 3000 didn't jump to line 3001 because the condition on line 3000 was never true

3001 raise VHDLWriterError("Configuration instantiation has no label.", instantiation) 

3002 

3003 self._WriteStatementStart(instantiation) 

3004 self._Write(f"{self._Keyword(ReservedWord.Configuration)} ") 

3005 

3006 def DepartConfigurationInstantiation(self, instantiation: ConfigurationInstantiation) -> None: 

3007 """ 

3008 Write the semicolon ending a configuration instantiation. 

3009 

3010 :param instantiation: The configuration instantiation. 

3011 """ 

3012 self._Write(";\n") 

3013 

3014 def VisitConcurrentBlockStatement(self, block: ConcurrentBlockStatement) -> None: 

3015 """ 

3016 Write the label and the reserved word ``block`` of a block statement; its header and declarations are indented. 

3017 

3018 **Format:** ``inner : block`` ... ``begin`` ... ``end block inner;`` 

3019 

3020 :param block: The block statement. 

3021 :raises VHDLWriterError: If the block statement has no label. 

3022 """ 

3023 if block.Label is None: 3023 ↛ 3024line 3023 didn't jump to line 3024 because the condition on line 3023 was never true

3024 raise VHDLWriterError("Block statement has no label.", block) 

3025 

3026 self._WriteStatementStart(block) 

3027 self._Write(f"{self._Keyword(ReservedWord.Block)}\n") 

3028 self._indentation += 1 

3029 

3030 def DepartConcurrentBlockStatement(self, block: ConcurrentBlockStatement) -> None: 

3031 """ 

3032 Write the end of a block statement. 

3033 

3034 :param block: The block statement. 

3035 """ 

3036 self._WriteEnd((ReservedWord.Block,), block.Label) 

3037 

3038 def VisitIfGenerateStatement(self, statement: IfGenerateStatement) -> None: 

3039 """ 

3040 Write the label of an if-generate statement; its branches follow. 

3041 

3042 **Format:** ``gen : if BITS > 8 generate`` ... ``elsif`` ... ``else generate`` ... ``end generate gen;`` 

3043 

3044 :param statement: The if-generate statement. 

3045 :raises VHDLWriterError: If the if-generate statement has no label. 

3046 """ 

3047 if statement.Label is None: 3047 ↛ 3048line 3047 didn't jump to line 3048 because the condition on line 3047 was never true

3048 raise VHDLWriterError("If-generate statement has no label.", statement) 

3049 

3050 self._WriteStatementStart(statement) 

3051 

3052 def DepartIfGenerateStatement(self, statement: IfGenerateStatement) -> None: 

3053 """ 

3054 Write the end of an if-generate statement. 

3055 

3056 :param statement: The if-generate statement. 

3057 """ 

3058 self._WriteEndLine((ReservedWord.Generate,), statement.Label) 

3059 

3060 def VisitIfGenerateBranch(self, branch: IfGenerateBranch) -> None: 

3061 """ 

3062 Write the reserved word ``if`` and the alternative label, if any, of the if branch of an if-generate statement. 

3063 

3064 :param branch: The generate branch. 

3065 """ 

3066 self._Write(f"{self._Keyword(ReservedWord.If)} ") 

3067 self._WriteAlternativeLabel(branch) 

3068 

3069 def _WriteAlternativeLabel(self, branch: GenerateBranch) -> None: 

3070 """ 

3071 Write the alternative label, if any, of a generate branch, followed by a colon. 

3072 

3073 :param branch: The generate branch. 

3074 """ 

3075 if branch.AlternativeLabel is not None: 

3076 self._Write(f"{branch.AlternativeLabel} : ") 

3077 

3078 self._minimum = OperatorPrecedence.Range 

3079 

3080 def DepartIfGenerateBranch(self, branch: IfGenerateBranch) -> None: 

3081 """ 

3082 Leave the body of the if branch of an if-generate statement. 

3083 

3084 :param branch: The generate branch. 

3085 """ 

3086 self._indentation -= 1 

3087 

3088 def VisitElsifGenerateBranch(self, branch: ElsifGenerateBranch) -> None: 

3089 """ 

3090 Write the reserved word ``elsif`` and the alternative label, if any, of an elsif branch of an if-generate statement. 

3091 

3092 :param branch: The generate branch. 

3093 """ 

3094 self._WriteIndentation() 

3095 self._Write(f"{self._Keyword(ReservedWord.ElsIf)} ") 

3096 self._WriteAlternativeLabel(branch) 

3097 

3098 def DepartElsifGenerateBranch(self, branch: ElsifGenerateBranch) -> None: 

3099 """ 

3100 Leave the body of an elsif branch of an if-generate statement. 

3101 

3102 :param branch: The generate branch. 

3103 """ 

3104 self._indentation -= 1 

3105 

3106 def VisitElseGenerateBranch(self, branch: ElseGenerateBranch) -> None: 

3107 """ 

3108 Write the reserved word ``else`` and the alternative label, if any, of the else branch of an if-generate statement. 

3109 

3110 :param branch: The generate branch. 

3111 """ 

3112 self._WriteIndentation() 

3113 self._Write(self._Keyword(ReservedWord.Else)) 

3114 if branch.AlternativeLabel is not None: 

3115 self._Write(f" {branch.AlternativeLabel} :") 

3116 

3117 def DepartElseGenerateBranch(self, branch: ElseGenerateBranch) -> None: 

3118 """ 

3119 Leave the body of the else branch of an if-generate statement. 

3120 

3121 :param branch: The generate branch. 

3122 """ 

3123 self._indentation -= 1 

3124 

3125 def VisitCaseGenerateStatement(self, statement: CaseGenerateStatement) -> None: 

3126 """ 

3127 Write the label and the reserved word ``case`` of a case-generate statement; its alternatives are indented. 

3128 

3129 **Format:** ``gen : case MODE generate`` ... ``when 0 =>`` ... ``end generate gen;`` 

3130 

3131 :param statement: The case-generate statement. 

3132 :raises VHDLWriterError: If the case-generate statement has no label. 

3133 """ 

3134 if statement.Label is None: 3134 ↛ 3135line 3134 didn't jump to line 3135 because the condition on line 3134 was never true

3135 raise VHDLWriterError("Case-generate statement has no label.", statement) 

3136 

3137 self._WriteStatementStart(statement) 

3138 self._Write(f"{self._Keyword(ReservedWord.Case)} ") 

3139 self._minimum = OperatorPrecedence.Range 

3140 

3141 def DepartCaseGenerateStatement(self, statement: CaseGenerateStatement) -> None: 

3142 """ 

3143 Write the end of a case-generate statement. 

3144 

3145 :param statement: The case-generate statement. 

3146 """ 

3147 self._WriteEnd((ReservedWord.Generate,), statement.Label) 

3148 

3149 def VisitGenerateCase(self, case: GenerateCase) -> None: 

3150 """ 

3151 Write the reserved word ``when`` and the alternative label, if any, of an alternative of a case-generate statement. 

3152 

3153 **Format:** ``when 1 | 2 =>`` 

3154 

3155 :param case: The case-generate alternative. 

3156 """ 

3157 self._WriteIndentation() 

3158 self._Write(f"{self._Keyword(ReservedWord.When)} ") 

3159 if case.Label is not None: 

3160 self._Write(f"{case.Label} : ") 

3161 

3162 def DepartGenerateCase(self, case: GenerateCase) -> None: 

3163 """ 

3164 Leave the body of an alternative of a case-generate statement. 

3165 

3166 :param case: The case-generate alternative. 

3167 """ 

3168 self._indentation -= 1 

3169 

3170 def VisitOthersGenerateCase(self, case: OthersGenerateCase) -> None: 

3171 """ 

3172 Write the reserved words ``when`` and ``others`` of the ``others`` alternative of a case-generate statement. 

3173 

3174 **Format:** ``when others =>`` 

3175 

3176 :param case: The case-generate alternative. 

3177 """ 

3178 self._WriteIndentation() 

3179 self._Write(f"{self._Keyword(ReservedWord.When)} ") 

3180 if case.Label is not None: 3180 ↛ 3181line 3180 didn't jump to line 3181 because the condition on line 3180 was never true

3181 self._Write(f"{case.Label} : ") 

3182 

3183 self._Write(self._Keyword(ReservedWord.Others)) 

3184 

3185 def DepartOthersGenerateCase(self, case: OthersGenerateCase) -> None: 

3186 """ 

3187 Leave the body of the ``others`` alternative of a case-generate statement. 

3188 

3189 :param case: The case-generate alternative. 

3190 """ 

3191 self._indentation -= 1 

3192 

3193 def VisitIndexedGenerateChoice(self, choice: IndexedGenerateChoice) -> None: 

3194 """ 

3195 Enter a case-generate choice given by a value; the value is a simple expression. 

3196 

3197 **Format:** ``8`` 

3198 

3199 :param choice: The choice. 

3200 """ 

3201 self._minimum = OperatorPrecedence.Adding 

3202 

3203 def VisitForGenerateStatement(self, statement: ForGenerateStatement) -> None: 

3204 """ 

3205 Write the label, the reserved word ``for``, the loop index and ``in`` of a for-generate statement. 

3206 

3207 **Format:** ``gen : for i in 0 to 3 generate`` ... ``end generate gen;`` 

3208 

3209 :param statement: The for-generate statement. 

3210 :raises VHDLWriterError: If the for-generate statement has no label. 

3211 """ 

3212 if statement.Label is None: 

3213 raise VHDLWriterError("For-generate statement has no label.", statement) 

3214 

3215 self._WriteStatementStart(statement) 

3216 self._Write(f"{self._Keyword(ReservedWord.For)} {statement.LoopIndex} {self._Keyword(ReservedWord.In)} ") 

3217 self._minimum = OperatorPrecedence.Range 

3218 

3219 def DepartForGenerateStatement(self, statement: ForGenerateStatement) -> None: 

3220 """ 

3221 Write the end of a for-generate statement. 

3222 

3223 :param statement: The for-generate statement. 

3224 """ 

3225 self._WriteEnd((ReservedWord.Generate,), statement.Label) 

3226 

3227 def VisitOn(self, statement: WaitStatement) -> None: 

3228 """ 

3229 Write the reserved word ``on`` before the sensitivity list of a wait statement. 

3230 

3231 :param statement: The wait statement. 

3232 """ 

3233 self._Write(f" {self._Keyword(ReservedWord.On)} ") 

3234 

3235 def VisitUntil(self, statement: WaitStatement) -> None: 

3236 """ 

3237 Write the reserved word ``until`` before the condition of a wait statement. 

3238 

3239 :param statement: The wait statement. 

3240 """ 

3241 self._Write(f" {self._Keyword(ReservedWord.Until)} ") 

3242 self._minimum = OperatorPrecedence.Range 

3243 

3244 def VisitFor(self, statement: WaitStatement) -> None: 

3245 """ 

3246 Write the reserved word ``for`` before the timeout of a wait statement. 

3247 

3248 :param statement: The wait statement. 

3249 """ 

3250 self._Write(f" {self._Keyword(ReservedWord.For)} ") 

3251 self._minimum = OperatorPrecedence.Range 

3252 

3253 def DepartOthersSelectedExpression(self, expression: OthersSelectedExpression) -> None: 

3254 """ 

3255 Write the choice ``others`` of the ``others`` selected expression. 

3256 

3257 **Format:** ``'0' when others`` 

3258 

3259 :param expression: The selected expression. 

3260 """ 

3261 self._Write(self._Keyword(ReservedWord.Others)) 

3262 

3263 def VisitSequentialProcedureCall(self, call: SequentialProcedureCall) -> None: 

3264 """ 

3265 Write the label, if any, of a procedure call. 

3266 

3267 **Format:** ``check(value, limit => 4);`` 

3268 

3269 :param call: The procedure call. 

3270 """ 

3271 self._WriteStatementStart(call) 

3272 

3273 def DepartSequentialProcedureCall(self, call: SequentialProcedureCall) -> None: 

3274 """ 

3275 Write the semicolon ending a procedure call. 

3276 

3277 :param call: The procedure call. 

3278 """ 

3279 self._Write(";\n") 

3280 

3281 def VisitSequentialSimpleSignalAssignment(self, assignment: SequentialSimpleSignalAssignment) -> None: 

3282 """ 

3283 Write the label, if any, of a signal assignment. 

3284 

3285 **Format:** ``q <= d after 1 ns;`` 

3286 

3287 :param assignment: The signal assignment. 

3288 """ 

3289 self._WriteStatementStart(assignment) 

3290 

3291 def DepartSequentialSimpleSignalAssignment(self, assignment: SequentialSimpleSignalAssignment) -> None: 

3292 """ 

3293 Write the semicolon ending a signal assignment. 

3294 

3295 :param assignment: The signal assignment. 

3296 """ 

3297 self._Write(";\n") 

3298 

3299 def VisitSequentialVariableAssignment(self, assignment: SequentialVariableAssignment) -> None: 

3300 """ 

3301 Write the label, if any, of a variable assignment. 

3302 

3303 **Format:** ``count := count + 1;`` 

3304 

3305 :param assignment: The variable assignment. 

3306 """ 

3307 self._WriteStatementStart(assignment) 

3308 

3309 def DepartSequentialVariableAssignment(self, assignment: SequentialVariableAssignment) -> None: 

3310 """ 

3311 Write the semicolon ending a variable assignment. 

3312 

3313 :param assignment: The variable assignment. 

3314 """ 

3315 self._Write(";\n") 

3316 

3317 def VisitSequentialConditionalVariableAssignment(self, assignment: SequentialConditionalVariableAssignment) -> None: 

3318 """ 

3319 Write the label, if any, of a conditional variable assignment. 

3320 

3321 **Format:** ``v := a when sel = '0' else b;`` 

3322 

3323 :param assignment: The conditional variable assignment. 

3324 """ 

3325 self._WriteStatementStart(assignment) 

3326 

3327 def DepartSequentialConditionalVariableAssignment(self, assignment: SequentialConditionalVariableAssignment) -> None: 

3328 """ 

3329 Write the semicolon ending a conditional variable assignment. 

3330 

3331 :param assignment: The conditional variable assignment. 

3332 """ 

3333 self._Write(";\n") 

3334 

3335 def VisitSequentialConditionalSignalAssignment(self, assignment: SequentialConditionalSignalAssignment) -> None: 

3336 """ 

3337 Write the label, if any, of a conditional signal assignment. 

3338 

3339 **Format:** ``q <= a when sel = '0' else b;`` 

3340 

3341 :param assignment: The conditional signal assignment. 

3342 """ 

3343 self._WriteStatementStart(assignment) 

3344 

3345 def DepartSequentialConditionalSignalAssignment(self, assignment: SequentialConditionalSignalAssignment) -> None: 

3346 """ 

3347 Write the semicolon ending a conditional signal assignment. 

3348 

3349 :param assignment: The conditional signal assignment. 

3350 """ 

3351 self._Write(";\n") 

3352 

3353 def VisitSequentialSelectedVariableAssignment(self, assignment: SequentialSelectedVariableAssignment) -> None: 

3354 """ 

3355 Write the label, if any, and the reserved word ``with`` of a selected variable assignment. 

3356 

3357 **Format:** ``with sel select v := a when '0', b when others;`` 

3358 

3359 :param assignment: The selected variable assignment. 

3360 """ 

3361 self._WriteStatementStart(assignment) 

3362 self._Write(f"{self._Keyword(ReservedWord.With)} ") 

3363 self._minimum = OperatorPrecedence.Range 

3364 

3365 def DepartSequentialSelectedVariableAssignment(self, assignment: SequentialSelectedVariableAssignment) -> None: 

3366 """ 

3367 Write the semicolon ending a selected variable assignment. 

3368 

3369 :param assignment: The selected variable assignment. 

3370 """ 

3371 self._Write(";\n") 

3372 

3373 def VisitSequentialSelectedSignalAssignment(self, assignment: SequentialSelectedSignalAssignment) -> None: 

3374 """ 

3375 Write the label, if any, and the reserved word ``with`` of a selected signal assignment. 

3376 

3377 **Format:** ``with sel select q <= a when '0', b when others;`` 

3378 

3379 :param assignment: The selected signal assignment. 

3380 """ 

3381 self._WriteStatementStart(assignment) 

3382 self._Write(f"{self._Keyword(ReservedWord.With)} ") 

3383 self._minimum = OperatorPrecedence.Range 

3384 

3385 def DepartSequentialSelectedSignalAssignment(self, assignment: SequentialSelectedSignalAssignment) -> None: 

3386 """ 

3387 Write the semicolon ending a selected signal assignment. 

3388 

3389 :param assignment: The selected signal assignment. 

3390 """ 

3391 self._Write(";\n") 

3392 

3393 def VisitSignalForceAssignment(self, assignment: SignalForceAssignment) -> None: 

3394 """ 

3395 Write the label, if any, of a force assignment. 

3396 

3397 **Format:** ``q <= force '1';`` 

3398 

3399 :param assignment: The force assignment. 

3400 """ 

3401 self._WriteStatementStart(assignment) 

3402 

3403 def DepartSignalForceAssignment(self, assignment: SignalForceAssignment) -> None: 

3404 """ 

3405 Write the semicolon ending a force assignment. 

3406 

3407 :param assignment: The force assignment. 

3408 """ 

3409 self._Write(";\n") 

3410 

3411 def VisitSignalReleaseAssignment(self, assignment: SignalReleaseAssignment) -> None: 

3412 """ 

3413 Write the label, if any, of a release assignment. 

3414 

3415 **Format:** ``q <= release;`` 

3416 

3417 :param assignment: The release assignment. 

3418 """ 

3419 self._WriteStatementStart(assignment) 

3420 

3421 def DepartSignalReleaseAssignment(self, assignment: SignalReleaseAssignment) -> None: 

3422 """ 

3423 Write the reserved word ``release`` and the semicolon ending a release assignment. 

3424 

3425 :param assignment: The release assignment. 

3426 """ 

3427 self._Write(f"{self._Keyword(ReservedWord.Release)};\n") 

3428 

3429 def VisitSequentialReportStatement(self, statement: SequentialReportStatement) -> None: 

3430 """ 

3431 Write the label, if any, of a report statement. 

3432 

3433 **Format:** ``report "done" severity note;`` 

3434 

3435 :param statement: The report statement. 

3436 """ 

3437 self._WriteStatementStart(statement) 

3438 

3439 def DepartSequentialReportStatement(self, statement: SequentialReportStatement) -> None: 

3440 """ 

3441 Write the semicolon ending a report statement. 

3442 

3443 :param statement: The report statement. 

3444 """ 

3445 self._Write(";\n") 

3446 

3447 def VisitSequentialAssertStatement(self, assertion: SequentialAssertStatement) -> None: 

3448 """ 

3449 Write the label, if any, and the reserved word ``assert`` of an assertion. 

3450 

3451 **Format:** ``assert count < 8 report "overflow" severity error;`` 

3452 

3453 :param assertion: The assertion. 

3454 """ 

3455 self._WriteStatementStart(assertion) 

3456 self._Write(f"{self._Keyword(ReservedWord.Assert)} ") 

3457 self._minimum = OperatorPrecedence.Range 

3458 

3459 def DepartSequentialAssertStatement(self, assertion: SequentialAssertStatement) -> None: 

3460 """ 

3461 Write the semicolon ending an assertion. 

3462 

3463 :param assertion: The assertion. 

3464 """ 

3465 self._Write(";\n") 

3466 

3467 def VisitNullStatement(self, statement: NullStatement) -> None: 

3468 """ 

3469 Write a null statement. 

3470 

3471 **Format:** ``null;`` 

3472 

3473 :param statement: The null statement. 

3474 """ 

3475 self._WriteStatementStart(statement) 

3476 self._Write(f"{self._Keyword(ReservedWord.Null)};\n") 

3477 

3478 def VisitReturnStatement(self, statement: ReturnStatement) -> None: 

3479 """ 

3480 Write the label, if any, and the reserved word ``return`` of a return statement. 

3481 

3482 **Format:** ``return count;`` 

3483 

3484 :param statement: The return statement. 

3485 """ 

3486 self._WriteStatementStart(statement) 

3487 self._Write(self._Keyword(ReservedWord.Return)) 

3488 if statement.ReturnValue is not None: 

3489 self._Write(" ") 

3490 self._minimum = OperatorPrecedence.Range 

3491 

3492 def DepartReturnStatement(self, statement: ReturnStatement) -> None: 

3493 """ 

3494 Write the semicolon ending a return statement. 

3495 

3496 :param statement: The return statement. 

3497 """ 

3498 self._Write(";\n") 

3499 

3500 def VisitWaitStatement(self, statement: WaitStatement) -> None: 

3501 """ 

3502 Write the label, if any, and the reserved word ``wait`` of a wait statement. 

3503 

3504 **Format:** ``wait on clk until clk = '1' for 10 ns;`` 

3505 

3506 :param statement: The wait statement. 

3507 """ 

3508 self._WriteStatementStart(statement) 

3509 self._Write(self._Keyword(ReservedWord.Wait)) 

3510 

3511 def DepartWaitStatement(self, statement: WaitStatement) -> None: 

3512 """ 

3513 Write the semicolon ending a wait statement. 

3514 

3515 :param statement: The wait statement. 

3516 """ 

3517 self._Write(";\n") 

3518 

3519 def VisitThen(self, branch: IfBranch | ElsifBranch) -> None: 

3520 """ 

3521 Write the reserved word ``then`` of an if or elsif branch; its statements are indented. 

3522 

3523 :param branch: The branch. 

3524 """ 

3525 self._Write(f" {self._Keyword(ReservedWord.Then)}\n") 

3526 self._indentation += 1 

3527 

3528 def VisitLoop(self, statement: LoopStatement) -> None: 

3529 """ 

3530 Write the reserved word ``loop`` of a loop statement; its statements are indented. 

3531 

3532 :param statement: The loop statement. 

3533 """ 

3534 if isinstance(statement, EndlessLoopStatement): 

3535 self._Write(f"{self._Keyword(ReservedWord.Loop)}\n") 

3536 else: 

3537 self._Write(f" {self._Keyword(ReservedWord.Loop)}\n") 

3538 

3539 self._indentation += 1 

3540 

3541 def VisitIfStatement(self, statement: IfStatement) -> None: 

3542 """ 

3543 Write the label, if any, of an if statement; its branches follow. 

3544 

3545 **Format:** ``if count = 0 then`` ... ``elsif`` ... ``else`` ... ``end if;`` 

3546 

3547 :param statement: The if statement. 

3548 """ 

3549 self._WriteStatementStart(statement) 

3550 

3551 def DepartIfStatement(self, statement: IfStatement) -> None: 

3552 """ 

3553 Write the end of an if statement. 

3554 

3555 :param statement: The if statement. 

3556 """ 

3557 self._WriteEndLine((ReservedWord.If,), statement.Label) 

3558 

3559 def VisitIfBranch(self, branch: IfBranch) -> None: 

3560 """ 

3561 Write the reserved word ``if`` of the if branch of an if statement. 

3562 

3563 :param branch: The branch. 

3564 """ 

3565 self._Write(f"{self._Keyword(ReservedWord.If)} ") 

3566 self._minimum = OperatorPrecedence.Range 

3567 

3568 def DepartIfBranch(self, branch: IfBranch) -> None: 

3569 """ 

3570 Leave the statements of the if branch of an if statement. 

3571 

3572 :param branch: The branch. 

3573 """ 

3574 self._indentation -= 1 

3575 

3576 def VisitElsifBranch(self, branch: ElsifBranch) -> None: 

3577 """ 

3578 Write the reserved word ``elsif`` of an elsif branch of an if statement. 

3579 

3580 :param branch: The branch. 

3581 """ 

3582 self._WriteIndentation() 

3583 self._Write(f"{self._Keyword(ReservedWord.ElsIf)} ") 

3584 self._minimum = OperatorPrecedence.Range 

3585 

3586 def DepartElsifBranch(self, branch: ElsifBranch) -> None: 

3587 """ 

3588 Leave the statements of an elsif branch of an if statement. 

3589 

3590 :param branch: The branch. 

3591 """ 

3592 self._indentation -= 1 

3593 

3594 def VisitElseBranch(self, branch: ElseBranch) -> None: 

3595 """ 

3596 Write the reserved word ``else`` of the else branch of an if statement; its statements are indented. 

3597 

3598 :param branch: The branch. 

3599 """ 

3600 self._WriteIndentation() 

3601 self._Write(f"{self._Keyword(ReservedWord.Else)}\n") 

3602 self._indentation += 1 

3603 

3604 def DepartElseBranch(self, branch: ElseBranch) -> None: 

3605 """ 

3606 Leave the statements of the else branch of an if statement. 

3607 

3608 :param branch: The branch. 

3609 """ 

3610 self._indentation -= 1 

3611 

3612 def VisitCaseStatement(self, statement: CaseStatement) -> None: 

3613 """ 

3614 Write the label, if any, and the reserved word ``case`` of a case statement; its alternatives are indented. 

3615 

3616 **Format:** ``case state is`` ... ``when Idle =>`` ... ``end case;`` 

3617 

3618 :param statement: The case statement. 

3619 """ 

3620 self._WriteStatementStart(statement) 

3621 self._Write(f"{self._Keyword(ReservedWord.Case)} ") 

3622 self._minimum = OperatorPrecedence.Range 

3623 

3624 def DepartCaseStatement(self, statement: CaseStatement) -> None: 

3625 """ 

3626 Write the end of a case statement. 

3627 

3628 :param statement: The case statement. 

3629 """ 

3630 self._WriteEnd((ReservedWord.Case,), statement.Label) 

3631 

3632 def VisitCase(self, case: Case) -> None: 

3633 """ 

3634 Write the reserved word ``when`` of an alternative of a case statement. 

3635 

3636 **Format:** ``when 1 | 2 =>`` 

3637 

3638 :param case: The case alternative. 

3639 """ 

3640 self._WriteIndentation() 

3641 self._Write(f"{self._Keyword(ReservedWord.When)} ") 

3642 

3643 def DepartCase(self, case: Case) -> None: 

3644 """ 

3645 Leave the statements of an alternative of a case statement. 

3646 

3647 :param case: The case alternative. 

3648 """ 

3649 self._indentation -= 1 

3650 

3651 def VisitOthersCase(self, case: OthersCase) -> None: 

3652 """ 

3653 Write the reserved words ``when`` and ``others`` of the ``others`` alternative of a case statement. 

3654 

3655 **Format:** ``when others =>`` 

3656 

3657 :param case: The case alternative. 

3658 """ 

3659 self._WriteIndentation() 

3660 self._Write(f"{self._Keyword(ReservedWord.When)} {self._Keyword(ReservedWord.Others)}") 

3661 

3662 def DepartOthersCase(self, case: OthersCase) -> None: 

3663 """ 

3664 Leave the statements of the ``others`` alternative of a case statement. 

3665 

3666 :param case: The case alternative. 

3667 """ 

3668 self._indentation -= 1 

3669 

3670 def VisitEndlessLoopStatement(self, statement: EndlessLoopStatement) -> None: 

3671 """ 

3672 Write the label, if any, of a loop statement without iteration scheme. 

3673 

3674 **Format:** ``loop`` ... ``end loop;`` 

3675 

3676 :param statement: The loop statement. 

3677 """ 

3678 self._WriteStatementStart(statement) 

3679 

3680 def DepartEndlessLoopStatement(self, statement: EndlessLoopStatement) -> None: 

3681 """ 

3682 Write the end of a loop statement without iteration scheme. 

3683 

3684 :param statement: The loop statement. 

3685 """ 

3686 self._WriteEnd((ReservedWord.Loop,), statement.Label) 

3687 

3688 def VisitForLoopStatement(self, statement: ForLoopStatement) -> None: 

3689 """ 

3690 Write the label, if any, the reserved word ``for``, the loop index and ``in`` of a for-loop statement. 

3691 

3692 **Format:** ``for i in 0 to 7 loop`` ... ``end loop;`` 

3693 

3694 :param statement: The loop statement. 

3695 """ 

3696 self._WriteStatementStart(statement) 

3697 self._Write(f"{self._Keyword(ReservedWord.For)} {statement.LoopIndex} {self._Keyword(ReservedWord.In)} ") 

3698 self._minimum = OperatorPrecedence.Range 

3699 

3700 def DepartForLoopStatement(self, statement: ForLoopStatement) -> None: 

3701 """ 

3702 Write the end of a for-loop statement. 

3703 

3704 :param statement: The loop statement. 

3705 """ 

3706 self._WriteEnd((ReservedWord.Loop,), statement.Label) 

3707 

3708 def VisitWhileLoopStatement(self, statement: WhileLoopStatement) -> None: 

3709 """ 

3710 Write the label, if any, and the reserved word ``while`` of a while-loop statement. 

3711 

3712 **Format:** ``while count < 8 loop`` ... ``end loop;`` 

3713 

3714 :param statement: The loop statement. 

3715 """ 

3716 self._WriteStatementStart(statement) 

3717 self._Write(f"{self._Keyword(ReservedWord.While)} ") 

3718 self._minimum = OperatorPrecedence.Range 

3719 

3720 def DepartWhileLoopStatement(self, statement: WhileLoopStatement) -> None: 

3721 """ 

3722 Write the end of a while-loop statement. 

3723 

3724 :param statement: The loop statement. 

3725 """ 

3726 self._WriteEnd((ReservedWord.Loop,), statement.Label) 

3727 

3728 def VisitNextStatement(self, statement: NextStatement) -> None: 

3729 """ 

3730 Write the label, if any, and the reserved word ``next`` of a next statement. 

3731 

3732 **Format:** ``next when skip;`` 

3733 

3734 The model keeps no loop label, so none is written. 

3735 

3736 :param statement: The next statement. 

3737 """ 

3738 self._WriteStatementStart(statement) 

3739 self._Write(self._Keyword(ReservedWord.Next)) 

3740 

3741 def DepartNextStatement(self, statement: NextStatement) -> None: 

3742 """ 

3743 Write the semicolon ending a next statement. 

3744 

3745 :param statement: The next statement. 

3746 """ 

3747 self._Write(";\n") 

3748 

3749 def VisitExitStatement(self, statement: ExitStatement) -> None: 

3750 """ 

3751 Write the label, if any, and the reserved word ``exit`` of an exit statement. 

3752 

3753 **Format:** ``exit when done;`` 

3754 

3755 The model keeps no loop label, so none is written. 

3756 

3757 :param statement: The exit statement. 

3758 """ 

3759 self._WriteStatementStart(statement) 

3760 self._Write(self._Keyword(ReservedWord.Exit)) 

3761 

3762 def DepartExitStatement(self, statement: ExitStatement) -> None: 

3763 """ 

3764 Write the semicolon ending an exit statement. 

3765 

3766 :param statement: The exit statement. 

3767 """ 

3768 self._Write(";\n")