Coverage for pyVHDLModel/Subprogram.py: 97%
92 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-11 23:50 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-11 23:50 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2026 Patrick Lehmann - Boetzingen, Germany #
15# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany #
16# #
17# Licensed under the Apache License, Version 2.0 (the "License"); #
18# you may not use this file except in compliance with the License. #
19# You may obtain a copy of the License at #
20# #
21# http://www.apache.org/licenses/LICENSE-2.0 #
22# #
23# Unless required by applicable law or agreed to in writing, software #
24# distributed under the License is distributed on an "AS IS" BASIS, #
25# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
26# See the License for the specific language governing permissions and #
27# limitations under the License. #
28# #
29# SPDX-License-Identifier: Apache-2.0 #
30# ==================================================================================================================== #
31#
32"""
33This module contains parts of an abstract document language model for VHDL.
35Subprograms are procedures, functions and methods.
36"""
37from typing import ClassVar, List, Iterable, Optional as Nullable
39from pyTooling.Decorators import export, readonly
40from pyTooling.MetaClasses import ExtendedType
42from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, DocumentedEntityMixin, identifiersOf
43from pyVHDLModel.Symbol import SubtypeSymbol
44from pyVHDLModel.Type import ProtectedType
45from pyVHDLModel.Regions import ConcurrentDeclarationRegionMixin, SequentialDeclarationRegionMixin
46from pyVHDLModel.Regions import ProtectedTypeDeclarationRegionMixin
47from pyVHDLModel.Sequential import SequentialStatement
50@export
51class Subprogram(ModelEntity, NamedEntityMixin, DocumentedEntityMixin, SequentialDeclarationRegionMixin):
52 """
53 Represents the base-class of all subprograms: procedures and functions.
55 A subprogram is a named entity (:data:`Identifier`) with an optional generic clause
56 (:data:`GenericItems`), a parameter list (:data:`ParameterItems`), its own declarative part
57 (:data:`DeclaredItems`) and a sequence of statements (:data:`Statements`).
59 .. seealso::
61 * :class:`Procedure <pyVHDLModel.Subprogram.Procedure>`
62 * :class:`Function <pyVHDLModel.Subprogram.Function>`
63 """
64 _subprogramKeyword: ClassVar[str] = "subprogram" #: The VHDL keyword introducing this subprogram kind.
66 _genericItems: List['GenericInterfaceItemMixin'] #: List of all generics, in declaration order.
67 _parameterItems: List['ParameterInterfaceItemMixin'] #: List of all parameters, in declaration order.
68 _statements: List[SequentialStatement] #: List of all sequential statements in the subprogram's body.
69 _isPure: bool #: ``True`` if the subprogram was declared pure.
71 def __init__(
72 self,
73 identifier: str,
74 isPure: bool,
75 genericItems: Nullable[Iterable['GenericInterfaceItemMixin']] = None,
76 parameterItems: Nullable[Iterable['ParameterInterfaceItemMixin']] = None,
77 declaredItems: Nullable[Iterable] = None,
78 statements: Nullable[Iterable[SequentialStatement]] = None,
79 documentation: Nullable[str] = None,
80 parent: Nullable[ModelEntity] = None
81 ) -> None:
82 """
83 Initializes a subprogram.
85 :param identifier: The identifier of a model entity.
86 :param isPure: ``True`` if the subprogram was declared pure.
87 :param genericItems: List of all generics, in declaration order.
88 :param parameterItems: List of all parameters, in declaration order.
89 :param declaredItems: List of all declared items in this sequential declaration region.
90 :param statements: List of all sequential statements in the subprogram's body.
91 :param documentation: The documentation comment associated with this declaration.
92 :param parent: The parent model entity of this entity.
93 """
94 super().__init__(parent)
95 NamedEntityMixin.__init__(self, identifier)
96 DocumentedEntityMixin.__init__(self, documentation)
97 SequentialDeclarationRegionMixin.__init__(self, self._normalizedIdentifier, declaredItems)
99 self._genericItems = [] # TODO: convert to dict
100 if genericItems is not None:
101 for item in genericItems:
102 self._genericItems.append(item)
103 item.Parent = self
105 self._parameterItems = [] # TODO: convert to dict
106 if parameterItems is not None:
107 for item in parameterItems:
108 self._parameterItems.append(item)
109 item.Parent = self
111 self._statements = [] # TODO: use mixin class
112 if statements is not None:
113 for item in statements:
114 self._statements.append(item)
115 item.Parent = self
117 self._isPure = isPure
119 @ModelEntity.Parent.setter
120 def Parent(self, parent: ModelEntity) -> None:
121 ModelEntity.Parent.fset(self, parent)
123 # Connect the subprogram's namespace to the enclosing declaration region's namespace, so a
124 # declaration inside the subprogram hides a same-named one from the scope around it. Protected
125 # types and their bodies are declaration regions too, so a method chains like any other
126 # subprogram; the check remains because a parent need not be a region at all.
127 regions = (ConcurrentDeclarationRegionMixin, SequentialDeclarationRegionMixin, ProtectedTypeDeclarationRegionMixin)
128 if isinstance(parent, regions): 128 ↛ exitline 128 didn't return from function 'Parent' because the condition on line 128 was always true
129 self._namespace.ParentNamespace = parent._namespace
131 @readonly
132 def GenericItems(self) -> List['GenericInterfaceItemMixin']:
133 """
134 Read-only property to access the generic items (:attr:`_genericItems`).
136 :returns: List of generic items.
137 """
138 return self._genericItems
140 @readonly
141 def ParameterItems(self) -> List['ParameterInterfaceItemMixin']:
142 """
143 Read-only property to access the parameter items (:attr:`_parameterItems`).
145 :returns: List of parameter items.
146 """
147 return self._parameterItems
149 @readonly
150 def Statements(self) -> List[SequentialStatement]:
151 """
152 Read-only property to access the statements (:attr:`_statements`).
154 :returns: List of statements.
155 """
156 return self._statements
158 @readonly
159 def IsPure(self) -> bool:
160 """
161 Check if the subprogram is pure (:attr:`_isPure`).
163 :returns: ``True``, if the subprogram is pure.
164 """
165 return self._isPure
168 def IndexDeclaredItems(self) -> None:
169 """A subprogram's generics and parameters share the declarative region of its declarative part."""
170 self._IndexGenericItems()
171 self._IndexParameterItems()
173 super().IndexDeclaredItems()
175 def __str__(self) -> str:
176 """
177 Formats the subprogram declaration.
179 **Format:** ``procedure myProcedure(a, b)``
181 :returns: Formatted subprogram declaration.
182 """
183 parameters = ", ".join(name for item in self._parameterItems for name in identifiersOf(item))
184 return f"{self._subprogramKeyword} {self._identifier}({parameters})"
187@export
188class Procedure(Subprogram):
189 """
190 Represents a procedure.
192 Unlike a function, a procedure returns no value. Besides its parameters, it has its own
193 declarative part (:data:`DeclaredItems`) and statements (:data:`Statements`).
195 .. admonition:: Example
197 .. code-block:: VHDL
199 procedure proc(signal s : in bit; variable v : out bit) is
200 -- ^^^^ <- Identifier
201 -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- ParameterItems
202 variable tmp : bit;
203 --^^^^^^^^^^^^^^^^^^^ <- DeclaredItems
204 begin
205 tmp := s;
206 --^^^^^^^^^ <- Statements
207 v := tmp;
208 end procedure;
210 .. seealso::
212 * :class:`Procedure instantiation <pyVHDLModel.Instantiation.ProcedureInstantiation>`
213 * :class:`Generic procedure interface item <pyVHDLModel.Interface.GenericProcedureInterfaceItem>`
214 * :class:`Procedure method <pyVHDLModel.Subprogram.ProcedureMethod>`
215 * :class:`Function <pyVHDLModel.Subprogram.Function>`
216 """
218 _subprogramKeyword: ClassVar[str] = "procedure"
219 def __init__(
220 self,
221 identifier: str,
222 genericItems: Nullable[Iterable['GenericInterfaceItemMixin']] = None,
223 parameterItems: Nullable[Iterable['ParameterInterfaceItemMixin']] = None,
224 declaredItems: Nullable[Iterable] = None,
225 statements: Nullable[Iterable[SequentialStatement]] = None,
226 documentation: Nullable[str] = None,
227 parent: Nullable[ModelEntity] = None
228 ) -> None:
229 """
230 Initializes a procedure.
232 :param identifier: The identifier of a model entity.
233 :param genericItems: List of all generics, in declaration order.
234 :param parameterItems: List of all parameters, in declaration order.
235 :param declaredItems: List of all declared items in this sequential declaration region.
236 :param statements: List of all sequential statements in the subprogram's body.
237 :param documentation: The documentation comment associated with this declaration.
238 :param parent: The parent model entity of this entity.
239 """
240 super().__init__(identifier, False, genericItems, parameterItems, declaredItems, statements, documentation, parent)
243@export
244class Function(Subprogram):
245 """
246 Represents a function.
248 A function returns a value of its return type (:data:`ReturnType`) and is either pure or impure
249 (:data:`IsPure`). Besides its parameters, it has its own declarative part (:data:`DeclaredItems`)
250 and statements (:data:`Statements`).
252 .. admonition:: Example
254 .. code-block:: VHDL
256 function fun(constant c : in positive) return integer is
257 -- ^^^ <- Identifier
258 -- ^^^^^^^^^^^^^^^^^^^^^^^^ <- ParameterItems
259 -- ^^^^^^^ <- ReturnType
260 variable tmp : integer;
261 --^^^^^^^^^^^^^^^^^^^^^^^ <- DeclaredItems
262 begin
263 tmp := c;
264 --^^^^^^^^^ <- Statements
265 return tmp;
266 end function;
268 .. seealso::
270 * :class:`Function instantiation <pyVHDLModel.Instantiation.FunctionInstantiation>`
271 * :class:`Generic function interface item <pyVHDLModel.Interface.GenericFunctionInterfaceItem>`
272 * :class:`Function method <pyVHDLModel.Subprogram.FunctionMethod>`
273 * :class:`Procedure <pyVHDLModel.Subprogram.Procedure>`
274 """
276 _subprogramKeyword: ClassVar[str] = "function"
277 _returnType: SubtypeSymbol #: Reference to the subtype of the function's return value.
279 def __init__(
280 self,
281 identifier: str,
282 returnType: SubtypeSymbol,
283 isPure: bool = True,
284 genericItems: Nullable[Iterable['GenericInterfaceItemMixin']] = None,
285 parameterItems: Nullable[Iterable['ParameterInterfaceItemMixin']] = None,
286 declaredItems: Nullable[Iterable] = None,
287 statements: Nullable[Iterable[SequentialStatement]] = None,
288 documentation: Nullable[str] = None,
289 parent: Nullable[ModelEntity] = None
290 ) -> None:
291 """
292 Initializes a function.
294 :param identifier: The identifier of a model entity.
295 :param returnType: Reference to the subtype of the function's return value.
296 :param isPure: ``True`` if the subprogram was declared pure.
297 :param genericItems: List of all generics, in declaration order.
298 :param parameterItems: List of all parameters, in declaration order.
299 :param declaredItems: List of all declared items in this sequential declaration region.
300 :param statements: List of all sequential statements in the subprogram's body.
301 :param documentation: The documentation comment associated with this declaration.
302 :param parent: The parent model entity of this entity.
303 """
304 super().__init__(identifier, isPure, genericItems, parameterItems, declaredItems, statements, documentation, parent)
306 self._returnType = returnType
307 returnType.Parent = self
309 @readonly
310 def ReturnType(self) -> SubtypeSymbol:
311 """
312 Read-only property to access the return type (:attr:`_returnType`).
314 :returns: The return type.
315 """
316 return self._returnType
319@export
320class MethodMixin(metaclass=ExtendedType, mixin=True):
321 """
322 A ``Method`` is a mixin class for all subprograms in a protected type.
324 .. seealso::
326 * :class:`Procedure method <pyVHDLModel.Subprogram.ProcedureMethod>`
327 * :class:`Function method <pyVHDLModel.Subprogram.FunctionMethod>`
328 """
330 _protectedType: ProtectedType #: Reference to the protected type this method belongs to.
332 def __init__(self, protectedType: Nullable[ProtectedType] = None) -> None:
333 """
334 Initializes a method.
336 :param protectedType: Reference to the protected type this method belongs to.
337 """
338 self._protectedType = protectedType
339 if protectedType is not None:
340 protectedType.Parent = self
342 @readonly
343 def ProtectedType(self) -> ProtectedType:
344 """
345 Read-only property to access the protected type (:attr:`_protectedType`).
347 :returns: The protected type.
348 """
349 return self._protectedType
352@export
353class ProcedureMethod(Procedure, MethodMixin):
354 """
355 Represents a procedure declared as a method of a protected type.
357 The protected type is available as :data:`ProtectedType`.
359 .. seealso::
361 * :class:`Protected type <pyVHDLModel.Type.ProtectedType>`
362 """
363 def __init__(
364 self,
365 identifier: str,
366 genericItems: Nullable[Iterable['GenericInterfaceItemMixin']] = None,
367 parameterItems: Nullable[Iterable['ParameterInterfaceItemMixin']] = None,
368 declaredItems: Nullable[Iterable] = None,
369 statements: Nullable[Iterable[SequentialStatement]] = None,
370 documentation: Nullable[str] = None,
371 protectedType: Nullable[ProtectedType] = None,
372 parent: Nullable[ModelEntity] = None
373 ) -> None:
374 """
375 Initializes a procedure declared as a method of a protected type.
377 :param identifier: The identifier of a model entity.
378 :param genericItems: List of all generics, in declaration order.
379 :param parameterItems: List of all parameters, in declaration order.
380 :param declaredItems: List of all declared items in this sequential declaration region.
381 :param statements: List of all sequential statements in the subprogram's body.
382 :param documentation: The documentation comment associated with this declaration.
383 :param protectedType: Reference to the protected type this method belongs to.
384 :param parent: The parent model entity of this entity.
385 """
386 super().__init__(identifier, genericItems, parameterItems, declaredItems, statements, documentation, parent)
387 MethodMixin.__init__(self, protectedType)
390@export
391class FunctionMethod(Function, MethodMixin):
392 """
393 Represents a function declared as a method of a protected type.
395 The protected type is available as :data:`ProtectedType`.
397 .. seealso::
399 * :class:`Protected type <pyVHDLModel.Type.ProtectedType>`
400 """
401 def __init__(
402 self,
403 identifier: str,
404 returnType: SubtypeSymbol,
405 isPure: bool = True,
406 genericItems: Nullable[Iterable['GenericInterfaceItemMixin']] = None,
407 parameterItems: Nullable[Iterable['ParameterInterfaceItemMixin']] = None,
408 declaredItems: Nullable[Iterable] = None,
409 statements: Nullable[Iterable[SequentialStatement]] = None,
410 documentation: Nullable[str] = None,
411 protectedType: Nullable[ProtectedType] = None,
412 parent: Nullable[ModelEntity] = None
413 ) -> None:
414 """
415 Initializes a function declared as a method of a protected type.
417 :param identifier: The identifier of a model entity.
418 :param returnType: Reference to the subtype of the function's return value.
419 :param isPure: ``True`` if the subprogram was declared pure.
420 :param genericItems: List of all generics, in declaration order.
421 :param parameterItems: List of all parameters, in declaration order.
422 :param declaredItems: List of all declared items in this sequential declaration region.
423 :param statements: List of all sequential statements in the subprogram's body.
424 :param documentation: The documentation comment associated with this declaration.
425 :param protectedType: Reference to the protected type this method belongs to.
426 :param parent: The parent model entity of this entity.
427 """
428 super().__init__(identifier, returnType, isPure, genericItems, parameterItems, declaredItems, statements, documentation, parent)
429 MethodMixin.__init__(self, protectedType)