Coverage for pyVHDLModel/Sequential.py: 93%

636 statements  

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

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

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

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

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

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

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

7# |_| |___/ # 

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

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

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

14# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany # 

15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany # 

16# # 

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

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

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

20# # 

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

22# # 

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

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

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

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

27# limitations under the License. # 

28# # 

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

30# ==================================================================================================================== # 

31# 

32""" 

33This module contains parts of an abstract document language model for VHDL. 

34 

35Declarations for sequential statements. 

36""" 

37from __future__ import annotations 

38 

39from typing import TYPE_CHECKING, Iterable, Optional as Nullable 

40 

41from pyTooling.Common import getFullyQualifiedName, getTypeName 

42from pyTooling.Decorators import export, readonly 

43from pyTooling.MetaClasses import ExtendedType, abstractclass 

44 

45from pyVHDLModel.Base import ModelEntity, ExpressionUnion, Range, BaseChoice, BaseCase, ConditionalMixin, \ 

46 IfBranchMixin, ElsifBranchMixin, ElseBranchMixin, ReportStatementMixin, \ 

47 AssertStatementMixin, WaveformElement, ChoicesMixin, LabeledEntityMixin 

48from pyVHDLModel.Exception import AlreadyInDesignError, DuplicateLabelError, NotAChildError 

49from pyVHDLModel.Symbol import Symbol, SignalSymbol, VariableSymbol 

50from pyVHDLModel.Common import Statement, ProcedureCallMixin, AssignmentMixin, SignalAssignmentMixin, \ 

51 VariableAssignmentMixin, ConditionalWaveform, ConditionalExpression, \ 

52 ConditionalWaveformsMixin, WaveformMixin, ExpressionMixin, SelectedWaveformsMixin, \ 

53 SelectedExpressionsMixin, SelectedWaveform, SelectedExpression 

54from pyVHDLModel.Association import ParameterAssociationItem 

55 

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

57 from pyVHDLModel.Visitor import Visitor 

58 

59 

60@export 

61@abstractclass 

62class SequentialStatement(Statement): 

63 """ 

64 Represents the base-class of all sequential statements. 

65 

66 Sequential statements appear in a process or a subprogram body. 

67 """ 

68 

69 

70@export 

71class SequentialStatementsMixin(metaclass=ExtendedType, mixin=True, expects=("_LabelRegion", )): 

72 """ 

73 A mixin-class for language constructs containing sequential statements. 

74 

75 The statements are available in declaration order as :data:`Statements`. 

76 

77 .. seealso:: 

78 

79 * :class:`Process statement <pyVHDLModel.Concurrent.ProcessStatement>` 

80 * :class:`Branch <pyVHDLModel.Sequential.Branch>` 

81 * :class:`Sequential case <pyVHDLModel.Sequential.SequentialCase>` 

82 * :class:`Loop statement <pyVHDLModel.Sequential.LoopStatement>` 

83 * :class:`Subprogram <pyVHDLModel.Subprogram.Subprogram>` 

84 """ 

85 _statements: list[SequentialStatement] #: List of all sequential statements in this construct. 

86 

87 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None) -> None: 

88 # TODO: extract to mixin 

89 """ 

90 Initializes sequential statements. 

91 

92 :param statements: List of all sequential statements in this construct. 

93 """ 

94 self._statements = statementList = [] 

95 if statements is not None: 

96 for item in statements: 

97 statementList.append(item) 

98 item.Parent = self 

99 

100 @readonly 

101 def Statements(self) -> list[SequentialStatement]: 

102 """ 

103 Read-only property to access the list of sequential statements (:attr:`_statements`). 

104 

105 :returns: A list of sequential statements. 

106 """ 

107 return self._statements 

108 

109 def _VisitStatements(self, visitor: Visitor) -> None: 

110 """ 

111 Walk the sequential statements in statement order with a visitor. 

112 

113 :param visitor: The visitor receiving the events. 

114 """ 

115 for statement in self._statements: 

116 statement.Visit(visitor) 

117 

118 def _Labels(self) -> tuple[SequentialStatement, ...]: 

119 """ 

120 Return the labeled statements of this construct, including the statements nested in compound statements. 

121 

122 Every label of a process or subprogram body is declared in the process' or subprogram's declarative region, also 

123 a label inside an if branch, a case alternative or a loop. 

124 

125 :returns: Tuple of labeled statements, depth-first in statement order. 

126 """ 

127 return tuple(label for statement in self._statements for label in self._LabelsOf(statement)) 

128 

129 @staticmethod 

130 def _LabelsOf(statement: SequentialStatement) -> tuple[SequentialStatement, ...]: 

131 """ 

132 Return a statement, if it's labeled, and the labeled statements nested in it. 

133 

134 :param statement: The sequential statement. 

135 :returns: Tuple of labeled statements, depth-first in statement order. 

136 """ 

137 labels: list[SequentialStatement] = [] if statement._normalizedLabel is None else [statement] 

138 if isinstance(statement, SequentialStatementsMixin): 

139 labels.extend(statement._Labels()) 

140 elif isinstance(statement, IfStatement): 

141 labels.extend(statement._ifBranch._Labels()) 

142 for branch in statement._elsifBranches: 142 ↛ 143line 142 didn't jump to line 143 because the loop on line 142 never started

143 labels.extend(branch._Labels()) 

144 

145 if statement._elseBranch is not None: 145 ↛ 146line 145 didn't jump to line 146 because the condition on line 145 was never true

146 labels.extend(statement._elseBranch._Labels()) 

147 elif isinstance(statement, CaseStatement): 

148 for case in statement._cases: 

149 labels.extend(case._Labels()) 

150 

151 return tuple(labels) 

152 

153 def AddStatement(self, statement: SequentialStatement) -> None: 

154 """ 

155 Add a sequential statement at the end of this construct. 

156 

157 The statement's parent is set to this construct. 

158 

159 :param statement: The sequential statement to add. 

160 :raises ValueError: If parameter 'statement' is ``None``. 

161 :raises TypeError: If parameter 'statement' is not of type :class:`SequentialStatement`. 

162 :raises AlreadyInDesignError: If parameter 'statement' already has a parent. 

163 :raises DuplicateLabelError: If the declarative region already declares a label of the statement. 

164 

165 .. seealso:: 

166 

167 :meth:`InsertStatement` 

168 |rarr| Insert a sequential statement at a position of this construct. 

169 :meth:`RemoveStatement` 

170 |rarr| Remove a sequential statement from this construct. 

171 """ 

172 self.InsertStatement(len(self._statements), statement) 

173 

174 def InsertStatement(self, index: int, statement: SequentialStatement) -> None: 

175 """ 

176 Insert a sequential statement at a position of this construct. 

177 

178 The statement's parent is set to this construct. 

179 

180 Every label of a process or subprogram body is declared in the process' or subprogram's declarative region: the 

181 statement's label and the labels of statements nested in it (in branches, case alternatives and loops) may neither 

182 repeat another label of the body, nor an identifier declared in the region. A construct not in a process or 

183 subprogram (yet) checks the labels of its own statements. An unlabeled statement declares nothing. 

184 

185 :param index: Position, from ``0`` (first) to the number of statements (append). A negative index 

186 counts from the end, as for :meth:`list.insert`: ``-1`` inserts before the last 

187 statement. 

188 :param statement: The sequential statement to insert. 

189 :raises ValueError: If parameter 'index' is ``None``. 

190 :raises TypeError: If parameter 'index' is not of type :class:`int`. 

191 :raises ValueError: If parameter 'index' is out of range. 

192 :raises ValueError: If parameter 'statement' is ``None``. 

193 :raises TypeError: If parameter 'statement' is not of type :class:`SequentialStatement`. 

194 :raises AlreadyInDesignError: If parameter 'statement' already has a parent. 

195 :raises DuplicateLabelError: If the declarative region already declares a label of the statement. 

196 

197 .. seealso:: 

198 

199 :meth:`AddStatement` 

200 |rarr| Add a sequential statement at the end of this construct. 

201 :meth:`InsertStatementBefore` 

202 |rarr| Insert a sequential statement before another statement. 

203 :meth:`InsertStatementAfter` 

204 |rarr| Insert a sequential statement after another statement. 

205 :meth:`RemoveStatement` 

206 |rarr| Remove a sequential statement from this construct. 

207 :meth:`MoveStatement` 

208 |rarr| Move a sequential statement to a position of this construct. 

209 """ 

210 if index is None: 

211 raise ValueError("Parameter 'index' is None.") 

212 elif not isinstance(index, int): 

213 ex = TypeError("Parameter 'index' is not of type 'int'.") 

214 ex.add_note(f"Got type '{getFullyQualifiedName(index)}'.") 

215 raise ex 

216 elif not (-len(self._statements) <= index <= len(self._statements)): 

217 ex = ValueError(f"Parameter 'index' is out of range {-len(self._statements)}..{len(self._statements)}.") 

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

219 raise ex 

220 

221 if statement is None: 

222 raise ValueError("Parameter 'statement' is None.") 

223 elif not isinstance(statement, SequentialStatement): 

224 ex = TypeError("Parameter 'statement' is not of type 'SequentialStatement'.") 

225 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.") 

226 raise ex 

227 elif statement._parent is not None: 

228 label = "" if statement._label is None else f" '{statement._label}'" 

229 ex = AlreadyInDesignError( 

230 f"{getTypeName(statement)}{label} already has a parent.", 

231 element=statement, 

232 parent=statement._parent 

233 ) 

234 ex.add_note(f"Remove it from its {getTypeName(statement._parent)} first.") 

235 raise ex 

236 

237 region = self._LabelRegion() 

238 for labeled in self._LabelsOf(statement): 

239 if region is None: 

240 clashes = tuple(item for item in self._Labels() if item._normalizedLabel == labeled._normalizedLabel) 

241 else: 

242 clashes = region._ClashingDeclarations(labeled) 

243 

244 if len(clashes) > 0: 

245 construct = self if region is None else region 

246 ex = DuplicateLabelError( 

247 f"{getTypeName(construct)} already declares '{labeled._label}'.", 

248 identifier=labeled._label, 

249 namespace=None if region is None else region._namespace, 

250 element=labeled, 

251 existing=clashes[0] 

252 ) 

253 ex.add_note(f"Existing declaration is of type '{getFullyQualifiedName(clashes[0])}'.") 

254 raise ex 

255 

256 self._statements.insert(index, statement) 

