Coverage for pyVHDLModel/Type.py: 76%
216 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-10 23:46 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-10 23:46 +0000
1# ==================================================================================================================== #
2# __ ___ _ ____ _ __ __ _ _ #
3# _ __ _ \ \ / / | | | _ \| | | \/ | ___ __| | ___| | #
4# | '_ \| | | \ \ / /| |_| | | | | | | |\/| |/ _ \ / _` |/ _ \ | #
5# | |_) | |_| |\ V / | _ | |_| | |___| | | | (_) | (_| | __/ | #
6# | .__/ \__, | \_/ |_| |_|____/|_____|_| |_|\___/ \__,_|\___|_| #
7# |_| |___/ #
8# ==================================================================================================================== #
9# Authors: #
10# Patrick Lehmann #
11# #
12# License: #
13# ==================================================================================================================== #
14# Copyright 2017-2024 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.
35Types.
36"""
37from typing import Union, List, Iterator, Iterable, Tuple, Optional as Nullable, Dict, Mapping
39from pyTooling.Decorators import export, readonly
40from pyTooling.MetaClasses import ExtendedType
41from pyTooling.Graph import Vertex
43from pyVHDLModel.Base import ModelEntity, NamedEntityMixin, MultipleNamedEntityMixin, DocumentedEntityMixin, ExpressionUnion, Range
44from pyVHDLModel.Symbol import Symbol
45from pyVHDLModel.Name import Name
46from pyVHDLModel.Expression import EnumerationLiteral, PhysicalIntegerLiteral
49@export
50class BaseType(ModelEntity, NamedEntityMixin, DocumentedEntityMixin):
51 """``BaseType`` is the base-class of all type entities in this model."""
53 _objectVertex: Vertex
55 def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None:
56 """
57 Initializes underlying ``BaseType``.
59 :param identifier: Name of the type.
60 :param parent: Reference to the logical parent in the model hierarchy.
61 """
62 super().__init__(parent)
63 NamedEntityMixin.__init__(self, identifier)
64 DocumentedEntityMixin.__init__(self, documentation)
66 _objectVertex = None
69@export
70class Type(BaseType):
71 pass
74@export
75class AnonymousType(Type):
76 pass
79@export
80class FullType(BaseType):
81 pass
84@export
85class Subtype(BaseType):
86 _type: Symbol
87 _baseType: BaseType
88 _range: Range
89 _resolutionFunction: 'Function'
91 def __init__(self, identifier: str, symbol: Symbol, parent: ModelEntity = None) -> None:
92 super().__init__(identifier, parent)
94 self._type = symbol
95 self._baseType = None
96 self._range = None
97 self._resolutionFunction = None
99 @readonly
100 def Type(self) -> Symbol:
101 return self._type
103 @readonly
104 def BaseType(self) -> BaseType:
105 return self._baseType
107 @readonly
108 def Range(self) -> Range:
109 return self._range
111 @readonly
112 def ResolutionFunction(self) -> 'Function':
113 return self._resolutionFunction
115 def __str__(self) -> str:
116 return f"subtype {self._identifier} is {self._baseType}"
119@export
120class ScalarType(FullType):
121 """A ``ScalarType`` is a base-class for all scalar types."""
124@export
125class RangedScalarType(ScalarType):
126 """A ``RangedScalarType`` is a base-class for all scalar types with a range."""
128 _range: Union[Range, Name]
129 _leftBound: ExpressionUnion
130 _rightBound: ExpressionUnion
132 def __init__(self, identifier: str, rng: Union[Range, Name], parent: ModelEntity = None) -> None:
133 super().__init__(identifier, parent)
134 self._range = rng
136 @readonly
137 def Range(self) -> Union[Range, Name]:
138 return self._range
141@export
142class NumericTypeMixin(metaclass=ExtendedType, mixin=True):
143 """A ``NumericType`` is a mixin class for all numeric types."""
145 def __init__(self) -> None:
146 pass
149@export
150class DiscreteTypeMixin(metaclass=ExtendedType, mixin=True):
151 """A ``DiscreteType`` is a mixin class for all discrete types."""
153 def __init__(self) -> None:
154 pass
157@export
158class EnumeratedType(ScalarType, DiscreteTypeMixin):
159 _literals: List[EnumerationLiteral]
161 def __init__(self, identifier: str, literals: Iterable[EnumerationLiteral], parent: ModelEntity = None) -> None:
162 super().__init__(identifier, parent)
164 self._literals = []
165 if literals is not None: 165 ↛ exitline 165 didn't return from function '__init__' because the condition on line 165 was always true
166 for literal in literals:
167 self._literals.append(literal)
168 literal._parent = self
170 @readonly
171 def Literals(self) -> List[EnumerationLiteral]:
172 return self._literals
174 def __str__(self) -> str:
175 return f"{self._identifier} is ({', '.join(str(l) for l in self._literals)})"
178@export
179class IntegerType(RangedScalarType, NumericTypeMixin, DiscreteTypeMixin):
180 def __init__(self, identifier: str, rng: Union[Range, Name], parent: ModelEntity = None) -> None:
181 super().__init__(identifier, rng, parent)
183 def __str__(self) -> str:
184 return f"{self._identifier} is range {self._range}"
187@export
188class RealType(RangedScalarType, NumericTypeMixin):
189 def __init__(self, identifier: str, rng: Union[Range, Name], parent: ModelEntity = None) -> None:
190 super().__init__(identifier, rng, parent)
192 def __str__(self) -> str:
193 return f"{self._identifier} is range {self._range}"
196@export
197class PhysicalType(RangedScalarType, NumericTypeMixin):
198 _primaryUnit: str
199 _secondaryUnits: List[Tuple[str, PhysicalIntegerLiteral]]
201 def __init__(
202 self,
203 identifier: str,
204 rng: Union[Range, Name],
205 primaryUnit: str,
206 units: Iterable[Tuple[str, PhysicalIntegerLiteral]],
207 parent: ModelEntity = None
208 ) -> None:
209 super().__init__(identifier, rng, parent)
211 self._primaryUnit = primaryUnit
213 self._secondaryUnits = [] # TODO: convert to dict
214 for unit in units:
215 self._secondaryUnits.append(unit)
216 unit[1]._parent = self
218 @readonly
219 def PrimaryUnit(self) -> str:
220 return self._primaryUnit
222 @property
223 def SecondaryUnits(self) -> List[Tuple[str, PhysicalIntegerLiteral]]:
224 return self._secondaryUnits
226 def __str__(self) -> str:
227 return f"{self._identifier} is range {self._range} units {self._primaryUnit}; {'; '.join(su + ' = ' + str(pu) for su, pu in self._secondaryUnits)};"
230@export
231class CompositeType(FullType):
232 """A ``CompositeType`` is a base-class for all composite types."""
235@export
236class ArrayType(CompositeType):
237 _dimensions: List[Range]
238 _elementType: Symbol
240 def __init__(
241 self,
242 identifier: str,
243 indices: Iterable,
244 elementSubtype: Symbol,
245 parent: ModelEntity = None
246 ) -> None:
247 super().__init__(identifier, parent)
249 self._dimensions = []
250 for index in indices:
251 self._dimensions.append(index)
252 # index._parent = self # FIXME: indices are provided as empty list
254 self._elementType = elementSubtype
255 # elementSubtype._parent = self # FIXME: subtype is provided as None
257 @property
258 def Dimensions(self) -> List[Range]:
259 return self._dimensions
261 @property
262 def ElementType(self) -> Symbol:
263 return self._elementType
265 def __str__(self) -> str:
266 return f"{self._identifier} is array({'; '.join(str(r) for r in self._dimensions)}) of {self._elementType}"
269@export
270class RecordTypeElement(ModelEntity, MultipleNamedEntityMixin):
271 _subtype: Symbol
273 def __init__(self, identifiers: Iterable[str], subtype: Symbol, parent: ModelEntity = None) -> None:
274 super().__init__(parent)
275 MultipleNamedEntityMixin.__init__(self, identifiers)
277 self._subtype = subtype
278 subtype._parent = self
280 @property
281 def Subtype(self) -> Symbol:
282 return self._subtype
284 def __str__(self) -> str:
285 return f"{', '.join(self._identifiers)} : {self._subtype}"
288@export
289class RecordType(CompositeType):
290 _elements: List[RecordTypeElement]
292 def __init__(self, identifier: str, elements: Nullable[Iterable[RecordTypeElement]] = None, parent: ModelEntity = None) -> None:
293 super().__init__(identifier, parent)
295 self._elements = [] # TODO: convert to dict
296 if elements is not None: 296 ↛ exitline 296 didn't return from function '__init__' because the condition on line 296 was always true
297 for element in elements: 297 ↛ 298line 297 didn't jump to line 298 because the loop on line 297 never started
298 self._elements.append(element)
299 element._parent = self
301 @property
302 def Elements(self) -> List[RecordTypeElement]:
303 return self._elements
305 def __str__(self) -> str:
306 return f"{self._identifier} is record {'; '.join(str(re) for re in self._elements)};"
309@export
310class ProtectedType(FullType):
311 _methods: List[Union['Procedure', 'Function']]
313 def __init__(self, identifier: str, methods: Union[List, Iterator] = None, parent: ModelEntity = None) -> None:
314 super().__init__(identifier, parent)
316 self._methods = []
317 if methods is not None:
318 for method in methods:
319 self._methods.append(method)
320 method._parent = self
322 @property
323 def Methods(self) -> List[Union['Procedure', 'Function']]:
324 return self._methods
327@export
328class ProtectedTypeBody(FullType):
329 _methods: List[Union['Procedure', 'Function']]
331 def __init__(self, identifier: str, declaredItems: Union[List, Iterator] = None, parent: ModelEntity = None) -> None:
332 super().__init__(identifier, parent)
334 self._methods = []
335 if declaredItems is not None:
336 for method in declaredItems:
337 self._methods.append(method)
338 method._parent = self
340 # FIXME: needs to be declared items or so
341 @property
342 def Methods(self) -> List[Union['Procedure', 'Function']]:
343 return self._methods
346@export
347class AccessType(FullType):
348 _designatedSubtype: Symbol
350 def __init__(self, identifier: str, designatedSubtype: Symbol, parent: ModelEntity = None) -> None:
351 super().__init__(identifier, parent)
353 self._designatedSubtype = designatedSubtype
354 designatedSubtype._parent = self
356 @property
357 def DesignatedSubtype(self):
358 return self._designatedSubtype
360 def __str__(self) -> str:
361 return f"{self._identifier} is access {self._designatedSubtype}"
364@export
365class FileType(FullType):
366 _designatedSubtype: Symbol
368 def __init__(self, identifier: str, designatedSubtype: Symbol, parent: ModelEntity = None) -> None:
369 super().__init__(identifier, parent)
371 self._designatedSubtype = designatedSubtype
372 designatedSubtype._parent = self
374 @property
375 def DesignatedSubtype(self):
376 return self._designatedSubtype
378 def __str__(self) -> str:
379 return f"{self._identifier} is access {self._designatedSubtype}"