Coverage for pyVHDLModel/Type.py: 76%

216 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-20 22:13 +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. 

34 

35Types. 

36""" 

37from typing import Union, List, Iterator, Iterable, Tuple, Optional as Nullable, Dict, Mapping 

38 

39from pyTooling.Decorators import export, readonly 

40from pyTooling.MetaClasses import ExtendedType 

41from pyTooling.Graph import Vertex 

42 

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 

47 

48 

49@export 

50class BaseType(ModelEntity, NamedEntityMixin, DocumentedEntityMixin): 

51 """``BaseType`` is the base-class of all type entities in this model.""" 

52 

53 _objectVertex: Vertex 

54 

55 def __init__(self, identifier: str, documentation: Nullable[str] = None, parent: ModelEntity = None) -> None: 

56 """ 

57 Initializes underlying ``BaseType``. 

58 

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) 

65 

66 _objectVertex = None 

67 

68 

69@export 

70class Type(BaseType): 

71 pass 

72 

73 

74@export 

75class AnonymousType(Type): 

76 pass 

77 

78 

79@export 

80class FullType(BaseType): 

81 pass 

82 

83 

84@export 

85class Subtype(BaseType): 

86 _type: Symbol 

87 _baseType: BaseType 

88 _range: Range 

89 _resolutionFunction: 'Function' 

90 

91 def __init__(self, identifier: str, symbol: Symbol, parent: ModelEntity = None) -> None: 

92 super().__init__(identifier, parent) 

93 

94 self._type = symbol 

95 self._baseType = None 

96 self._range = None 

97 self._resolutionFunction = None 

98 

99 @readonly 

100 def Type(self) -> Symbol: 

101 return self._type 

102 

103 @readonly 

104 def BaseType(self) -> BaseType: 

105 return self._baseType 

106 

107 @readonly 

108 def Range(self) -> Range: 

109 return self._range 

110 

111 @readonly 

112 def ResolutionFunction(self) -> 'Function': 

113 return self._resolutionFunction 

114 

115 def __str__(self) -> str: 

116 return f"subtype {self._identifier} is {self._baseType}" 

117 

118 

119@export 

120class ScalarType(FullType): 

121 """A ``ScalarType`` is a base-class for all scalar types.""" 

122 

123 

124@export 

125class RangedScalarType(ScalarType): 

126 """A ``RangedScalarType`` is a base-class for all scalar types with a range.""" 

127 

128 _range: Union[Range, Name] 

129 _leftBound: ExpressionUnion 

130 _rightBound: ExpressionUnion 

131 

132 def __init__(self, identifier: str, rng: Union[Range, Name], parent: ModelEntity = None) -> None: 

133 super().__init__(identifier, parent) 

134 self._range = rng 

135 

136 @readonly 

137 def Range(self) -> Union[Range, Name]: 

138 return self._range 

139 

140 

141@export 

142class NumericTypeMixin(metaclass=ExtendedType, mixin=True): 

143 """A ``NumericType`` is a mixin class for all numeric types.""" 

144 

145 def __init__(self) -> None: 

146 pass 

147 

148 

149@export 

150class DiscreteTypeMixin(metaclass=ExtendedType, mixin=True): 

151 """A ``DiscreteType`` is a mixin class for all discrete types.""" 

152 

153 def __init__(self) -> None: 

154 pass 

155 

156 

157@export 

158class EnumeratedType(ScalarType, DiscreteTypeMixin): 

159 _literals: List[EnumerationLiteral] 

160 

161 def __init__(self, identifier: str, literals: Iterable[EnumerationLiteral], parent: ModelEntity = None) -> None: 

162 super().__init__(identifier, parent) 

163 

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 

169 

170 @readonly 

171 def Literals(self) -> List[EnumerationLiteral]: 

172 return self._literals 

173 

174 def __str__(self) -> str: 

175 return f"{self._identifier} is ({', '.join(str(l) for l in self._literals)})" 

176 

177 

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) 

182 

183 def __str__(self) -> str: 

184 return f"{self._identifier} is range {self._range}" 

185 

186 

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) 

191 

192 def __str__(self) -> str: 

193 return f"{self._identifier} is range {self._range}" 

194 

195 

196@export 

197class PhysicalType(RangedScalarType, NumericTypeMixin): 

198 _primaryUnit: str 

199 _secondaryUnits: List[Tuple[str, PhysicalIntegerLiteral]] 

200 

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) 

210 

211 self._primaryUnit = primaryUnit 

212 

213 self._secondaryUnits = [] # TODO: convert to dict 

214 for unit in units: 

215 self._secondaryUnits.append(unit) 

216 unit[1]._parent = self 

217 

218 @readonly 

219 def PrimaryUnit(self) -> str: 

220 return self._primaryUnit 