257 statement.Parent = self 

258 

259 def InsertStatementBefore(self, statement: SequentialStatement, before: SequentialStatement) -> None: 

260 """ 

261 Insert a sequential statement before another statement of this construct. 

262 

263 The statement's parent is set to this construct. 

264 

265 :param statement: The sequential statement to insert. 

266 :param before: The statement of this construct to insert before. 

267 :raises ValueError: If parameter 'before' is ``None``. 

268 :raises TypeError: If parameter 'before' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

269 :raises NotAChildError: If parameter 'before' is not a statement of this construct. 

270 :raises ValueError: If parameter 'statement' is ``None``. 

271 :raises TypeError: If parameter 'statement' is not of type :class:`SequentialStatement`. 

272 :raises AlreadyInDesignError: If parameter 'statement' already has a parent. 

273 :raises DuplicateLabelError: If the declarative region already declares a label of the statement. 

274 

275 .. seealso:: 

276 

277 :meth:`InsertStatement` 

278 |rarr| Insert a sequential statement at a position of this construct. 

279 :meth:`InsertStatementAfter` 

280 |rarr| Insert a sequential statement after another statement. 

281 """ 

282 if before is None: 282 ↛ 283line 282 didn't jump to line 283 because the condition on line 282 was never true

283 raise ValueError("Parameter 'before' is None.") 

284 elif not isinstance(before, ModelEntity): 284 ↛ 285line 284 didn't jump to line 285 because the condition on line 284 was never true

285 ex = TypeError("Parameter 'before' is not of type 'ModelEntity'.") 

286 ex.add_note(f"Got type '{getFullyQualifiedName(before)}'.") 

287 raise ex 

288 

289 for index, item in enumerate(self._statements): 

290 if item is before: 

291 break 

292 else: 

293 label = "" 

294 if isinstance(before, LabeledEntityMixin) and before._label is not None: 294 ↛ 296line 294 didn't jump to line 296 because the condition on line 294 was always true

295 label = f" '{before._label}'" 

296 raise NotAChildError( 

297 f"{getTypeName(before)}{label} is not a statement of this {getTypeName(self)}.", 

298 element=before, 

299 parent=self 

300 ) 

301 

302 self.InsertStatement(index, statement) 

303 

304 def InsertStatementAfter(self, statement: SequentialStatement, after: SequentialStatement) -> None: 

305 """ 

306 Insert a sequential statement after another statement of this construct. 

307 

308 The statement's parent is set to this construct. 

309 

310 :param statement: The sequential statement to insert. 

311 :param after: The statement of this construct to insert after. 

312 :raises ValueError: If parameter 'after' is ``None``. 

313 :raises TypeError: If parameter 'after' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

314 :raises NotAChildError: If parameter 'after' is not a statement of this construct. 

315 :raises ValueError: If parameter 'statement' is ``None``. 

316 :raises TypeError: If parameter 'statement' is not of type :class:`SequentialStatement`. 

317 :raises AlreadyInDesignError: If parameter 'statement' already has a parent. 

318 :raises DuplicateLabelError: If the declarative region already declares a label of the statement. 

319 

320 .. seealso:: 

321 

322 :meth:`InsertStatement` 

323 |rarr| Insert a sequential statement at a position of this construct. 

324 :meth:`InsertStatementBefore` 

325 |rarr| Insert a sequential statement before another statement. 

326 """ 

327 if after is None: 327 ↛ 328line 327 didn't jump to line 328 because the condition on line 327 was never true

328 raise ValueError("Parameter 'after' is None.") 

329 elif not isinstance(after, ModelEntity): 329 ↛ 330line 329 didn't jump to line 330 because the condition on line 329 was never true

330 ex = TypeError("Parameter 'after' is not of type 'ModelEntity'.") 

331 ex.add_note(f"Got type '{getFullyQualifiedName(after)}'.") 

332 raise ex 

333 

334 for index, item in enumerate(self._statements): 

335 if item is after: 335 ↛ 334line 335 didn't jump to line 334 because the condition on line 335 was always true

336 break 

337 else: 

338 label = "" 

339 if isinstance(after, LabeledEntityMixin) and after._label is not None: 339 ↛ 340line 339 didn't jump to line 340 because the condition on line 339 was never true

340 label = f" '{after._label}'" 

341 raise NotAChildError( 

342 f"{getTypeName(after)}{label} is not a statement of this {getTypeName(self)}.", 

343 element=after, 

344 parent=self 

345 ) 

346 

347 self.InsertStatement(index + 1, statement) 

348 

349 def RemoveStatement(self, statement: SequentialStatement) -> None: 

350 """ 

351 Remove a sequential statement from this construct. 

352 

353 The statement is detached: its parent is cleared. The statement itself is unchanged and can be added to another 

354 construct, or inserted at another position; its labels are free again in this construct's declarative region. 

355 

356 :param statement: The sequential statement to remove. 

357 :raises ValueError: If parameter 'statement' is ``None``. 

358 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

359 :raises NotAChildError: If parameter 'statement' is not a statement of this construct. 

360 

361 .. seealso:: 

362 

363 :meth:`AddStatement` 

364 |rarr| Add a sequential statement at the end of this construct. 

365 :meth:`InsertStatement` 

366 |rarr| Insert a sequential statement at a position of this construct. 

367 :meth:`MoveStatement` 

368 |rarr| Move a sequential statement to a position of this construct. 

369 """ 

370 if statement is None: 

371 raise ValueError("Parameter 'statement' is None.") 

372 elif not isinstance(statement, ModelEntity): 

373 ex = TypeError("Parameter 'statement' is not of type 'ModelEntity'.") 

374 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.") 

375 raise ex 

376 

377 for index, item in enumerate(self._statements): 

378 if item is statement: 378 ↛ 377line 378 didn't jump to line 377 because the condition on line 378 was always true

379 break 

380 else: 

381 label = "" 

382 if isinstance(statement, LabeledEntityMixin) and statement._label is not None: 382 ↛ 384line 382 didn't jump to line 384 because the condition on line 382 was always true

383 label = f" '{statement._label}'" 

384 raise NotAChildError( 

385 f"{getTypeName(statement)}{label} is not a statement of this {getTypeName(self)}.", 

386 element=statement, 

387 parent=self 

388 ) 

389 

390 del self._statements[index] 

391 statement._parent = None 

392 

393 def MoveStatement(self, statement: SequentialStatement, index: int) -> None: 

394 """ 

395 Move a sequential statement to a position of this construct. 

396 

397 The statement stays a statement of this construct: only the order of the statements changes. 

398 

399 :param statement: The sequential statement to move. 

400 :param index: Position of the statement after the move, from ``0`` (first) to the number of statements 

401 minus one (last). A negative index counts from the end, as for a :class:`list` index: ``-1`` 

402 moves the statement to the end. 

403 :raises ValueError: If parameter 'statement' is ``None``. 

404 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

405 :raises NotAChildError: If parameter 'statement' is not a statement of this construct. 

406 :raises ValueError: If parameter 'index' is ``None``. 

407 :raises TypeError: If parameter 'index' is not of type :class:`int`. 

408 :raises ValueError: If parameter 'index' is out of range. 

409 

410 .. seealso:: 

411 

412 :meth:`MoveStatementBefore` 

413 |rarr| Move a sequential statement before another statement. 

414 :meth:`MoveStatementAfter` 

415 |rarr| Move a sequential statement after another statement. 

416 :meth:`InsertStatement` 

417 |rarr| Insert a sequential statement at a position of this construct. 

418 :meth:`RemoveStatement` 

419 |rarr| Remove a sequential statement from this construct. 

420 """ 

421 if statement is None: 

422 raise ValueError("Parameter 'statement' is None.") 

423 elif not isinstance(statement, ModelEntity): 

424 ex = TypeError("Parameter 'statement' is not of type 'ModelEntity'.") 

425 ex.add_note(f"Got type '{getFullyQualifiedName(statement)}'.") 

426 raise ex 

427 

428 for currentIndex, item in enumerate(self._statements): 

429 if item is statement: 

430 break 

431 else: 

432 label = "" 

433 if isinstance(statement, LabeledEntityMixin) and statement._label is not None: 433 ↛ 435line 433 didn't jump to line 435 because the condition on line 433 was always true

434 label = f" '{statement._label}'" 

435 raise NotAChildError( 

436 f"{getTypeName(statement)}{label} is not a statement of this {getTypeName(self)}.", 

437 element=statement, 

438 parent=self 

439 ) 

440 

441 if index is None: 441 ↛ 442line 441 didn't jump to line 442 because the condition on line 441 was never true

442 raise ValueError("Parameter 'index' is None.") 

443 elif not isinstance(index, int): 443 ↛ 444line 443 didn't jump to line 444 because the condition on line 443 was never true

444 ex = TypeError("Parameter 'index' is not of type 'int'.") 

445 ex.add_note(f"Got type '{getFullyQualifiedName(index)}'.") 

446 raise ex 

447 elif not (-len(self._statements) <= index < len(self._statements)): 

448 ex = ValueError(f"Parameter 'index' is out of range {-len(self._statements)}..{len(self._statements) - 1}.") 

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

450 raise ex 

451 

452 newIndex = index if index >= 0 else len(self._statements) + index 

453 del self._statements[currentIndex] 

454 self._statements.insert(newIndex, statement) 

455 

456 def MoveStatementBefore(self, statement: SequentialStatement, before: SequentialStatement) -> None: 

457 """ 

458 Move a sequential statement before another statement of this construct. 

459 

460 The statement stays a statement of this construct: only the order of the statements changes, as for 

461 :meth:`MoveStatement`. Moving a statement before itself keeps it in place. 

462 

463 :param statement: The sequential statement to move. 

464 :param before: The statement of this construct to move before. 

465 :raises ValueError: If parameter 'before' is ``None``. 

466 :raises TypeError: If parameter 'before' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

467 :raises NotAChildError: If parameter 'before' is not a statement of this construct. 

468 :raises ValueError: If parameter 'statement' is ``None``. 

469 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

470 :raises NotAChildError: If parameter 'statement' is not a statement of this construct. 

471 

472 .. seealso:: 

473 

474 :meth:`MoveStatement` 

475 |rarr| Move a sequential statement to a position of this construct. 

476 :meth:`MoveStatementAfter` 

477 |rarr| Move a sequential statement after another statement. 

478 """ 

479 if before is None: 479 ↛ 480line 479 didn't jump to line 480 because the condition on line 479 was never true

