Coverage for pyVHDLModel/Sequential.py: 93%
636 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-25 10:05 +0000
« 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.
35Declarations for sequential statements.
36"""
37from __future__ import annotations
39from typing import TYPE_CHECKING, Iterable, Optional as Nullable
41from pyTooling.Common import getFullyQualifiedName, getTypeName
42from pyTooling.Decorators import export, readonly
43from pyTooling.MetaClasses import ExtendedType, abstractclass
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
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
60@export
61@abstractclass
62class SequentialStatement(Statement):
63 """
64 Represents the base-class of all sequential statements.
66 Sequential statements appear in a process or a subprogram body.
67 """
70@export
71class SequentialStatementsMixin(metaclass=ExtendedType, mixin=True, expects=("_LabelRegion", )):
72 """
73 A mixin-class for language constructs containing sequential statements.
75 The statements are available in declaration order as :data:`Statements`.
77 .. seealso::
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.
87 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None) -> None:
88 # TODO: extract to mixin
89 """
90 Initializes sequential statements.
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
100 @readonly
101 def Statements(self) -> list[SequentialStatement]:
102 """
103 Read-only property to access the list of sequential statements (:attr:`_statements`).
105 :returns: A list of sequential statements.
106 """
107 return self._statements
109 def _VisitStatements(self, visitor: Visitor) -> None:
110 """
111 Walk the sequential statements in statement order with a visitor.
113 :param visitor: The visitor receiving the events.
114 """
115 for statement in self._statements:
116 statement.Visit(visitor)
118 def _Labels(self) -> tuple[SequentialStatement, ...]:
119 """
120 Return the labeled statements of this construct, including the statements nested in compound statements.
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.
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))
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.
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())
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())
151 return tuple(labels)
153 def AddStatement(self, statement: SequentialStatement) -> None:
154 """
155 Add a sequential statement at the end of this construct.
157 The statement's parent is set to this construct.
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.
165 .. seealso::
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)
174 def InsertStatement(self, index: int, statement: SequentialStatement) -> None:
175 """
176 Insert a sequential statement at a position of this construct.
178 The statement's parent is set to this construct.
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.
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.
197 .. seealso::
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
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
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)
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
256 self._statements.insert(index, statement)
257 statement.Parent = self
259 def InsertStatementBefore(self, statement: SequentialStatement, before: SequentialStatement) -> None:
260 """
261 Insert a sequential statement before another statement of this construct.
263 The statement's parent is set to this construct.
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.
275 .. seealso::
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
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 )
302 self.InsertStatement(index, statement)
304 def InsertStatementAfter(self, statement: SequentialStatement, after: SequentialStatement) -> None:
305 """
306 Insert a sequential statement after another statement of this construct.
308 The statement's parent is set to this construct.
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.
320 .. seealso::
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
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 )
347 self.InsertStatement(index + 1, statement)
349 def RemoveStatement(self, statement: SequentialStatement) -> None:
350 """
351 Remove a sequential statement from this construct.
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.
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.
361 .. seealso::
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
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 )
390 del self._statements[index]
391 statement._parent = None
393 def MoveStatement(self, statement: SequentialStatement, index: int) -> None:
394 """
395 Move a sequential statement to a position of this construct.
397 The statement stays a statement of this construct: only the order of the statements changes.
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.
410 .. seealso::
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
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 )
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
452 newIndex = index if index >= 0 else len(self._statements) + index
453 del self._statements[currentIndex]
454 self._statements.insert(newIndex, statement)
456 def MoveStatementBefore(self, statement: SequentialStatement, before: SequentialStatement) -> None:
457 """
458 Move a sequential statement before another statement of this construct.
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.
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.
472 .. seealso::
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
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 )
499 precedes = any(item is statement for item in self._statements[:index])
500 self.MoveStatement(statement, index - 1 if precedes else index)
502 def MoveStatementAfter(self, statement: SequentialStatement, after: SequentialStatement) -> None:
503 """
504 Move a sequential statement after another statement of this construct.
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.
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.
518 .. seealso::
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
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 )
545 precedes = any(item is statement for item in self._statements[:index + 1])
546 self.MoveStatement(statement, index if precedes else index + 1)
549@export
550class SequentialProcedureCall(SequentialStatement, ProcedureCallMixin):
551 """
552 Represents a procedure call as a sequential statement.
554 Like every sequential statement, it can carry an optional label (:data:`Label`).
556 .. admonition:: Example
558 .. code-block:: VHDL
560 lbl : log("hello");
561 --^^^ <- optional Label
562 -- ^^^^^^^^^^^^ <- the call
564 .. seealso::
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.
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)
586 def Visit(self, visitor: Visitor) -> None:
587 """
588 Walk this procedure call, its procedure and its parameters with a visitor.
590 :param visitor: The visitor receiving the events.
591 """
592 visitor.VisitSequentialProcedureCall(self)
593 self._VisitProcedureCall(visitor)
594 visitor.DepartSequentialProcedureCall(self)
597@export
598class SequentialSignalAssignment(SequentialStatement, SignalAssignmentMixin):
599 """
600 Represents the base-class of all sequential signal assignments.
602 .. seealso::
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.
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)
618@export
619class SequentialSimpleSignalAssignment(SequentialSignalAssignment, WaveformMixin):
620 """
621 Represents a simple sequential signal assignment.
623 The assignment's destination is available as :data:`Target`, its value as :data:`Waveform`.
625 .. admonition:: Example
627 .. code-block:: VHDL
629 lbl : s <= '1';
630 --^^^ <- optional Label
631 -- ^ <- Target
632 -- ^^^ <- Waveform
634 .. seealso::
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.
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)
650 def Visit(self, visitor: Visitor) -> None:
651 """
652 Walk this signal assignment, its target and its waveform with a visitor.
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)
663@export
664class SequentialVariableAssignment(SequentialStatement, VariableAssignmentMixin):
665 """
666 Represents a simple sequential variable assignment.
668 The assignment's destination is available as :data:`Target`, its value as :data:`Expression`.
670 .. admonition:: Example
672 .. code-block:: VHDL
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.
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)
691 def Visit(self, visitor: Visitor) -> None:
692 """
693 Walk this variable assignment, its target and its expression with a visitor.
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)
704@export
705class SequentialConditionalVariableAssignment(SequentialStatement, AssignmentMixin):
706 """
707 Represents a conditional sequential variable assignment.
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.
713 .. admonition:: Example
715 .. code-block:: VHDL
717 lbl : v := '1' when sel = '0' else '0';
718 --^^^ <- optional Label
719 -- ^ <- Target
720 -- ^^^^^^^^^^^^^^^^^^ <- ConditionalExpressions[0]
721 -- ^^^ <- ConditionalExpressions[1]
723 .. seealso::
725 * :class:`Conditional expression <pyVHDLModel.Common.ConditionalExpression>`
726 """
728 _conditionalExpressions: list[ConditionalExpression] #: List of all alternatives, in the order they were written.
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.
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)
748 self._conditionalExpressions = conditionalExpressionList = []
749 for conditionalExpression in conditionalExpressions:
750 conditionalExpressionList.append(conditionalExpression)
751 conditionalExpression.Parent = self
753 def Visit(self, visitor: Visitor) -> None:
754 """
755 Walk this conditional variable assignment, its target and its alternatives with a visitor.
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)
766 conditionalExpression.Visit(visitor)
768 visitor.DepartSequentialConditionalVariableAssignment(self)
770 @readonly
771 def ConditionalExpressions(self) -> list[ConditionalExpression]:
772 """
773 Read-only property to access the conditional expressions (:attr:`_conditionalExpressions`).
775 :returns: List of conditional expressions.
776 """
777 return self._conditionalExpressions
780@export
781class SequentialConditionalSignalAssignment(SequentialStatement, SignalAssignmentMixin, ConditionalWaveformsMixin):
782 """
783 Represents a conditional sequential signal assignment.
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.
789 .. admonition:: Example
791 .. code-block:: VHDL
793 lbl : s <= '1' when sel = '0' else '0';
794 --^^^ <- optional Label
795 -- ^ <- Target
796 -- ^^^^^^^^^^^^^^^^^^ <- ConditionalWaveforms[0]
797 -- ^^^ <- ConditionalWaveforms[1]
799 .. seealso::
801 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentConditionalSignalAssignment>`
802 * :class:`Conditional waveform <pyVHDLModel.Common.ConditionalWaveform>`
803 """
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.
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)
824 def Visit(self, visitor: Visitor) -> None:
825 """
826 Walk this conditional signal assignment, its target and its alternatives with a visitor.
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)
837@export
838class SequentialSelectedVariableAssignment(SequentialStatement, AssignmentMixin, ExpressionMixin, SelectedExpressionsMixin):
839 """
840 Represents a selected sequential variable assignment.
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.
846 .. admonition:: Example
848 .. code-block:: VHDL
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]
857 .. seealso::
859 * :class:`Selected expression <pyVHDLModel.Common.SelectedExpression>`
860 """
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.
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)
884 def Visit(self, visitor: Visitor) -> None:
885 """
886 Walk this selected variable assignment, its selector, its target and its alternatives with a visitor.
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)
899@export
900class SequentialSelectedSignalAssignment(SequentialStatement, SignalAssignmentMixin, ExpressionMixin, SelectedWaveformsMixin):
901 """
902 Represents a selected sequential signal assignment.
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.
908 .. admonition:: Example
910 .. code-block:: VHDL
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]
919 .. seealso::
921 * :class:`Concurrent counterpart <pyVHDLModel.Concurrent.ConcurrentSelectedSignalAssignment>`
922 * :class:`Selected waveform <pyVHDLModel.Common.SelectedWaveform>`
923 """
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.
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)
947 def Visit(self, visitor: Visitor) -> None:
948 """
949 Walk this selected signal assignment, its selector, its target and its alternatives with a visitor.
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)
962@export
963class SignalForceAssignment(SequentialStatement, SignalAssignmentMixin, ExpressionMixin):
964 """
965 Represents a signal force assignment.
967 A force assignment overrides a signal's driver until it is released.
969 .. admonition:: Example
971 .. code-block:: VHDL
973 lbl : s <= force '1';
974 --^^^ <- optional Label
975 -- ^ <- Target
976 -- ^^^ <- Expression
977 """
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.
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)
998 def Visit(self, visitor: Visitor) -> None:
999 """
1000 Walk this force assignment, its target and its expression with a visitor.
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)
1011@export
1012class SignalReleaseAssignment(SequentialStatement, SignalAssignmentMixin):
1013 """
1014 Represents a signal release assignment.
1016 A release assignment ends a previously applied force.
1018 .. admonition:: Example
1020 .. code-block:: VHDL
1022 lbl : s <= release;
1023 --^^^ <- optional Label
1024 -- ^ <- Target
1025 """
1027 def __init__(self, target: SignalSymbol, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
1028 """
1029 Initializes a signal release assignment.
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)
1038 def Visit(self, visitor: Visitor) -> None:
1039 """
1040 Walk this release assignment and its target with a visitor.
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)
1050@export
1051class SequentialReportStatement(SequentialStatement, ReportStatementMixin):
1052 """
1053 Represents a sequential report statement.
1055 The report string is available as :data:`Message`, the optional severity as :data:`Severity`.
1057 .. admonition:: Example
1059 .. code-block:: VHDL
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.
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)
1078 def Visit(self, visitor: Visitor) -> None:
1079 """
1080 Walk this report statement, its message and its severity with a visitor.
1082 :param visitor: The visitor receiving the events.
1083 """
1084 visitor.VisitSequentialReportStatement(self)
1085 self._VisitReportAndSeverity(visitor)
1086 visitor.DepartSequentialReportStatement(self)
1089@export
1090class SequentialAssertStatement(SequentialStatement, AssertStatementMixin):
1091 """
1092 Represents a sequential assertion statement.
1094 The checked condition is available as :data:`Condition`, the optional report string as
1095 :data:`Message` and the optional severity as :data:`Severity`.
1097 .. admonition:: Example
1099 .. code-block:: VHDL
1101 lbl : assert sel = '0' report "bad" severity error;
1102 --^^^ <- optional Label
1103 -- ^^^^^^^^^ <- Condition
1104 -- ^^^^^ <- optional Message
1105 -- ^^^^^ <- optional Severity
1107 .. seealso::
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.
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)
1131 def Visit(self, visitor: Visitor) -> None:
1132 """
1133 Walk this assertion, its condition, its message and its severity with a visitor.
1135 :param visitor: The visitor receiving the events.
1136 """
1137 visitor.VisitSequentialAssertStatement(self)
1138 self._VisitAssertion(visitor)
1139 visitor.DepartSequentialAssertStatement(self)
1142@export
1143@abstractclass
1144class CompoundStatement(SequentialStatement):
1145 """
1146 Represents the base-class of all compound statements.
1148 A compound statement contains further sequential statements: if, case and loop statements.
1150 .. seealso::
1152 * :class:`If statement <pyVHDLModel.Sequential.IfStatement>`
1153 * :class:`Case statement <pyVHDLModel.Sequential.CaseStatement>`
1154 * :class:`Loop statement <pyVHDLModel.Sequential.LoopStatement>`
1155 """
1158@export
1159@abstractclass
1160class Branch(ModelEntity, SequentialStatementsMixin):
1161 """
1162 Represents the base-class of all branches of an if statement.
1164 .. seealso::
1166 * :class:`If branch <pyVHDLModel.Sequential.IfBranch>`
1167 * :class:`Elsif branch <pyVHDLModel.Sequential.ElsifBranch>`
1168 * :class:`Else branch <pyVHDLModel.Sequential.ElseBranch>`
1169 """
1171 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, parent: Nullable[ModelEntity] = None) -> None:
1172 """
1173 Initializes a branch.
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)
1181 def _LabelRegion(self) -> Nullable[ModelEntity]:
1182 """
1183 Return the process or subprogram declaring the labels of this branch's statements.
1185 It's the region of the construct holding the if statement.
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
1193 return ifStatement._parent._LabelRegion()
1196@export
1197class IfBranch(Branch, IfBranchMixin):
1198 """
1199 Represents the ``if`` branch of an if statement.
1201 The branch's condition is available as :data:`Condition`, its body as :data:`Statements`.
1203 .. admonition:: Example
1205 The whole if statement is shown; the bracket marks the part this class represents.
1207 .. code-block:: VHDL
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.
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)
1230 def Visit(self, visitor: Visitor) -> None:
1231 """
1232 Walk this if branch, its condition and its statements with a visitor.
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)
1243@export
1244class ElsifBranch(Branch, ElsifBranchMixin):
1245 """
1246 Represents an ``elsif`` branch of an if statement.
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.
1251 .. admonition:: Example
1253 The whole if statement is shown; the bracket marks the part this class represents.
1255 .. code-block:: VHDL
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.
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)
1278 def Visit(self, visitor: Visitor) -> None:
1279 """
1280 Walk this elsif branch, its condition and its statements with a visitor.
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)
1291@export
1292class ElseBranch(Branch, ElseBranchMixin):
1293 """
1294 Represents the ``else`` branch of an if statement.
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.
1299 .. admonition:: Example
1301 The whole if statement is shown; the bracket marks the part this class represents.
1303 .. code-block:: VHDL
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.
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)
1324 def Visit(self, visitor: Visitor) -> None:
1325 """
1326 Walk this else branch and its statements with a visitor.
1328 :param visitor: The visitor receiving the events.
1329 """
1330 visitor.VisitElseBranch(self)
1331 self._VisitStatements(visitor)
1332 visitor.DepartElseBranch(self)
1335@export
1336class IfStatement(CompoundStatement):
1337 """
1338 Represents an if statement.
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`).
1343 .. admonition:: Example
1345 Only an ``if`` branch:
1347 .. code-block:: VHDL
1349 lbl : if sel = '0' then
1350 --^^^ <- optional Label
1351 s <= '0';
1352 end if;
1354 With ``elsif`` and ``else`` branches:
1356 .. code-block:: VHDL
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;
1370 .. seealso::
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.
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.
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)
1397 self._ifBranch = ifBranch
1398 ifBranch.Parent = self
1400 self._elsifBranches = elsifBranchList = []
1401 if elsifBranches is not None:
1402 for branch in elsifBranches:
1403 elsifBranchList.append(branch)
1404 branch.Parent = self
1406 if elseBranch is not None:
1407 self._elseBranch = elseBranch
1408 elseBranch.Parent = self
1409 else:
1410 self._elseBranch = None
1412 def Visit(self, visitor: Visitor) -> None:
1413 """
1414 Walk this if statement and its branches with a visitor.
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)
1423 if self._elseBranch is not None:
1424 self._elseBranch.Visit(visitor)
1426 visitor.DepartIfStatement(self)
1428 @readonly
1429 def IfBranch(self) -> IfBranch:
1430 """
1431 Read-only property to access the if-branch of the if-statement (:attr:`_ifBranch`).
1433 :returns: The if-branch.
1434 """
1435 return self._ifBranch
1437 @readonly
1438 def ElsIfBranches(self) -> list[ElsifBranch]:
1439 """
1440 Read-only property to access the elsif-branch of the if-statement (:attr:`_elsifBranch`).
1442 :returns: The elsif-branch.
1443 """
1444 return self._elsifBranches
1446 @readonly
1447 def ElseBranch(self) -> Nullable[ElseBranch]:
1448 """
1449 Read-only property to access the else-branch of the if-statement (:attr:`_elseBranch`).
1451 :returns: The else-branch.
1452 """
1453 return self._elseBranch
1456@export
1457@abstractclass
1458class SequentialChoice(BaseChoice):
1459 """
1460 Represents the base-class of all choices in a sequential case statement.
1462 .. seealso::
1464 * :class:`Indexed choice <pyVHDLModel.Sequential.IndexedChoice>`
1465 * :class:`Ranged choice <pyVHDLModel.Sequential.RangedChoice>`
1466 """
1469@export
1470class IndexedChoice(SequentialChoice):
1471 """
1472 Represents a case choice given by a single value.
1474 The value is available as :data:`Expression`.
1476 .. admonition:: Example
1478 .. code-block:: VHDL
1480 when 0 => v := '1';
1481 -- ^ <- Expression
1482 """
1483 _expression: ExpressionUnion #: The expression this choice selects on.
1485 def __init__(self, expression: ExpressionUnion, parent: Nullable[ModelEntity] = None) -> None:
1486 """
1487 Initializes a case choice given by a single value.
1489 :param expression: The expression this choice selects on.
1490 :param parent: The parent model entity of this entity.
1491 """
1492 super().__init__(parent)
1494 self._expression = expression
1495 expression.Parent = self
1497 def Visit(self, visitor: Visitor) -> None:
1498 """
1499 Walk this choice and its value with a visitor.
1501 :param visitor: The visitor receiving the events.
1502 """
1503 visitor.VisitIndexedChoice(self)
1504 self._expression.Visit(visitor)
1505 visitor.DepartIndexedChoice(self)
1507 @readonly
1508 def Expression(self) -> ExpressionUnion:
1509 """
1510 Read-only property to access the expression (:attr:`_expression`).
1512 :returns: The expression.
1513 """
1514 return self._expression
1516 def __str__(self) -> str:
1517 """
1518 Formats the indexed case choice.
1520 **Format:** ``0``
1522 :returns: Formatted indexed case choice.
1523 """
1524 return str(self._expression)
1527@export
1528class RangedChoice(SequentialChoice):
1529 """
1530 Represents a case choice given by a range.
1532 The range is available as :data:`Range`.
1534 .. admonition:: Example
1536 .. code-block:: VHDL
1538 when 1 to 2 => v := '0';
1539 -- ^^^^^^ <- Range
1540 """
1541 _range: Range #: The range this choice selects on.
1543 def __init__(self, rng: Range, parent: Nullable[ModelEntity] = None) -> None:
1544 """
1545 Initializes a case choice given by a range.
1547 :param rng: The range this choice selects on.
1548 :param parent: The parent model entity of this entity.
1549 """
1550 super().__init__(parent)
1552 self._range = rng
1553 rng.Parent = self
1555 def Visit(self, visitor: Visitor) -> None:
1556 """
1557 Walk this choice and its range with a visitor.
1559 :param visitor: The visitor receiving the events.
1560 """
1561 visitor.VisitRangedChoice(self)
1562 self._range.Visit(visitor)
1563 visitor.DepartRangedChoice(self)
1565 @readonly
1566 def Range(self) -> Range:
1567 """
1568 Read-only property to access the range (:attr:`_range`).
1570 :returns: The range.
1571 """
1572 return self._range
1574 def __str__(self) -> str:
1575 """
1576 Formats the ranged case choice.
1578 **Format:** ``0 to 3``
1580 :returns: Formatted ranged case choice.
1581 """
1582 return str(self._range)
1585@export
1586class SequentialCase(BaseCase, SequentialStatementsMixin, ChoicesMixin):
1587 """
1588 Represents the base-class of all alternatives of a sequential case statement.
1590 .. seealso::
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.
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)
1612 def _LabelRegion(self) -> Nullable[ModelEntity]:
1613 """
1614 Return the process or subprogram declaring the labels of this case alternative's statements.
1616 It's the region of the construct holding the case statement.
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
1624 return caseStatement._parent._LabelRegion()
1627@export
1628class Case(SequentialCase):
1629 """
1630 Represents one alternative of a case statement, selected by its choices.
1632 .. admonition:: Example
1634 .. code-block:: VHDL
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.
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)
1650 def Visit(self, visitor: Visitor) -> None:
1651 """
1652 Walk this case alternative, its choices and its statements with a visitor.
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)
1661 choice.Visit(visitor)
1663 visitor.VisitArrow(self)
1664 self._VisitStatements(visitor)
1665 visitor.DepartCase(self)
1667 def __str__(self) -> str:
1668 """
1669 Formats the case alternative.
1671 **Format:** ``when 0 | 1 =>``
1673 :returns: Formatted case alternative.
1674 """
1675 return "when {choices} =>".format(choices=" | ".join(str(c) for c in self._choices))
1678@export
1679class OthersCase(SequentialCase):
1680 """
1681 Represents the ``others`` alternative of a case statement.
1683 It covers every choice not named explicitly.
1685 .. admonition:: Example
1687 .. code-block:: VHDL
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.
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)
1703 def __str__(self) -> str:
1704 """
1705 Formats the ``others`` case alternative.
1707 **Format:** ``when others =>``
1709 :returns: Formatted ``others`` case alternative.
1710 """
1711 return "when others =>"
1714@export
1715class CaseStatement(CompoundStatement):
1716 """
1717 Represents a case statement.
1719 The expression being tested is available as :data:`SelectExpression`, the alternatives as
1720 :data:`Cases`.
1722 .. admonition:: Example
1724 .. code-block:: VHDL
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;
1735 .. seealso::
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.
1742 def __init__(self, expression: ExpressionUnion, cases: Iterable[SequentialCase], label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
1743 """
1744 Initializes a case statement.
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)
1753 self._expression = expression
1754 expression.Parent = self
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
1762 def Visit(self, visitor: Visitor) -> None:
1763 """
1764 Walk this case statement, its selector and its alternatives with a visitor.
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)
1774 visitor.DepartCaseStatement(self)
1776 @readonly
1777 def SelectExpression(self) -> ExpressionUnion:
1778 """
1779 Read-only property to access the select expression (:attr:`_expression`).
1781 :returns: The select expression.
1782 """
1783 return self._expression
1785 @readonly
1786 def Cases(self) -> list[SequentialCase]:
1787 """
1788 Read-only property to access the cases (:attr:`_cases`).
1790 :returns: List of cases.
1791 """
1792 return self._cases
1795@export
1796@abstractclass
1797class LoopStatement(CompoundStatement, SequentialStatementsMixin):
1798 """
1799 Represents the base-class of all loop statements.
1801 .. seealso::
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 """
1808 def __init__(self, statements: Nullable[Iterable[SequentialStatement]] = None, label: Nullable[str] = None, parent: Nullable[ModelEntity] = None) -> None:
1809 """
1810 Initializes a loop statement.
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)
1819 def _LabelRegion(self) -> Nullable[ModelEntity]:
1820 """
1821 Return the process or subprogram declaring the labels of this loop's statements.
1823 It's the region of the construct holding the loop.
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()
1830@export
1831class EndlessLoopStatement(LoopStatement):
1832 """
1833 Represents an endless loop statement.
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.
1838 .. admonition:: Example
1840 .. code-block:: VHDL
1842 lbl : loop
1843 --^^^ <- optional Label
1844 exit;
1845 -- ^^^^^ <- Statements
1846 end loop;
1848 .. seealso::
1850 * :class:`For loop statement <pyVHDLModel.Sequential.ForLoopStatement>`
1851 * :class:`While loop statement <pyVHDLModel.Sequential.WhileLoopStatement>`
1852 """
1854 def Visit(self, visitor: Visitor) -> None:
1855 """
1856 Walk this loop and its statements with a visitor.
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)
1866@export
1867class ForLoopStatement(LoopStatement):
1868 """
1869 Represents a for-loop statement.
1871 The loop index is available as :data:`LoopIndex`, the iteration range as :data:`Range` and the
1872 loop body as :data:`Statements`.
1874 .. admonition:: Example
1876 .. code-block:: VHDL
1878 lbl : for k in 0 to 3 loop
1879 --^^^ <- optional Label
1880 -- ^ <- LoopIndex
1881 -- ^^^^^^ <- Range
1882 null;
1883 -- ^^^^^ <- Statements
1884 end loop;
1886 .. seealso::
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.
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.
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)
1907 self._loopIndex = loopIndex
1909 self._range = rng
1910 rng.Parent = self
1912 def Visit(self, visitor: Visitor) -> None:
1913 """
1914 Walk this for-loop, its range and its statements with a visitor.
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)
1924 @readonly
1925 def LoopIndex(self) -> str:
1926 """
1927 Read-only property to access the loop index (:attr:`_loopIndex`).
1929 :returns: The loop index.
1930 """
1931 return self._loopIndex
1933 @readonly
1934 def Range(self) -> Range:
1935 """
1936 Read-only property to access the range (:attr:`_range`).
1938 :returns: The range.
1939 """
1940 return self._range
1943@export
1944class WhileLoopStatement(LoopStatement, ConditionalMixin):
1945 """
1946 Represents a while-loop statement.
1948 The loop condition is available as :data:`Condition`, the loop body as :data:`Statements`.
1950 .. admonition:: Example
1952 .. code-block:: VHDL
1954 lbl : while i < 4 loop
1955 --^^^ <- optional Label
1956 -- ^^^^^ <- Condition
1957 null;
1958 -- ^^^^^ <- Statements
1959 end loop;
1961 .. seealso::
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.
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)
1984 def Visit(self, visitor: Visitor) -> None:
1985 """
1986 Walk this while-loop, its condition and its statements with a visitor.
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)
1997@export
1998@abstractclass
1999class LoopControlStatement(SequentialStatement, ConditionalMixin):
2000 """
2001 Represents the base-class of the loop control statements ``next`` and ``exit``.
2003 An optional loop label (:data:`LoopReference`) selects which enclosing loop is affected.
2005 .. seealso::
2007 * :class:`Next statement <pyVHDLModel.Sequential.NextStatement>`
2008 * :class:`Exit statement <pyVHDLModel.Sequential.ExitStatement>`
2009 """
2011 _loopReference: LoopStatement #: Reference to the loop this statement controls.
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.
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)
2024 self._loopReference = None
2026 # TODO: loopLabel
2027 # TODO: loop reference -> is it a symbol?
2029 @readonly
2030 def LoopReference(self) -> LoopStatement:
2031 """
2032 Read-only property to access the loop reference (:attr:`_loopReference`).
2034 :returns: The loop reference.
2035 """
2036 return self._loopReference
2039@export
2040class NextStatement(LoopControlStatement):
2041 """
2042 Represents a next statement.
2044 A next statement skips to the next iteration of the named loop (:data:`LoopReference`),
2045 optionally only when a condition (:data:`Condition`) holds.
2047 .. admonition:: Example
2049 .. code-block:: VHDL
2051 lbl : next outer when k = 1;
2052 --^^^ <- optional Label
2053 -- ^^^^^ <- optional LoopReference
2054 -- ^^^^^ <- optional Condition
2055 """
2057 def Visit(self, visitor: Visitor) -> None:
2058 """
2059 Walk this next statement and its condition (if any) with a visitor.
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)
2068 visitor.DepartNextStatement(self)
2071@export
2072class ExitStatement(LoopControlStatement):
2073 """
2074 Represents an exit statement.
2076 An exit statement leaves the named loop (:data:`LoopReference`), optionally only when a
2077 condition (:data:`Condition`) holds.
2079 .. admonition:: Example
2081 .. code-block:: VHDL
2083 lbl : exit outer when k = 1;
2084 --^^^ <- optional Label
2085 -- ^^^^^ <- optional LoopReference
2086 -- ^^^^^ <- optional Condition
2087 """
2089 def Visit(self, visitor: Visitor) -> None:
2090 """
2091 Walk this exit statement and its condition (if any) with a visitor.
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)
2100 visitor.DepartExitStatement(self)
2103@export
2104class NullStatement(SequentialStatement):
2105 """
2106 Represents a null statement.
2108 A null statement does nothing. Like every sequential statement, it can carry an optional label
2109 (:data:`Label`).
2111 .. admonition:: Example
2113 .. code-block:: VHDL
2115 lbl : null;
2116 --^^^ <- optional Label
2117 -- ^^^^ <- the statement
2118 """
2120 def Visit(self, visitor: Visitor) -> None:
2121 """
2122 Walk this null statement with a visitor.
2124 :param visitor: The visitor receiving the events.
2125 """
2126 visitor.VisitNullStatement(self)
2127 visitor.DepartNullStatement(self)
2130@export
2131class ReturnStatement(SequentialStatement):
2132 """
2133 Represents a return statement.
2135 The optionally returned value is available as :data:`ReturnValue`; a procedure returns nothing.
2137 .. admonition:: Example
2139 .. code-block:: VHDL
2141 lbl : return x;
2142 --^^^ <- optional Label
2143 -- ^ <- optional ReturnValue
2144 """
2145 _returnValue: Nullable[ExpressionUnion] #: The returned expression, or ``None`` for a procedure.
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.
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)
2162 self._returnValue = returnValue
2163 if returnValue is not None:
2164 returnValue.Parent = self
2166 def Visit(self, visitor: Visitor) -> None:
2167 """
2168 Walk this return statement and its value (if any) with a visitor.
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)
2176 visitor.DepartReturnStatement(self)
2178 @readonly
2179 def ReturnValue(self) -> Nullable[ExpressionUnion]:
2180 """
2181 Read-only property to access the return value (:attr:`_returnValue`).
2183 :returns: The return value, or ``None`` if not set.
2184 """
2185 return self._returnValue
2188@export
2189class WaitStatement(SequentialStatement, ConditionalMixin):
2190 """
2191 Represents a wait statement.
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.
2196 .. admonition:: Example
2198 .. code-block:: VHDL
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.
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.
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)
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
2236 self._timeout = timeout
2237 if timeout is not None:
2238 timeout.Parent = self
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.
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)
2253 name.Visit(visitor)
2255 if self._condition is not None:
2256 visitor.VisitUntil(self)
2257 self._condition.Visit(visitor)
2259 if self._timeout is not None:
2260 visitor.VisitFor(self)
2261 self._timeout.Visit(visitor)
2263 visitor.DepartWaitStatement(self)
2265 @readonly
2266 def SensitivityList(self) -> list[Symbol]:
2267 """
2268 Read-only property to access the sensitivity list (:attr:`_sensitivityList`).
2270 :returns: List of sensitivity list.
2271 """
2272 return self._sensitivityList
2274 @readonly
2275 def Timeout(self) -> ExpressionUnion:
2276 """
2277 Read-only property to access the timeout (:attr:`_timeout`).
2279 :returns: The timeout.
2280 """
2281 return self._timeout