221 

222 @property 

223 def SecondaryUnits(self) -> List[Tuple[str, PhysicalIntegerLiteral]]: 

224 return self._secondaryUnits 

225 

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)};" 

228 

229 

230@export 

231class CompositeType(FullType): 

232 """A ``CompositeType`` is a base-class for all composite types.""" 

233 

234 

235@export 

236class ArrayType(CompositeType): 

237 _dimensions: List[Range] 

238 _elementType: Symbol 

239 

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) 

248 

249 self._dimensions = [] 

250 for index in indices: 

251 self._dimensions.append(index) 

252 # index._parent = self # FIXME: indices are provided as empty list 

253 

254 self._elementType = elementSubtype 

255 # elementSubtype._parent = self # FIXME: subtype is provided as None 

256 

257 @property 

258 def Dimensions(self) -> List[Range]: 

259 return self._dimensions 

260 

261 @property 

262 def ElementType(self) -> Symbol: 

263 return self._elementType 

264 

265 def __str__(self) -> str: 

266 return f"{self._identifier} is array({'; '.join(str(r) for r in self._dimensions)}) of {self._elementType}" 

267 

268 

269@export 

270class RecordTypeElement(ModelEntity, MultipleNamedEntityMixin): 

271 _subtype: Symbol 

272 

273 def __init__(self, identifiers: Iterable[str], subtype: Symbol, parent: ModelEntity = None) -> None: 

274 super().__init__(parent) 

275 MultipleNamedEntityMixin.__init__(self, identifiers) 

276 

277 self._subtype = subtype 

278 subtype._parent = self 

279 

280 @property 

281 def Subtype(self) -> Symbol: 

282 return self._subtype 

283 

284 def __str__(self) -> str: 

285 return f"{', '.join(self._identifiers)} : {self._subtype}" 

286 

287 

288@export 

289class RecordType(CompositeType): 

290 _elements: List[RecordTypeElement] 

291 

292 def __init__(self, identifier: str, elements: Nullable[Iterable[RecordTypeElement]] = None, parent: ModelEntity = None) -> None: 

293 super().__init__(identifier, parent) 

294 

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 

300 

301 @property 

302 def Elements(self) -> List[RecordTypeElement]: 

303 return self._elements 

304 

305 def __str__(self) -> str: 

306 return f"{self._identifier} is record {'; '.join(str(re) for re in self._elements)};" 

307 

308 

309@export 

310class ProtectedType(FullType): 

311 _methods: List[Union['Procedure', 'Function']] 

312 

313 def __init__(self, identifier: str, methods: Union[List, Iterator] = None, parent: ModelEntity = None) -> None: 

314 super().__init__(identifier, parent) 

315 

316 self._methods = [] 

317 if methods is not None: 

318 for method in methods: 

319 self._methods.append(method) 

320 method._parent = self 

321 

322 @property 

323 def Methods(self) -> List[Union['Procedure', 'Function']]: 

324 return self._methods 

325 

326 

327@export 

328class ProtectedTypeBody(FullType): 

329 _methods: List[Union['Procedure', 'Function']] 

330 

331 def __init__(self, identifier: str, declaredItems: Union[List, Iterator] = None, parent: ModelEntity = None) -> None: 

332 super().__init__(identifier, parent) 

333 

334 self._methods = [] 

335 if declaredItems is not None: 

336 for method in declaredItems: 

337 self._methods.append(method) 

338 method._parent = self 

339 

340 # FIXME: needs to be declared items or so 

341 @property 

342 def Methods(self) -> List[Union['Procedure', 'Function']]: 

343 return self._methods 

344 

345 

346@export 

347class AccessType(FullType): 

348 _designatedSubtype: Symbol 

349 

350 def __init__(self, identifier: str, designatedSubtype: Symbol, parent: ModelEntity = None) -> None: 

351 super().__init__(identifier, parent) 

352 

353 self._designatedSubtype = designatedSubtype 

354 designatedSubtype._parent = self 

355 

356 @property 

357 def DesignatedSubtype(self): 

358 return self._designatedSubtype 

359 

360 def __str__(self) -> str: 

361 return f"{self._identifier} is access {self._designatedSubtype}" 

362 

363 

364@export 

365class FileType(FullType): 

366 _designatedSubtype: Symbol 

367 

368 def __init__(self, identifier: str, designatedSubtype: Symbol, parent: ModelEntity = None) -> None: 

369 super().__init__(identifier, parent) 

370 

371 self._designatedSubtype = designatedSubtype 

372 designatedSubtype._parent = self 

373 

374 @property 

375 def DesignatedSubtype(self): 

376 return self._designatedSubtype 

377 

378 def __str__(self) -> str: 

379 return f"{self._identifier} is access {self._designatedSubtype}"