480 raise ValueError("Parameter 'before' is None.") 

481 elif not isinstance(before, ModelEntity): 481 ↛ 482line 481 didn't jump to line 482 because the condition on line 481 was never true

482 ex = TypeError("Parameter 'before' is not of type 'ModelEntity'.") 

483 ex.add_note(f"Got type '{getFullyQualifiedName(before)}'.") 

484 raise ex 

485 

486 for index, item in enumerate(self._statements): 486 ↛ 490line 486 didn't jump to line 490 because the loop on line 486 didn't complete

487 if item is before: 487 ↛ 486line 487 didn't jump to line 486 because the condition on line 487 was always true

488 break 

489 else: 

490 label = "" 

491 if isinstance(before, LabeledEntityMixin) and before._label is not None: 

492 label = f" '{before._label}'" 

493 raise NotAChildError( 

494 f"{getTypeName(before)}{label} is not a statement of this {getTypeName(self)}.", 

495 element=before, 

496 parent=self 

497 ) 

498 

499 precedes = any(item is statement for item in self._statements[:index]) 

500 self.MoveStatement(statement, index - 1 if precedes else index) 

501 

502 def MoveStatementAfter(self, statement: SequentialStatement, after: SequentialStatement) -> None: 

503 """ 

504 Move a sequential statement after another statement of this construct. 

505 

506 The statement stays a statement of this construct: only the order of the statements changes, as for 

507 :meth:`MoveStatement`. Moving a statement after itself keeps it in place. 

508 

509 :param statement: The sequential statement to move. 

510 :param after: The statement of this construct to move after. 

511 :raises ValueError: If parameter 'after' is ``None``. 

512 :raises TypeError: If parameter 'after' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

513 :raises NotAChildError: If parameter 'after' is not a statement of this construct. 

514 :raises ValueError: If parameter 'statement' is ``None``. 

515 :raises TypeError: If parameter 'statement' is not of type :class:`~pyVHDLModel.Base.ModelEntity`. 

516 :raises NotAChildError: If parameter 'statement' is not a statement of this construct. 

517 

518 .. seealso:: 

519 

520 :meth:`MoveStatement` 

521 |rarr| Move a sequential statement to a position of this construct. 

522 :meth:`MoveStatementBefore` 

523 |rarr| Move a sequential statement before another statement. 

524 """ 

525 if after is None: 525 ↛ 526line 525 didn't jump to line 526 because the condition on line 525 was never true

526 raise ValueError("Parameter 'after' is None.") 

527 elif not isinstance(after, ModelEntity): 527 ↛ 528line 527 didn't jump to line 528 because the condition on line 527 was never true

528 ex = TypeError("Parameter 'after' is not of type 'ModelEntity'.") 

529 ex.add_note(f"Got type '{getFullyQualifiedName(after)}'.") 

530 raise ex 

531 

532 for index, item in enumerate(self._statements): 

533 if item is after: 

534 break 

535 else: 

536 label = "" 

537 if isinstance(after, LabeledEntityMixin) and after._label is not None: 537 ↛ 538line 537 didn't jump to line 538 because the condition on line 537 was never true

538 label = f" '{after._label}'" 

539 raise NotAChildError( 

540 f"{getTypeName(after)}{label} is not a statement of this {getTypeName(self)}.", 

541 element=after, 

542 parent=self 

543 ) 

544 

545 precedes = any(item is statement for item in self._statements[:index + 1]) 

546 self.MoveStatement(statement, index if precedes else index + 1) 

547 

548 

549@export 

550class SequentialProcedureCall(SequentialStatement, ProcedureCallMixin): 

551 """ 

552 Represents a procedure call as a sequential statement. 

553 

554 Like every sequential statement, it can carry an optional label (:data:`Label`). 

555 

556 .. admonition:: Example 

557 

558 .. code-block:: VHDL 

559 

560 lbl : log("hello"); 

561 --^^^ <- optional Label 

562 -- ^^^^^^^^^^^^ <- the call 

563 

564 .. seealso:: 

565 

566 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentProcedureCall>` 

567 """ 

568 def __init__( 

569 self, 

570 procedureName: Symbol, 

571 parameterAssociationItems: Nullable[Iterable[ParameterAssociationItem]] = None, 

572 label: Nullable[str] = None, 

573 parent: Nullable[ModelEntity] = None 

574 ) -> None: 

575 """ 

576 Initializes a procedure call as a sequential statement. 

577 

578 :param procedureName: Reference to the called procedure. 

579 :param parameterAssociationItems: List of all parameter associations of the call. 

580 :param label: The label of a model entity. 

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

582 """ 

583 super().__init__(label, parent) 

584 ProcedureCallMixin.__init__(self, procedureName, parameterAssociationItems) 

585 

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

587 """ 

588 Walk this procedure call, its procedure and its parameters with a visitor. 

589 

590 :param visitor: The visitor receiving the events. 

591 """ 

592 visitor.VisitSequentialProcedureCall(self) 

593 self._VisitProcedureCall(visitor) 

594 visitor.DepartSequentialProcedureCall(self) 

595 

596 

597@export 

598class SequentialSignalAssignment(SequentialStatement, SignalAssignmentMixin): 

599 """ 

600 Represents the base-class of all sequential signal assignments. 

601 

602 .. seealso:: 

603 

604 * :class:`Sequential simple signal assignment <pyVHDLModel.Sequential.SequentialSimpleSignalAssignment>` 

605 """ 

606 def __init__(self, target: SignalSymbol, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

607 """ 

608 Initializes a sequential signal assignment. 

609 

610 :param target: Reference to the assignment's destination. 

611 :param label: The label of a model entity. 

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

613 """ 

614 super().__init__(label, parent) 

615 SignalAssignmentMixin.__init__(self, target) 

616 

617 

618@export 

619class SequentialSimpleSignalAssignment(SequentialSignalAssignment, WaveformMixin): 

620 """ 

621 Represents a simple sequential signal assignment. 

622 

623 The assignment's destination is available as :data:`Target`, its value as :data:`Waveform`. 

624 

625 .. admonition:: Example 

626 

627 .. code-block:: VHDL 

628 

629 lbl : s <= '1'; 

630 --^^^ <- optional Label 

631 -- ^ <- Target 

632 -- ^^^ <- Waveform 

633 

634 .. seealso:: 

635 

636 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentSimpleSignalAssignment>` 

637 """ 

638 def __init__(self, target: SignalSymbol, waveform: Iterable[WaveformElement], label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

639 """ 

640 Initializes a simple sequential signal assignment. 

641 

642 :param target: Reference to the assignment's destination. 

643 :param waveform: List of all waveform elements, in the order they were written. 

644 :param label: The label of a model entity. 

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

646 """ 

647 super().__init__(target, label, parent) 

648 WaveformMixin.__init__(self, waveform) 

649 

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

651 """ 

652 Walk this signal assignment, its target and its waveform with a visitor. 

653 

654 :param visitor: The visitor receiving the events. 

655 """ 

656 visitor.VisitSequentialSimpleSignalAssignment(self) 

657 self._target.Visit(visitor) 

658 visitor.VisitSignalAssignment(self) 

659 self._VisitWaveform(visitor) 

660 visitor.DepartSequentialSimpleSignalAssignment(self) 

661 

662 

663@export 

664class SequentialVariableAssignment(SequentialStatement, VariableAssignmentMixin): 

665 """ 

666 Represents a simple sequential variable assignment. 

667 

668 The assignment's destination is available as :data:`Target`, its value as :data:`Expression`. 

669 

670 .. admonition:: Example 

671 

672 .. code-block:: VHDL 

673 

674 lbl : v := '1'; 

675 --^^^ <- optional Label 

676 -- ^ <- Target 

677 -- ^^^ <- Expression 

678 """ 

679 def __init__(self, target: VariableSymbol, expression: ExpressionUnion, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

680 """ 

681 Initializes a simple sequential variable assignment. 

682 

683 :param target: Reference to the assignment's destination. 

684 :param expression: The assigned expression. 

685 :param label: The label of a model entity. 

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

687 """ 

688 super().__init__(label, parent) 

689 VariableAssignmentMixin.__init__(self, target, expression) 

690 

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

692 """ 

693 Walk this variable assignment, its target and its expression with a visitor. 

694 

695 :param visitor: The visitor receiving the events. 

696 """ 

697 visitor.VisitSequentialVariableAssignment(self) 

698 self._target.Visit(visitor) 

699 visitor.VisitVariableAssignment(self) 

700 self._expression.Visit(visitor) 

701 visitor.DepartSequentialVariableAssignment(self) 

702 

703 

704@export 

705class SequentialConditionalVariableAssignment(SequentialStatement, AssignmentMixin): 

706 """ 

707 Represents a conditional sequential variable assignment. 

708 

709 The alternatives are available as :data:`ConditionalExpressions`, a list of 

710 :class:`~pyVHDLModel.Common.ConditionalExpression`. The model holds them in a list and has no 

711 distinct field per alternative, so the markers below name list elements. 

712 

713 .. admonition:: Example 

714 

715 .. code-block:: VHDL 

716 

717 lbl : v := '1' when sel = '0' else '0'; 

718 --^^^ <- optional Label 

719 -- ^ <- Target 

720 -- ^^^^^^^^^^^^^^^^^^ <- ConditionalExpressions[0] 

721 -- ^^^ <- ConditionalExpressions[1] 

722 

723 .. seealso:: 

724 

725 * :class:`Conditional expression <pyVHDLModel.Common.ConditionalExpression>` 

726 """ 

727 

728 _conditionalExpressions: list[ConditionalExpression] #: List of all alternatives, in the order they were written. 

729 

730 def __init__( 

731 self, 

732 target: VariableSymbol, 

733 conditionalExpressions: Iterable[ConditionalExpression], 

734 label: Nullable[str] = None, 

735 parent: Nullable[ModelEntity] = None 

736 ) -> None: 

737 """ 

738 Initializes a conditional sequential variable assignment. 

739 

740 :param target: Reference to the assignment's destination. 

741 :param conditionalExpressions: List of all alternatives, in the order they were written. 

742 :param label: The label of a model entity. 

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

744 """ 

745 super().__init__(label, parent) 

746 AssignmentMixin.__init__(self, target) 

747 

748 self._conditionalExpressions = conditionalExpressionList = [] 

749 for conditionalExpression in conditionalExpressions: 

750 conditionalExpressionList.append(conditionalExpression) 

751 conditionalExpression.Parent = self 

752 

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

754 """ 

755 Walk this conditional variable assignment, its target and its alternatives with a visitor. 

756 

757 :param visitor: The visitor receiving the events. 

758 """ 

759 visitor.VisitSequentialConditionalVariableAssignment(self) 

760 self._target.Visit(visitor) 

761 visitor.VisitVariableAssignment(self) 

762 for index, conditionalExpression in enumerate(self._conditionalExpressions): 

763 if index > 0: 

764 visitor.VisitElse(self) 

765 

766 conditionalExpression.Visit(visitor) 

767 

768 visitor.DepartSequentialConditionalVariableAssignment(self) 

769 

770 @readonly 

771 def ConditionalExpressions(self) -> list[ConditionalExpression]: 

772 """ 

773 Read-only property to access the conditional expressions (:attr:`_conditionalExpressions`). 

774 

775 :returns: List of conditional expressions. 

776 """ 

777 return self._conditionalExpressions 

778 

779 

780@export 

781class SequentialConditionalSignalAssignment(SequentialStatement, SignalAssignmentMixin, ConditionalWaveformsMixin): 

782 """ 

783 Represents a conditional sequential signal assignment. 

784 

785 The alternatives are available as :data:`ConditionalWaveforms`, a list of 

786 :class:`~pyVHDLModel.Common.ConditionalWaveform`. The model holds them in a list and has no 

787 distinct field per alternative, so the markers below name list elements. 

788 

789 .. admonition:: Example 

790 

791 .. code-block:: VHDL 

792 

793 lbl : s <= '1' when sel = '0' else '0'; 

794 --^^^ <- optional Label 

795 -- ^ <- Target 

796 -- ^^^^^^^^^^^^^^^^^^ <- ConditionalWaveforms[0] 

797 -- ^^^ <- ConditionalWaveforms[1] 

798 

799 .. seealso:: 

800 

801 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment>` 

802 * :class:`Conditional waveform <pyVHDLModel.Common.ConditionalWaveform>` 

803 """ 

804 

805 def __init__( 

806 self, 

807 target: SignalSymbol, 

808 conditionalWaveforms: Iterable[ConditionalWaveform], 

809 label: Nullable[str] = None, 

810 parent: Nullable[ModelEntity] = None 

811 ) -> None: 

812 """ 

813 Initializes a conditional sequential signal assignment. 

814 

815 :param target: Reference to the assignment's destination. 

816 :param conditionalWaveforms: All alternatives, in order. 

817 :param label: The label of a model entity. 

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

819 """ 

820 super().__init__(label, parent) 

821 SignalAssignmentMixin.__init__(self, target) 

822 ConditionalWaveformsMixin.__init__(self, conditionalWaveforms) 

823 

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

825 """ 

826 Walk this conditional signal assignment, its target and its alternatives with a visitor. 

827 

828 :param visitor: The visitor receiving the events. 

829 """ 

830 visitor.VisitSequentialConditionalSignalAssignment(self) 

831 self._target.Visit(visitor) 

832 visitor.VisitSignalAssignment(self) 

833 self._VisitConditionalWaveforms(visitor) 

834 visitor.DepartSequentialConditionalSignalAssignment(self) 

835 

836 

837@export 

838class SequentialSelectedVariableAssignment(SequentialStatement, AssignmentMixin, ExpressionMixin, SelectedExpressionsMixin): 

839 """ 

840 Represents a selected sequential variable assignment. 

841 

842 The selector is available as :data:`Expression`, the alternatives as :data:`SelectedExpressions`, 

843 a list of :class:`~pyVHDLModel.Common.SelectedExpression`. The model holds them in a list and has 

844 no distinct field per alternative, so the markers below name list elements. 

845 

846 .. admonition:: Example 

847 

848 .. code-block:: VHDL 

849 

850 lbl : with sel select v := '1' when '0', '0' when others; 

851 --^^^ <- optional Label 

852 -- ^^^ <- Expression 

853 -- ^ <- Target 

854 -- ^^^^^^^^^^^^ <- SelectedExpressions[0] 

855 -- ^^^^^^^^^^^^^^^ <- SelectedExpressions[1] 

856 

857 .. seealso:: 

858 

859 * :class:`Selected expression <pyVHDLModel.Common.SelectedExpression>` 

860 """ 

861 

862 def __init__( 

863 self, 

864 target: VariableSymbol, 

865 expression: ExpressionUnion, 

866 selectedExpressions: Iterable[SelectedExpression], 

867 label: Nullable[str] = None, 

868 parent: Nullable[ModelEntity] = None 

869 ) -> None: 

870 """ 

871 Initializes a selected sequential variable assignment. 

872 

873 :param target: Reference to the assignment's destination. 

874 :param expression: The selector expression. 

875 :param selectedExpressions: All alternatives, in order. 

876 :param label: The label of a model entity. 

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

878 """ 

879 super().__init__(label, parent) 

880 AssignmentMixin.__init__(self, target) 

881 ExpressionMixin.__init__(self, expression) 

882 SelectedExpressionsMixin.__init__(self, selectedExpressions) 

883 

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

885 """ 

886 Walk this selected variable assignment, its selector, its target and its alternatives with a visitor. 

887 

888 :param visitor: The visitor receiving the events. 

889 """ 

890 visitor.VisitSequentialSelectedVariableAssignment(self) 

891 self._expression.Visit(visitor) 

892 visitor.VisitSelect(self) 

893 self._target.Visit(visitor) 

894 visitor.VisitVariableAssignment(self) 

895 self._VisitSelectedExpressions(visitor) 

896 visitor.DepartSequentialSelectedVariableAssignment(self) 

897 

898 

899@export 

900class SequentialSelectedSignalAssignment(SequentialStatement, SignalAssignmentMixin, ExpressionMixin, SelectedWaveformsMixin): 

901 """ 

902 Represents a selected sequential signal assignment. 

903 

904 The selector is available as :data:`Expression`, the alternatives as :data:`SelectedWaveforms`, 

905 a list of :class:`~pyVHDLModel.Common.SelectedWaveform`. The model holds them in a list and has 

906 no distinct field per alternative, so the markers below name list elements. 

907 

908 .. admonition:: Example 

909 

910 .. code-block:: VHDL 

911 

912 lbl : with sel select s <= '1' when '0', '0' when others; 

913 --^^^ <- optional Label 

914 -- ^^^ <- Expression 

915 -- ^ <- Target 

916 -- ^^^^^^^^^^^^ <- SelectedWaveforms[0] 

917 -- ^^^^^^^^^^^^^^^ <- SelectedWaveforms[1] 

918 

919 .. seealso:: 

920 

921 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment>` 

922 * :class:`Selected waveform <pyVHDLModel.Common.SelectedWaveform>` 

923 """ 

924 

925 def __init__( 

926 self, 

927 target: SignalSymbol, 

928 expression: ExpressionUnion, 

929 selectedWaveforms: Iterable[SelectedWaveform], 

930 label: Nullable[str] = None, 

931 parent: Nullable[ModelEntity] = None 

932 ) -> None: 

933 """ 

934 Initializes a selected sequential signal assignment. 

935 

936 :param target: Reference to the assignment's destination. 

937 :param expression: The selector expression. 

938 :param selectedWaveforms: All alternatives, in order. 

939 :param label: The label of a model entity. 

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

941 """ 

942 super().__init__(label, parent) 

943 SignalAssignmentMixin.__init__(self, target) 

944 ExpressionMixin.__init__(self, expression) 

945 SelectedWaveformsMixin.__init__(self, selectedWaveforms) 

946 

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

948 """ 

949 Walk this selected signal assignment, its selector, its target and its alternatives with a visitor. 

950 

951 :param visitor: The visitor receiving the events. 

952 """ 

953 visitor.VisitSequentialSelectedSignalAssignment(self) 

954 self._expression.Visit(visitor) 

955 visitor.VisitSelect(self) 

956 self._target.Visit(visitor) 

957 visitor.VisitSignalAssignment(self) 

958 self._VisitSelectedWaveforms(visitor) 

959 visitor.DepartSequentialSelectedSignalAssignment(self) 

960 

961 

962@export 

963class SignalForceAssignment(SequentialStatement, SignalAssignmentMixin, ExpressionMixin): 

964 """ 

965 Represents a signal force assignment. 

966 

967 A force assignment overrides a signal's driver until it is released. 

968 

969 .. admonition:: Example 

970 

971 .. code-block:: VHDL 

972 

973 lbl : s <= force '1'; 

974 --^^^ <- optional Label 

975 -- ^ <- Target 

976 -- ^^^ <- Expression 

977 """ 

978 

979 def __init__( 

980 self, 

981 target: SignalSymbol, 

982 expression: ExpressionUnion, 

983 label: Nullable[str] = None, 

984 parent: Nullable[ModelEntity] = None 

985 ) -> None: 

986 """ 

987 Initializes a signal force assignment. 

988 

989 :param target: Reference to the assignment's destination. 

990 :param expression: The value forced onto the signal. 

991 :param label: The label of a model entity. 

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

993 """ 

994 super().__init__(label, parent) 

995 SignalAssignmentMixin.__init__(self, target) 

996 ExpressionMixin.__init__(self, expression) 

997 

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

999 """ 

1000 Walk this force assignment, its target and its expression with a visitor. 

1001 

1002 :param visitor: The visitor receiving the events. 

1003 """ 

1004 visitor.VisitSignalForceAssignment(self) 

1005 self._target.Visit(visitor) 

1006 visitor.VisitSignalAssignment(self) 

1007 self._expression.Visit(visitor) 

1008 visitor.DepartSignalForceAssignment(self) 

1009 

1010 

1011@export 

1012class SignalReleaseAssignment(SequentialStatement, SignalAssignmentMixin): 

1013 """ 

1014 Represents a signal release assignment. 

1015 

1016 A release assignment ends a previously applied force. 

1017 

1018 .. admonition:: Example 

1019 

1020 .. code-block:: VHDL 

1021 

1022 lbl : s <= release; 

1023 --^^^ <- optional Label 

1024 -- ^ <- Target 

1025 """ 

1026 

1027 def __init__(self, target: SignalSymbol, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

1028 """ 

1029 Initializes a signal release assignment. 

1030 

1031 :param target: Reference to the assignment's destination. 

1032 :param label: The label of a model entity. 

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

1034 """ 

1035 super().__init__(label, parent) 

1036 SignalAssignmentMixin.__init__(self, target) 

1037 

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

1039 """ 

1040 Walk this release assignment and its target with a visitor. 

1041 

1042 :param visitor: The visitor receiving the events. 

1043 """ 

1044 visitor.VisitSignalReleaseAssignment(self) 

1045 self._target.Visit(visitor) 

1046 visitor.VisitSignalAssignment(self) 

1047 visitor.DepartSignalReleaseAssignment(self) 

1048 

1049 

1050@export 

1051class SequentialReportStatement(SequentialStatement, ReportStatementMixin): 

1052 """ 

1053 Represents a sequential report statement. 

1054 

1055 The report string is available as :data:`Message`, the optional severity as :data:`Severity`. 

1056 

1057 .. admonition:: Example 

1058 

1059 .. code-block:: VHDL 

1060 

1061 lbl : report "message" severity note; 

1062 --^^^ <- optional Label 

1063 -- ^^^^^^^^^ <- Message 

1064 -- ^^^^ <- optional Severity 

1065 """ 

1066 def __init__(self, message: ExpressionUnion, severity: Nullable[ExpressionUnion] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

1067 """ 

1068 Initializes a sequential report statement. 

1069 

1070 :param message: The reported message, or ``None`` if none was given. 

1071 :param severity: The reported severity level, or ``None`` if none was given. 

1072 :param label: The label of a model entity. 

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

1074 """ 

1075 super().__init__(label, parent) 

1076 ReportStatementMixin.__init__(self, message, severity) 

1077 

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

1079 """ 

1080 Walk this report statement, its message and its severity with a visitor. 

1081 

1082 :param visitor: The visitor receiving the events. 

1083 """ 

1084 visitor.VisitSequentialReportStatement(self) 

1085 self._VisitReportAndSeverity(visitor) 

1086 visitor.DepartSequentialReportStatement(self) 

1087 

1088 

1089@export 

1090class SequentialAssertStatement(SequentialStatement, AssertStatementMixin): 

1091 """ 

1092 Represents a sequential assertion statement. 

1093 

1094 The checked condition is available as :data:`Condition`, the optional report string as 

1095 :data:`Message` and the optional severity as :data:`Severity`. 

1096 

1097 .. admonition:: Example 

1098 

1099 .. code-block:: VHDL 

1100 

1101 lbl : assert sel = '0' report "bad" severity error; 

1102 --^^^ <- optional Label 

1103 -- ^^^^^^^^^ <- Condition 

1104 -- ^^^^^ <- optional Message 

1105 -- ^^^^^ <- optional Severity 

1106 

1107 .. seealso:: 

1108 

1109 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentAssertStatement>` 

1110 """ 

1111 def __init__( 

1112 self, 

1113 condition: ExpressionUnion, 

1114 message: Nullable[ExpressionUnion] = None, 

1115 severity: Nullable[ExpressionUnion] = None, 

1116 label: Nullable[str] = None, 

1117 parent: Nullable[ModelEntity] = None 

1118 ) -> None: 

1119 """ 

1120 Initializes a sequential assertion statement. 

1121 

1122 :param condition: The condition guarding this statement. 

1123 :param message: The reported message, or ``None`` if none was given. 

1124 :param severity: The reported severity level, or ``None`` if none was given. 

1125 :param label: The label of a model entity. 

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

1127 """ 

1128 super().__init__(label, parent) 

1129 AssertStatementMixin.__init__(self, condition, message, severity) 

1130 

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

1132 """ 

1133 Walk this assertion, its condition, its message and its severity with a visitor. 

1134 

1135 :param visitor: The visitor receiving the events. 

1136 """ 

1137 visitor.VisitSequentialAssertStatement(self) 

1138 self._VisitAssertion(visitor) 

1139 visitor.DepartSequentialAssertStatement(self) 

1140 

1141 

1142@export 

1143@abstractclass 

1144class CompoundStatement(SequentialStatement): 

1145 """ 

1146 Represents the base-class of all compound statements. 

1147 

1148 A compound statement contains further sequential statements: if, case and loop statements. 

1149 

1150 .. seealso:: 

1151 

1152 * :class:`If statement <pyVHDLModel.Sequential.IfStatement>` 

1153 * :class:`Case statement <pyVHDLModel.Sequential.CaseStatement>` 

1154 * :class:`Loop statement <pyVHDLModel.Sequential.LoopStatement>` 

1155 """ 

1156 

1157 

1158@export 

1159@abstractclass 

1160class Branch(ModelEntity, SequentialStatementsMixin): 

1161 """ 

1162 Represents the base-class of all branches of an if statement. 

1163 

1164 .. seealso:: 

1165 

1166 * :class:`If branch <pyVHDLModel.Sequential.IfBranch>` 

1167 * :class:`Elsif branch <pyVHDLModel.Sequential.ElsifBranch>` 

1168 * :class:`Else branch <pyVHDLModel.Sequential.ElseBranch>` 

1169 """ 

1170 

1171 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None: 

1172 """ 

1173 Initializes a branch. 

1174 

1175 :param statements: List of all sequential statements in this construct. 

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

1177 """ 

1178 super().__init__(parent) 

1179 SequentialStatementsMixin.__init__(self, statements) 

1180 

1181 def _LabelRegion(self) -> Nullable[ModelEntity]: 

1182 """ 

1183 Return the process or subprogram declaring the labels of this branch's statements. 

1184 

1185 It's the region of the construct holding the if statement. 

1186 

1187 :returns: The process or subprogram, or ``None`` if the branch isn't part of one (yet). 

1188 """ 

1189 ifStatement = self._parent 

1190 if ifStatement is None or ifStatement._parent is None: 

1191 return None 

1192 

1193 return ifStatement._parent._LabelRegion() 

1194 

1195 

1196@export 

1197class IfBranch(Branch, IfBranchMixin): 

1198 """ 

1199 Represents the ``if`` branch of an if statement. 

1200 

1201 The branch's condition is available as :data:`Condition`, its body as :data:`Statements`. 

1202 

1203 .. admonition:: Example 

1204 

1205 The whole if statement is shown; the bracket marks the part this class represents. 

1206 

1207 .. code-block:: VHDL 

1208 

1209 if sel = '0' then -- ┐ IfBranch 

1210 -- ^^^^^^^^^ -- │ <- Condition 

1211 s <= '0'; -- │ 

1212 --^^^^^^^^^ -- ┘ <- Statements 

1213 elsif sel = '1' then 

1214 s <= '1'; 

1215 else 

1216 s <= '0'; 

1217 end if; 

1218 """ 

1219 def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None: 

1220 """ 

1221 Initializes an if branch. 

1222 

1223 :param condition: The condition guarding this statement. 

1224 :param statements: List of all sequential statements in this construct. 

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

1226 """ 

1227 super().__init__(statements, parent) 

1228 IfBranchMixin.__init__(self, condition) 

1229 

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

1231 """ 

1232 Walk this if branch, its condition and its statements with a visitor. 

1233 

1234 :param visitor: The visitor receiving the events. 

1235 """ 

1236 visitor.VisitIfBranch(self) 

1237 self._condition.Visit(visitor) 

1238 visitor.VisitThen(self) 

1239 self._VisitStatements(visitor) 

1240 visitor.DepartIfBranch(self) 

1241 

1242 

1243@export 

1244class ElsifBranch(Branch, ElsifBranchMixin): 

1245 """ 

1246 Represents an ``elsif`` branch of an if statement. 

1247 

1248 The branch's condition is available as :data:`Condition`, its body as :data:`Statements`. 

1249 An if statement may have any number of them. 

1250 

1251 .. admonition:: Example 

1252 

1253 The whole if statement is shown; the bracket marks the part this class represents. 

1254 

1255 .. code-block:: VHDL 

1256 

1257 if sel = '0' then 

1258 s <= '0'; 

1259 elsif sel = '1' then -- ┐ ElsifBranch 

1260 -- ^^^^^^^^^ -- │ <- Condition 

1261 s <= '1'; -- │ 

1262 --^^^^^^^^^ -- ┘ <- Statements 

1263 else 

1264 s <= '0'; 

1265 end if; 

1266 """ 

1267 def __init__(self, condition: ExpressionUnion, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None: 

1268 """ 

1269 Initializes an ``elsif`` branch of an if statement. 

1270 

1271 :param condition: The condition guarding this statement. 

1272 :param statements: List of all sequential statements in this construct. 

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

1274 """ 

1275 super().__init__(statements, parent) 

1276 ElsifBranchMixin.__init__(self, condition) 

1277 

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

1279 """ 

1280 Walk this elsif branch, its condition and its statements with a visitor. 

1281 

1282 :param visitor: The visitor receiving the events. 

1283 """ 

1284 visitor.VisitElsifBranch(self) 

1285 self._condition.Visit(visitor) 

1286 visitor.VisitThen(self) 

1287 self._VisitStatements(visitor) 

1288 visitor.DepartElsifBranch(self) 

1289 

1290 

1291@export 

1292class ElseBranch(Branch, ElseBranchMixin): 

1293 """ 

1294 Represents the ``else`` branch of an if statement. 

1295 

1296 Unlike the other branches, an else branch has no condition; it only has a body 

1297 (:data:`Statements`). An if statement has at most one. 

1298 

1299 .. admonition:: Example 

1300 

1301 The whole if statement is shown; the bracket marks the part this class represents. 

1302 

1303 .. code-block:: VHDL 

1304 

1305 if sel = '0' then 

1306 s <= '0'; 

1307 elsif sel = '1' then 

1308 s <= '1'; 

1309 else -- ┐ ElseBranch 

1310 s <= '0'; -- │ 

1311 --^^^^^^^^^ -- ┘ <- Statements 

1312 end if; 

1313 """ 

1314 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None: 

1315 """ 

1316 Initializes an else branch. 

1317 

1318 :param statements: List of all sequential statements in this construct. 

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

1320 """ 

1321 super().__init__(statements, parent) 

1322 ElseBranchMixin.__init__(self) 

1323 

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

1325 """ 

1326 Walk this else branch and its statements with a visitor. 

1327 

1328 :param visitor: The visitor receiving the events. 

1329 """ 

1330 visitor.VisitElseBranch(self) 

1331 self._VisitStatements(visitor) 

1332 visitor.DepartElseBranch(self) 

1333 

1334 

1335@export 

1336class IfStatement(CompoundStatement): 

1337 """ 

1338 Represents an if statement. 

1339 

1340 An if statement has one ``if`` branch (:data:`IfBranch`), any number of ``elsif`` branches 

1341 (:data:`ElsIfBranches`) and an optional ``else`` branch (:data:`ElseBranch`). 

1342 

1343 .. admonition:: Example 

1344 

1345 Only an ``if`` branch: 

1346 

1347 .. code-block:: VHDL 

1348 

1349 lbl : if sel = '0' then 

1350 --^^^ <- optional Label 

1351 s <= '0'; 

1352 end if; 

1353 

1354 With ``elsif`` and ``else`` branches: 

1355 

1356 .. code-block:: VHDL 

1357 

1358 lbl : if sel = '0' then 

1359 --^^^ <- optional Label 

1360 -- ^^^^^^^^^^^^^^^^^ <- IfBranch 

1361 s <= '0'; 

1362 elsif sel = '1' then 

1363 --^^^^^^^^^^^^^^^^^^^^ <- ElsIfBranches[0] 

1364 s <= '1'; 

1365 else 

1366 --^^^^ <- ElseBranch 

1367 s <= '0'; 

1368 end if; 

1369 

1370 .. seealso:: 

1371 

1372 * :class:`If-generate statement <pyVHDLModel.Concurrent.IfGenerateStatement>` 

1373 """ 

1374 _ifBranch: IfBranch #: The mandatory ``if`` branch. 

1375 _elsifBranches: list[ElsifBranch] #: List of all ``elsif`` branches, in the order they were written. 

1376 _elseBranch: Nullable[ElseBranch] #: The optional ``else`` branch, or ``None`` if none was given. 

1377 

1378 def __init__( 

1379 self, 

1380 ifBranch: IfBranch, 

1381 elsifBranches: Nullable[Iterable[ElsifBranch]] = None, 

1382 elseBranch: Nullable[ElseBranch] = None, 

1383 label: Nullable[str] = None, 

1384 parent: Nullable[ModelEntity] = None 

1385 ) -> None: 

1386 """ 

1387 Initializes an if statement. 

1388 

1389 :param ifBranch: The mandatory ``if`` branch. 

1390 :param elsifBranches: List of all ``elsif`` branches, in the order they were written. 

1391 :param elseBranch: The optional ``else`` branch, or ``None`` if none was given. 

1392 :param label: The label of a model entity. 

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

1394 """ 

1395 super().__init__(label, parent) 

1396 

1397 self._ifBranch = ifBranch 

1398 ifBranch.Parent = self 

1399 

1400 self._elsifBranches = elsifBranchList = [] 

1401 if elsifBranches is not None: 

1402 for branch in elsifBranches: 

1403 elsifBranchList.append(branch) 

1404 branch.Parent = self 

1405 

1406 if elseBranch is not None: 

1407 self._elseBranch = elseBranch 

1408 elseBranch.Parent = self 

1409 else: 

1410 self._elseBranch = None 

1411 

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

1413 """ 

1414 Walk this if statement and its branches with a visitor. 

1415 

1416 :param visitor: The visitor receiving the events. 

1417 """ 

1418 visitor.VisitIfStatement(self) 

1419 self._ifBranch.Visit(visitor) 

1420 for branch in self._elsifBranches: 

1421 branch.Visit(visitor) 

1422 

1423 if self._elseBranch is not None: 

1424 self._elseBranch.Visit(visitor) 

1425 

1426 visitor.DepartIfStatement(self) 

1427 

1428 @readonly 

1429 def IfBranch(self) -> IfBranch: 

1430 """ 

1431 Read-only property to access the if-branch of the if-statement (:attr:`_ifBranch`). 

1432 

1433 :returns: The if-branch. 

1434 """ 

1435 return self._ifBranch 

1436 

1437 @readonly 

1438 def ElsIfBranches(self) -> list[ElsifBranch]: 

1439 """ 

1440 Read-only property to access the elsif-branch of the if-statement (:attr:`_elsifBranch`). 

1441 

1442 :returns: The elsif-branch. 

1443 """ 

1444 return self._elsifBranches 

1445 

1446 @readonly 

1447 def ElseBranch(self) -> Nullable[ElseBranch]: 

1448 """ 

1449 Read-only property to access the else-branch of the if-statement (:attr:`_elseBranch`). 

1450 

1451 :returns: The else-branch. 

1452 """ 

1453 return self._elseBranch 

1454 

1455 

1456@export 

1457@abstractclass 

1458class SequentialChoice(BaseChoice): 

1459 """ 

1460 Represents the base-class of all choices in a sequential case statement. 

1461 

1462 .. seealso:: 

1463 

1464 * :class:`Indexed choice <pyVHDLModel.Sequential.IndexedChoice>` 

1465 * :class:`Ranged choice <pyVHDLModel.Sequential.RangedChoice>` 

1466 """ 

1467 

1468 

1469@export 

1470class IndexedChoice(SequentialChoice): 

1471 """ 

1472 Represents a case choice given by a single value. 

1473 

1474 The value is available as :data:`Expression`. 

1475 

1476 .. admonition:: Example 

1477 

1478 .. code-block:: VHDL 

1479 

1480 when 0 => v := '1'; 

1481 -- ^ <- Expression 

1482 """ 

1483 _expression: ExpressionUnion #: The expression this choice selects on. 

1484 

1485 def __init__(self, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None: 

1486 """ 

1487 Initializes a case choice given by a single value. 

1488 

1489 :param expression: The expression this choice selects on. 

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

1491 """ 

1492 super().__init__(parent) 

1493 

1494 self._expression = expression 

1495 expression.Parent = self 

1496 

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

1498 """ 

1499 Walk this choice and its value with a visitor. 

1500 

1501 :param visitor: The visitor receiving the events. 

1502 """ 

1503 visitor.VisitIndexedChoice(self) 

1504 self._expression.Visit(visitor) 

1505 visitor.DepartIndexedChoice(self) 

1506 

1507 @readonly 

1508 def Expression(self) -> ExpressionUnion: 

1509 """ 

1510 Read-only property to access the expression (:attr:`_expression`). 

1511 

1512 :returns: The expression. 

1513 """ 

1514 return self._expression 

1515 

1516 def __str__(self) -> str: 

1517 """ 

1518 Formats the indexed case choice. 

1519 

1520 **Format:** ``0`` 

1521 

1522 :returns: Formatted indexed case choice. 

1523 """ 

1524 return str(self._expression) 

1525 

1526 

1527@export 

1528class RangedChoice(SequentialChoice): 

1529 """ 

1530 Represents a case choice given by a range. 

1531 

1532 The range is available as :data:`Range`. 

1533 

1534 .. admonition:: Example 

1535 

1536 .. code-block:: VHDL 

1537 

1538 when 1 to 2 => v := '0'; 

1539 -- ^^^^^^ <- Range 

1540 """ 

1541 _range: Range #: The range this choice selects on. 

1542 

1543 def __init__(self, rng: Range, parent: Nullable[ModelEntity] = None) -> None: 

1544 """ 

1545 Initializes a case choice given by a range. 

1546 

1547 :param rng: The range this choice selects on. 

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

1549 """ 

1550 super().__init__(parent) 

1551 

1552 self._range = rng 

1553 rng.Parent = self 

1554 

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

1556 """ 

1557 Walk this choice and its range with a visitor. 

1558 

1559 :param visitor: The visitor receiving the events. 

1560 """ 

1561 visitor.VisitRangedChoice(self) 

1562 self._range.Visit(visitor) 

1563 visitor.DepartRangedChoice(self) 

1564 

1565 @readonly 

1566 def Range(self) -> Range: 

1567 """ 

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

1569 

1570 :returns: The range. 

1571 """ 

1572 return self._range 

1573 

1574 def __str__(self) -> str: 

1575 """ 

1576 Formats the ranged case choice. 

1577 

1578 **Format:** ``0 to 3`` 

1579 

1580 :returns: Formatted ranged case choice. 

1581 """ 

1582 return str(self._range) 

1583 

1584 

1585@export 

1586class SequentialCase(BaseCase, SequentialStatementsMixin, ChoicesMixin): 

1587 """ 

1588 Represents the base-class of all alternatives of a sequential case statement. 

1589 

1590 .. seealso:: 

1591 

1592 * :class:`Case <pyVHDLModel.Sequential.Case>` 

1593 * :class:`Others case <pyVHDLModel.Sequential.OthersCase>` 

1594 """ 

1595 def __init__( 

1596 self, 

1597 statements: Nullable[Iterable[SequentialStatement]] = None, 

1598 choices: Nullable[Iterable[BaseChoice]] = None, 

1599 parent: Nullable[ModelEntity] = None 

1600 ) -> None: 

1601 """ 

1602 Initializes a sequential case. 

1603 

1604 :param statements: List of all sequential statements in this construct. 

1605 :param choices: List of all choices selecting this alternative. 

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

1607 """ 

1608 super().__init__(parent) 

1609 SequentialStatementsMixin.__init__(self, statements) 

1610 ChoicesMixin.__init__(self, choices) 

1611 

1612 def _LabelRegion(self) -> Nullable[ModelEntity]: 

1613 """ 

1614 Return the process or subprogram declaring the labels of this case alternative's statements. 

1615 

1616 It's the region of the construct holding the case statement. 

1617 

1618 :returns: The process or subprogram, or ``None`` if the case alternative isn't part of one (yet). 

1619 """ 

1620 caseStatement = self._parent 

1621 if caseStatement is None or caseStatement._parent is None: 1621 ↛ 1622line 1621 didn't jump to line 1622 because the condition on line 1621 was never true

1622 return None 

1623 

1624 return caseStatement._parent._LabelRegion() 

1625 

1626 

1627@export 

1628class Case(SequentialCase): 

1629 """ 

1630 Represents one alternative of a case statement, selected by its choices. 

1631 

1632 .. admonition:: Example 

1633 

1634 .. code-block:: VHDL 

1635 

1636 when 1 to 2 => v := '0'; 

1637 -- ^^^^^^ <- Choices 

1638 -- ^^^^^^^^^ <- the statements 

1639 """ 

1640 def __init__(self, choices: Iterable[SequentialChoice], statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None: 

1641 """ 

1642 Initializes a case. 

1643 

1644 :param choices: List of all choices selecting this alternative. 

1645 :param statements: List of all sequential statements in this construct. 

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

1647 """ 

1648 super().__init__(statements, choices, parent) 

1649 

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

1651 """ 

1652 Walk this case alternative, its choices and its statements with a visitor. 

1653 

1654 :param visitor: The visitor receiving the events. 

1655 """ 

1656 visitor.VisitCase(self) 

1657 for index, choice in enumerate(self._choices): 

1658 if index > 0: 

1659 visitor.VisitBar(self) 

1660 

1661 choice.Visit(visitor) 

1662 

1663 visitor.VisitArrow(self) 

1664 self._VisitStatements(visitor) 

1665 visitor.DepartCase(self) 

1666 

1667 def __str__(self) -> str: 

1668 """ 

1669 Formats the case alternative. 

1670 

1671 **Format:** ``when 0 | 1 =>`` 

1672 

1673 :returns: Formatted case alternative. 

1674 """ 

1675 return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices)) 

1676 

1677 

1678@export 

1679class OthersCase(SequentialCase): 

1680 """ 

1681 Represents the ``others`` alternative of a case statement. 

1682 

1683 It covers every choice not named explicitly. 

1684 

1685 .. admonition:: Example 

1686 

1687 .. code-block:: VHDL 

1688 

1689 when others => null; 

1690 -- ^^^^^^ <- the choice 

1691 """ 

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

1693 """ 

1694 Walk this ``others`` case alternative and its statements with a visitor. 

1695 

1696 :param visitor: The visitor receiving the events. 

1697 """ 

1698 visitor.VisitOthersCase(self) 

1699 visitor.VisitArrow(self) 

1700 self._VisitStatements(visitor) 

1701 visitor.DepartOthersCase(self) 

1702 

1703 def __str__(self) -> str: 

1704 """ 

1705 Formats the ``others`` case alternative. 

1706 

1707 **Format:** ``when others =>`` 

1708 

1709 :returns: Formatted ``others`` case alternative. 

1710 """ 

1711 return "when others =>" 

1712 

1713 

1714@export 

1715class CaseStatement(CompoundStatement): 

1716 """ 

1717 Represents a case statement. 

1718 

1719 The expression being tested is available as :data:`SelectExpression`, the alternatives as 

1720 :data:`Cases`. 

1721 

1722 .. admonition:: Example 

1723 

1724 .. code-block:: VHDL 

1725 

1726 lbl : case sel is 

1727 --^^^ <- optional Label 

1728 -- ^^^ <- SelectExpression 

1729 when '0' => s <= '1'; 

1730 -- ^^^^^^^^^^^^^^^^^^^^^^^^ <- Cases[0] 

1731 when others => null; 

1732 -- ^^^^^^^^^^^^^^^^^^^^ <- Cases[1] 

1733 end case; 

1734 

1735 .. seealso:: 

1736 

1737 * :class:`Case-generate statement <pyVHDLModel.Concurrent.CaseGenerateStatement>` 

1738 """ 

1739 _expression: ExpressionUnion #: The expression being tested. 

1740 _cases: list[SequentialCase] #: List of all alternatives, in the order they were written. 

1741 

1742 def __init__(self, expression: ExpressionUnion, cases: Iterable[SequentialCase], label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

1743 """ 

1744 Initializes a case statement. 

1745 

1746 :param expression: The expression being tested. 

1747 :param cases: List of all alternatives, in the order they were written. 

1748 :param label: The label of a model entity. 

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

1750 """ 

1751 super().__init__(label, parent) 

1752 

1753 self._expression = expression 

1754 expression.Parent = self 

1755 

1756 self._cases = caseList = [] 

1757 if cases is not None: 1757 ↛ exitline 1757 didn't return from function '__init__' because the condition on line 1757 was always true

1758 for case in cases: 

1759 caseList.append(case) 

1760 case.Parent = self 

1761 

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

1763 """ 

1764 Walk this case statement, its selector and its alternatives with a visitor. 

1765 

1766 :param visitor: The visitor receiving the events. 

1767 """ 

1768 visitor.VisitCaseStatement(self) 

1769 self._expression.Visit(visitor) 

1770 visitor.VisitIs(self) 

1771 for case in self._cases: 

1772 case.Visit(visitor) 

1773 

1774 visitor.DepartCaseStatement(self) 

1775 

1776 @readonly 

1777 def SelectExpression(self) -> ExpressionUnion: 

1778 """ 

1779 Read-only property to access the select expression (:attr:`_expression`). 

1780 

1781 :returns: The select expression. 

1782 """ 

1783 return self._expression 

1784 

1785 @readonly 

1786 def Cases(self) -> list[SequentialCase]: 

1787 """ 

1788 Read-only property to access the cases (:attr:`_cases`). 

1789 

1790 :returns: List of cases. 

1791 """ 

1792 return self._cases 

1793 

1794 

1795@export 

1796@abstractclass 

1797class LoopStatement(CompoundStatement, SequentialStatementsMixin): 

1798 """ 

1799 Represents the base-class of all loop statements. 

1800 

1801 .. seealso:: 

1802 

1803 * :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>` 

1804 * :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>` 

1805 * :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>` 

1806 """ 

1807 

1808 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

1809 """ 

1810 Initializes a loop statement. 

1811 

1812 :param statements: List of all sequential statements in this construct. 

1813 :param label: The label of a model entity. 

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

1815 """ 

1816 super().__init__(label, parent) 

1817 SequentialStatementsMixin.__init__(self, statements) 

1818 

1819 def _LabelRegion(self) -> Nullable[ModelEntity]: 

1820 """ 

1821 Return the process or subprogram declaring the labels of this loop's statements. 

1822 

1823 It's the region of the construct holding the loop. 

1824 

1825 :returns: The process or subprogram, or ``None`` if the loop isn't part of one (yet). 

1826 """ 

1827 return None if self._parent is None else self._parent._LabelRegion() 

1828 

1829 

1830@export 

1831class EndlessLoopStatement(LoopStatement): 

1832 """ 

1833 Represents an endless loop statement. 

1834 

1835 The loop body is available as :data:`Statements`. The loop has no iteration scheme, so it is 

1836 left with an exit or return statement. 

1837 

1838 .. admonition:: Example 

1839 

1840 .. code-block:: VHDL 

1841 

1842 lbl : loop 

1843 --^^^ <- optional Label 

1844 exit; 

1845 -- ^^^^^ <- Statements 

1846 end loop; 

1847 

1848 .. seealso:: 

1849 

1850 * :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>` 

1851 * :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>` 

1852 """ 

1853 

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

1855 """ 

1856 Walk this loop and its statements with a visitor. 

1857 

1858 :param visitor: The visitor receiving the events. 

1859 """ 

1860 visitor.VisitEndlessLoopStatement(self) 

1861 visitor.VisitLoop(self) 

1862 self._VisitStatements(visitor) 

1863 visitor.DepartEndlessLoopStatement(self) 

1864 

1865 

1866@export 

1867class ForLoopStatement(LoopStatement): 

1868 """ 

1869 Represents a for-loop statement. 

1870 

1871 The loop index is available as :data:`LoopIndex`, the iteration range as :data:`Range` and the 

1872 loop body as :data:`Statements`. 

1873 

1874 .. admonition:: Example 

1875 

1876 .. code-block:: VHDL 

1877 

1878 lbl : for k in 0 to 3 loop 

1879 --^^^ <- optional Label 

1880 -- ^ <- LoopIndex 

1881 -- ^^^^^^ <- Range 

1882 null; 

1883 -- ^^^^^ <- Statements 

1884 end loop; 

1885 

1886 .. seealso:: 

1887 

1888 * :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>` 

1889 * :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>` 

1890 * :class:`For-generate statement <pyVHDLModel.Concurrent.ForGenerateStatement>` 

1891 """ 

1892 _loopIndex: str #: The name of the loop's index. 

1893 _range: Range #: The range the loop iterates over. 

1894 

1895 def __init__(self, loopIndex: str, rng: Range, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: 

1896 """ 

1897 Initializes a for-loop statement. 

1898 

1899 :param loopIndex: The name of the loop's index. 

1900 :param rng: The range the loop iterates over. 

1901 :param statements: List of all sequential statements in this construct. 

1902 :param label: The label of a model entity. 

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

1904 """ 

1905 super().__init__(statements, label, parent) 

1906 

1907 self._loopIndex = loopIndex 

1908 

1909 self._range = rng 

1910 rng.Parent = self 

1911 

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

1913 """ 

1914 Walk this for-loop, its range and its statements with a visitor. 

1915 

1916 :param visitor: The visitor receiving the events. 

1917 """ 

1918 visitor.VisitForLoopStatement(self) 

1919 self._range.Visit(visitor) 

1920 visitor.VisitLoop(self) 

1921 self._VisitStatements(visitor) 

1922 visitor.DepartForLoopStatement(self) 

1923 

1924 @readonly 

1925 def LoopIndex(self) -> str: 

1926 """ 

1927 Read-only property to access the loop index (:attr:`_loopIndex`). 

1928 

1929 :returns: The loop index. 

1930 """ 

1931 return self._loopIndex 

1932 

1933 @readonly 

1934 def Range(self) -> Range: 

1935 """ 

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

1937 

1938 :returns: The range. 

1939 """ 

1940 return self._range 

1941 

1942 

1943@export 

1944class WhileLoopStatement(LoopStatement, ConditionalMixin): 

1945 """ 

1946 Represents a while-loop statement. 

1947 

1948 The loop condition is available as :data:`Condition`, the loop body as :data:`Statements`. 

1949 

1950 .. admonition:: Example 

1951 

1952 .. code-block:: VHDL 

1953 

1954 lbl : while i < 4 loop 

1955 --^^^ <- optional Label 

1956 -- ^^^^^ <- Condition 

1957 null; 

1958 -- ^^^^^ <- Statements 

1959 end loop; 

1960 

1961 .. seealso:: 

1962 

1963 * :class:`Endless loop statement <pyVHDLModel.Sequential.EndlessLoopStatement>` 

1964 * :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>` 

1965 """ 

1966 def __init__( 

1967 self, 

1968 condition: ExpressionUnion, 

1969 statements: Nullable[Iterable[SequentialStatement]] = None, 

1970 label: Nullable[str] = None, 

1971 parent: Nullable[ModelEntity] = None 

1972 ) -> None: 

1973 """ 

1974 Initializes a while-loop statement. 

1975 

1976 :param condition: The condition guarding this statement. 

1977 :param statements: List of all sequential statements in this construct. 

1978 :param label: The label of a model entity. 

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

1980 """ 

1981 super().__init__(statements, label, parent) 

1982 ConditionalMixin.__init__(self, condition) 

1983 

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

1985 """ 

1986 Walk this while-loop, its condition and its statements with a visitor. 

1987 

1988 :param visitor: The visitor receiving the events. 

1989 """ 

1990 visitor.VisitWhileLoopStatement(self) 

1991 self._condition.Visit(visitor) 

1992 visitor.VisitLoop(self) 

1993 self._VisitStatements(visitor) 

1994 visitor.DepartWhileLoopStatement(self) 

1995 

1996 

1997@export 

1998@abstractclass 

1999class LoopControlStatement(SequentialStatement, ConditionalMixin): 

2000 """ 

2001 Represents the base-class of the loop control statements ``next`` and ``exit``. 

2002 

2003 An optional loop label (:data:`LoopReference`) selects which enclosing loop is affected. 

2004 

2005 .. seealso:: 

2006 

2007 * :class:`Next statement <pyVHDLModel.Sequential.NextStatement>` 

2008 * :class:`Exit statement <pyVHDLModel.Sequential.ExitStatement>` 

2009 """ 

2010 

2011 _loopReference: LoopStatement #: Reference to the loop this statement controls. 

2012 

2013 def __init__(self, condition: Nullable[ExpressionUnion] = None, loopLabel: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None: # TODO: is this label (currently str) a Name or a Label class? 

2014 """ 

2015 Initializes a loop control statement. 

2016 

2017 :param condition: The condition guarding this statement. 

2018 :param loopLabel: The label of the controlled loop, or ``None`` for the innermost loop. 

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

2020 """ 

2021 super().__init__(parent) 

2022 ConditionalMixin.__init__(self, condition) 

2023 

2024 self._loopReference = None 

2025 

2026 # TODO: loopLabel 

2027 # TODO: loop reference -> is it a symbol? 

2028 

2029 @readonly 

2030 def LoopReference(self) -> LoopStatement: 

2031 """ 

2032 Read-only property to access the loop reference (:attr:`_loopReference`). 

2033 

2034 :returns: The loop reference. 

2035 """ 

2036 return self._loopReference 

2037 

2038 

2039@export 

2040class NextStatement(LoopControlStatement): 

2041 """ 

2042 Represents a next statement. 

2043 

2044 A next statement skips to the next iteration of the named loop (:data:`LoopReference`), 

2045 optionally only when a condition (:data:`Condition`) holds. 

2046 

2047 .. admonition:: Example 

2048 

2049 .. code-block:: VHDL 

2050 

2051 lbl : next outer when k = 1; 

2052 --^^^ <- optional Label 

2053 -- ^^^^^ <- optional LoopReference 

2054 -- ^^^^^ <- optional Condition 

2055 """ 

2056 

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

2058 """ 

2059 Walk this next statement and its condition (if any) with a visitor. 

2060 

2061 :param visitor: The visitor receiving the events. 

2062 """ 

2063 visitor.VisitNextStatement(self) 

2064 if self._condition is not None: 

2065 visitor.VisitWhen(self) 

2066 self._condition.Visit(visitor) 

2067 

2068 visitor.DepartNextStatement(self) 

2069 

2070 

2071@export 

2072class ExitStatement(LoopControlStatement): 

2073 """ 

2074 Represents an exit statement. 

2075 

2076 An exit statement leaves the named loop (:data:`LoopReference`), optionally only when a 

2077 condition (:data:`Condition`) holds. 

2078 

2079 .. admonition:: Example 

2080 

2081 .. code-block:: VHDL 

2082 

2083 lbl : exit outer when k = 1; 

2084 --^^^ <- optional Label 

2085 -- ^^^^^ <- optional LoopReference 

2086 -- ^^^^^ <- optional Condition 

2087 """ 

2088 

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

2090 """ 

2091 Walk this exit statement and its condition (if any) with a visitor. 

2092 

2093 :param visitor: The visitor receiving the events. 

2094 """ 

2095 visitor.VisitExitStatement(self) 

2096 if self._condition is not None: 

2097 visitor.VisitWhen(self) 

2098 self._condition.Visit(visitor) 

2099 

2100 visitor.DepartExitStatement(self) 

2101 

2102 

2103@export 

2104class NullStatement(SequentialStatement): 

2105 """ 

2106 Represents a null statement. 

2107 

2108 A null statement does nothing. Like every sequential statement, it can carry an optional label 

2109 (:data:`Label`). 

2110 

2111 .. admonition:: Example 

2112 

2113 .. code-block:: VHDL 

2114 

2115 lbl : null; 

2116 --^^^ <- optional Label 

2117 -- ^^^^ <- the statement 

2118 """ 

2119 

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

2121 """ 

2122 Walk this null statement with a visitor. 

2123 

2124 :param visitor: The visitor receiving the events. 

2125 """ 

2126 visitor.VisitNullStatement(self) 

2127 visitor.DepartNullStatement(self) 

2128 

2129 

2130@export 

2131class ReturnStatement(SequentialStatement): 

2132 """ 

2133 Represents a return statement. 

2134 

2135 The optionally returned value is available as :data:`ReturnValue`; a procedure returns nothing. 

2136 

2137 .. admonition:: Example 

2138 

2139 .. code-block:: VHDL 

2140 

2141 lbl : return x; 

2142 --^^^ <- optional Label 

2143 -- ^ <- optional ReturnValue 

2144 """ 

2145 _returnValue: Nullable[ExpressionUnion] #: The returned expression, or ``None`` for a procedure. 

2146 

2147 def __init__( 

2148 self, 

2149 returnValue: Nullable[ExpressionUnion] = None, 

2150 label: Nullable[str] = None, 

2151 parent: Nullable[ModelEntity] = None 

2152 ) -> None: 

2153 """ 

2154 Initializes a return statement. 

2155 

2156 :param returnValue: The returned expression, or ``None`` for a procedure. 

2157 :param label: The label of a model entity. 

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

2159 """ 

2160 super().__init__(label, parent) 

2161 

2162 self._returnValue = returnValue 

2163 if returnValue is not None: 

2164 returnValue.Parent = self 

2165 

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

2167 """ 

2168 Walk this return statement and its value (if any) with a visitor. 

2169 

2170 :param visitor: The visitor receiving the events. 

2171 """ 

2172 visitor.VisitReturnStatement(self) 

2173 if self._returnValue is not None: 

2174 self._returnValue.Visit(visitor) 

2175 

2176 visitor.DepartReturnStatement(self) 

2177 

2178 @readonly 

2179 def ReturnValue(self) -> Nullable[ExpressionUnion]: 

2180 """ 

2181 Read-only property to access the return value (:attr:`_returnValue`). 

2182 

2183 :returns: The return value, or ``None`` if not set. 

2184 """ 

2185 return self._returnValue 

2186 

2187 

2188@export 

2189class WaitStatement(SequentialStatement, ConditionalMixin): 

2190 """ 

2191 Represents a wait statement. 

2192 

2193 A wait statement may name a sensitivity list (:data:`SensitivityList`), a condition 

2194 (:data:`Condition`) and a timeout (:data:`Timeout`); all three are optional. 

2195 

2196 .. admonition:: Example 

2197 

2198 .. code-block:: VHDL 

2199 

2200 lbl : wait until clock = '1' for 10 ns; 

2201 --^^^ <- optional Label 

2202 -- ^^^^^^^^^^^ <- optional Condition 

2203 -- ^^^^^ <- optional Timeout 

2204 """ 

2205 _sensitivityList: Nullable[list[Symbol]] #: List of all signal names to wait on, or ``None`` if none was given. 

2206 _timeout: ExpressionUnion #: The timeout expression, or ``None`` if none was given. 

2207 

2208 def __init__( 

2209 self, 

2210 sensitivityList: Nullable[Iterable[Symbol]] = None, 

2211 condition: Nullable[ExpressionUnion] = None, 

2212 timeout: Nullable[ExpressionUnion] = None, 

2213 label: Nullable[str] = None, 

2214 parent: Nullable[ModelEntity] = None 

2215 ) -> None: 

2216 """ 

2217 Initializes a wait statement. 

2218 

2219 :param sensitivityList: List of all signal names to wait on, or ``None`` if none was given. 

2220 :param condition: The condition guarding this statement. 

2221 :param timeout: The timeout expression, or ``None`` if none was given. 

2222 :param label: The label of a model entity. 

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

2224 """ 

2225 super().__init__(label, parent) 

2226 ConditionalMixin.__init__(self, condition) 

2227 

2228 if sensitivityList is None: 

2229 self._sensitivityList = None 

2230 else: 

2231 self._sensitivityList = signalSymbols = [] # TODO: convert to dict 

2232 for signalSymbol in sensitivityList: 

2233 signalSymbols.append(signalSymbol) 

2234 signalSymbol.Parent = self 

2235 

2236 self._timeout = timeout 

2237 if timeout is not None: 

2238 timeout.Parent = self 

2239 

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

2241 """ 

2242 Walk this wait statement, its sensitivity clause, its condition clause and its timeout clause with a visitor. 

2243 

2244 :param visitor: The visitor receiving the events. 

2245 """ 

2246 visitor.VisitWaitStatement(self) 

2247 if self._sensitivityList is not None: 

2248 visitor.VisitOn(self) 

2249 for index, name in enumerate(self._sensitivityList): 

2250 if index > 0: 

2251 visitor.VisitComma(self) 

2252 

2253 name.Visit(visitor) 

2254 

2255 if self._condition is not None: 

2256 visitor.VisitUntil(self) 

2257 self._condition.Visit(visitor) 

2258 

2259 if self._timeout is not None: 

2260 visitor.VisitFor(self) 

2261 self._timeout.Visit(visitor) 

2262 

2263 visitor.DepartWaitStatement(self) 

2264 

2265 @readonly 

2266 def SensitivityList(self) -> list[Symbol]: 

2267 """ 

2268 Read-only property to access the sensitivity list (:attr:`_sensitivityList`). 

2269 

2270 :returns: List of sensitivity list. 

2271 """ 

2272 return self._sensitivityList 

2273 

2274 @readonly 

2275 def Timeout(self) -> ExpressionUnion: 

2276 """ 

2277 Read-only property to access the timeout (:attr:`_timeout`). 

2278 

2279 :returns: The timeout. 

2280 """ 

2281 return self._timeout 

2282 

2283