Coverage for pyVHDLModel/Object.py: 98%

122 statements  

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

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

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

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

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

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

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

7# |_| |___/ # 

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

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

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

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

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

16# # 

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

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

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

20# # 

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

22# # 

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

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

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

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

27# limitations under the License. # 

28# # 

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

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

31# 

32""" 

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

34 

35Objects are constants, variables, signals and files. 

36""" 

37from __future__ import annotations 

38 

39from typing import TYPE_CHECKING, ClassVar, Iterable, Optional as Nullable, Self 

40 

41from pyTooling.Decorators import export, readonly 

42from pyTooling.MetaClasses import ExtendedType, abstractclass 

43from pyTooling.Graph import Vertex 

44 

45from pyVHDLModel.Base import ModelEntity, MultipleNamedEntityMixin, DocumentedEntityMixin, ExpressionUnion, \ 

46 ReservedWord 

47from pyVHDLModel.Symbol import Symbol 

48 

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

50 from pyVHDLModel.Visitor import Visitor 

51 

52 

53@export 

54@abstractclass 

55class Obj(ModelEntity, MultipleNamedEntityMixin, DocumentedEntityMixin): 

56 """ 

57 Base-class for all objects (constants, signals, variables and files) in VHDL. 

58 

59 An object (syntax element) can define multiple objects (semantic elements) in a single declaration, thus 

60 :class:`~pyVHDLModel.Base.MultipleNamedEntityMixin` is inherited. All objects can be documented, thus 

61 :class:`~pyVHDLModel.Base.DocumentedEntityMixin` is inherited too. 

62 

63 Each object references a subtype via :data:`_subtype`. 

64 

65 Objects are elements in the type and object graph, thus a reference to a vertex in that graph is stored in 

66 :data:`__objectVertex`. 

67 

68 .. seealso:: 

69 

70 * :class:`Base constant <pyVHDLModel.Object.BaseConstant>` 

71 * :class:`Variable <pyVHDLModel.Object.Variable>` 

72 * :class:`Shared variable <pyVHDLModel.Object.SharedVariable>` 

73 * :class:`Signal <pyVHDLModel.Object.Signal>` 

74 * :class:`File <pyVHDLModel.Object.File>` 

75 """ 

76 

77 _OBJECT_KEYWORD: ClassVar[tuple[ReservedWord, ...]] #: The reserved words introducing this object class. 

78 

79 _subtype: Symbol #: Reference to the object's subtype. 

80 _objectVertex: Nullable[Vertex] #: The vertex representing this object in the design's object graph. 

81 

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

83 """ 

84 Initializes an object. 

85 

86 :param identifiers: A list of identifiers. 

87 :param subtype: Reference to the object's subtype. 

88 :param documentation: The documentation comment associated with this declaration. 

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

90 """ 

91 super().__init__(parent) 

92 MultipleNamedEntityMixin.__init__(self, identifiers) 

93 DocumentedEntityMixin.__init__(self, documentation) 

94 

95 self._subtype = subtype 

96 subtype.Parent = self 

97 

98 self._objectVertex = None 

99 

100 @readonly 

101 def Subtype(self) -> Symbol: 

102 """ 

103 Read-only property to access the subtype (:attr:`_subtype`). 

104 

105 :returns: The subtype. 

106 """ 

107 return self._subtype 

108 

109 @readonly 

110 def ObjectVertex(self) -> Nullable[Vertex]: 

111 """ 

112 Read-only property to access the corresponding object vertex (:attr:`_objectVertex`). 

113 

114 The object vertex references this Object by its value field. 

115 

116 :returns: The corresponding object vertex. 

117 """ 

118 return self._objectVertex 

119 

120 def Copy(self) -> Self: 

121 """ 

122 Create a copy of this object declaration. 

123 

124 The copy has no parent and no object vertex. Its subtype is a copy of this declaration's subtype. 

125 

126 :returns: The new object declaration. 

127 """ 

128 return self.__class__(self._identifiers, self._subtype.Copy(), self._documentation) 

129 

130 def __str__(self) -> str: 

131 """ 

132 Formats the object declaration. 

133 

134 **Format:** ``signal s1, s2 : bit`` 

135 

136 :returns: Formatted object declaration. 

137 """ 

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

139 

140 

141@export 

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

143 """ 

144 A ``WithDefaultExpression`` is a mixin-class for all objects declarations accepting default expressions. 

145 

146 The default expression is referenced by :data:`__defaultExpression`. If no default expression is present, this field 

147 is ``None``. 

148 

149 .. seealso:: 

150 

151 * :class:`Constant <pyVHDLModel.Object.Constant>` 

152 * :class:`Variable <pyVHDLModel.Object.Variable>` 

153 * :class:`Signal <pyVHDLModel.Object.Signal>` 

154 """ 

155 

156 _defaultExpression: Nullable[ExpressionUnion] #: The default value, or ``None`` if none was given. 

157 

158 def __init__(self, defaultExpression: Nullable[ExpressionUnion] = None) -> None: 

159 """ 

160 Initializes an object with a default expression. 

161 

162 :param defaultExpression: The default value, or ``None`` if none was given. 

163 """ 

164 self._defaultExpression = defaultExpression 

165 if defaultExpression is not None: 

166 defaultExpression.Parent = self 

167 

168 @readonly 

169 def DefaultExpression(self) -> Nullable[ExpressionUnion]: 

170 """ 

171 Read-only property to access the default expression (:attr:`_defaultExpression`). 

172 

173 :returns: The default expression, or ``None`` if not set. 

174 """ 

175 return self._defaultExpression 

176 

177 def _VisitDefaultExpression(self, visitor: Visitor) -> None: 

178 """ 

179 Walk the default expression, if any, after a variable assignment delimiter (``:=``) with a visitor. 

180 

181 :param visitor: The visitor receiving the events. 

182 """ 

183 if self._defaultExpression is not None: 

184 visitor.VisitVariableAssignment(self) 

185 self._defaultExpression.Visit(visitor) 

186 

187 

188@export 

189@abstractclass 

190class BaseConstant(Obj): 

191 """ 

192 Base-class for all constants (normal and deferred constants) in VHDL. 

193 

194 .. seealso:: 

195 

196 * :class:`Constant <pyVHDLModel.Object.Constant>` 

197 * :class:`Deferred constant <pyVHDLModel.Object.DeferredConstant>` 

198 """ 

199 

200 _OBJECT_KEYWORD: ClassVar[tuple[ReservedWord, ...]] = (ReservedWord.Constant,) #: The reserved words introducing this object class. 

201 

202 

203@export 

204class Constant(BaseConstant, WithDefaultExpressionMixin): 

205 """ 

206 Represents a constant. 

207 

208 As constants (always) have a default expression, the class :class:`~pyVHDLModel.Object.WithDefaultExpressionMixin` is inherited. 

209 

210 .. admonition:: Example 

211 

212 .. code-block:: VHDL 

213 

214 constant BITS : positive := 8; 

215 

216 .. seealso:: 

217 

218 * :class:`Generic constant interface item <pyVHDLModel.Interface.GenericConstantInterfaceItem>` 

219 * :class:`Parameter constant interface item <pyVHDLModel.Interface.ParameterConstantInterfaceItem>` 

220 """ 

221 

222 def __init__( 

223 self, 

224 identifiers: Iterable[str], 

225 subtype: Symbol, 

226 defaultExpression: Nullable[ExpressionUnion] = None, 

227 documentation: Nullable[str] = None, 

228 parent: Nullable[ModelEntity] = None 

229 ) -> None: 

230 """ 

231 Initializes a constant. 

232 

233 :param identifiers: A list of identifiers. 

234 :param subtype: Reference to the object's subtype. 

235 :param defaultExpression: The default value, or ``None`` if none was given. 

236 :param documentation: The documentation comment associated with this declaration. 

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

238 """ 

239 super().__init__(identifiers, subtype, documentation, parent) 

240 WithDefaultExpressionMixin.__init__(self, defaultExpression) 

241 

242 def Copy(self) -> Self: 

243 """ 

244 Create a copy of this constant. 

245 

246 The copy has no parent and no object vertex. Its subtype and default expression are copies of this constant's 

247 subtype and default expression. 

248 

249 :returns: The new constant. 

250 """ 

251 defaultExpression = None if self._defaultExpression is None else self._defaultExpression.Copy() 

252 return self.__class__(self._identifiers, self._subtype.Copy(), defaultExpression, self._documentation) 

253 

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

255 """ 

256 Walk this constant declaration, its subtype and its default expression with a visitor. 

257 

258 :param visitor: The visitor receiving the events. 

259 """ 

260 visitor.VisitConstant(self) 

261 self._subtype.Visit(visitor) 

262 self._VisitDefaultExpression(visitor) 

263 visitor.DepartConstant(self) 

264 

265 

266@export 

267class DeferredConstant(BaseConstant): 

268 """ 

269 Represents a deferred constant. 

270 

271 Deferred constants are forward declarations for a (complete) constant declaration, thus it contains a 

272 field :data:`__constantReference` to the complete constant declaration. 

273 

274 .. admonition:: Example 

275 

276 .. code-block:: VHDL 

277 

278 constant BITS : positive; 

279 """ 

280 _constantReference: Nullable[Constant] #: The full declaration, or ``None`` if unlinked. 

281 

282 def __init__( 

283 self, 

284 identifiers: Iterable[str], 

285 subtype: Symbol, 

286 documentation: Nullable[str] = None, 

287 parent: Nullable[ModelEntity] = None 

288 ) -> None: 

289 """ 

290 Initializes a deferred constant. 

291 

292 :param identifiers: A list of identifiers. 

293 :param subtype: Reference to the object's subtype. 

294 :param documentation: The documentation comment associated with this declaration. 

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

296 """ 

297 super().__init__(identifiers, subtype, documentation, parent) 

298 

299 self._constantReference = None 

300 

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

302 """ 

303 Walk this deferred constant declaration, its subtype with a visitor. 

304 

305 :param visitor: The visitor receiving the events. 

306 """ 

307 visitor.VisitDeferredConstant(self) 

308 self._subtype.Visit(visitor) 

309 visitor.DepartDeferredConstant(self) 

310 

311 @readonly 

312 def ConstantReference(self) -> Nullable[Constant]: 

313 """ 

314 Read-only property to access the constant reference (:attr:`_constantReference`). 

315 

316 :returns: The constant reference, or ``None`` if not set. 

317 """ 

318 return self._constantReference 

319 

320 def Copy(self) -> Self: 

321 """ 

322 Create a copy of this deferred constant. 

323 

324 The copy has no parent and no object vertex. Its subtype is a copy of this deferred constant's subtype; the full 

325 constant declaration, if linked, is the same. 

326 

327 :returns: The new deferred constant. 

328 """ 

329 copy = self.__class__(self._identifiers, self._subtype.Copy(), self._documentation) 

330 copy._constantReference = self._constantReference 

331 return copy 

332 

333 

334@export 

335class Variable(Obj, WithDefaultExpressionMixin): 

336 """ 

337 Represents a variable. 

338 

339 As variables might have a default expression, the class :class:`~pyVHDLModel.Object.WithDefaultExpressionMixin` is inherited. 

340 

341 .. admonition:: Example 

342 

343 .. code-block:: VHDL 

344 

345 variable result : natural := 0; 

346 

347 .. seealso:: 

348 

349 * :class:`Parameter variable interface item <pyVHDLModel.Interface.ParameterVariableInterfaceItem>` 

350 """ 

351 

352 _OBJECT_KEYWORD: ClassVar[tuple[ReservedWord, ...]] = (ReservedWord.Variable,) #: The reserved words introducing this object class. 

353 

354 def __init__( 

355 self, 

356 identifiers: Iterable[str], 

357 subtype: Symbol, 

358 defaultExpression: Nullable[ExpressionUnion] = None, 

359 documentation: Nullable[str] = None, 

360 parent: Nullable[ModelEntity] = None 

361 ) -> None: 

362 """ 

363 Initializes a variable. 

364 

365 :param identifiers: A list of identifiers. 

366 :param subtype: Reference to the object's subtype. 

367 :param defaultExpression: The default value, or ``None`` if none was given. 

368 :param documentation: The documentation comment associated with this declaration. 

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

370 """ 

371 super().__init__(identifiers, subtype, documentation, parent) 

372 WithDefaultExpressionMixin.__init__(self, defaultExpression) 

373 

374 def Copy(self) -> Self: 

375 """ 

376 Create a copy of this variable. 

377 

378 The copy has no parent and no object vertex. Its subtype and default expression are copies of this variable's 

379 subtype and default expression. 

380 

381 :returns: The new variable. 

382 """ 

383 defaultExpression = None if self._defaultExpression is None else self._defaultExpression.Copy() 

384 return self.__class__(self._identifiers, self._subtype.Copy(), defaultExpression, self._documentation) 

385 

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

387 """ 

388 Walk this variable declaration, its subtype and its default expression with a visitor. 

389 

390 :param visitor: The visitor receiving the events. 

391 """ 

392 visitor.VisitVariable(self) 

393 self._subtype.Visit(visitor) 

394 self._VisitDefaultExpression(visitor) 

395 visitor.DepartVariable(self) 

396 

397 

398@export 

399class SharedVariable(Obj): 

400 """ 

401 Represents a shared variable. 

402 

403 .. todo:: Shared variable object not implemented. 

404 """ 

405 

406 _OBJECT_KEYWORD: ClassVar[tuple[ReservedWord, ...]] = (ReservedWord.Shared, ReservedWord.Variable) #: The reserved words introducing this object class. 

407 

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

409 """ 

410 Walk this shared variable declaration, its subtype with a visitor. 

411 

412 :param visitor: The visitor receiving the events. 

413 """ 

414 visitor.VisitSharedVariable(self) 

415 self._subtype.Visit(visitor) 

416 visitor.DepartSharedVariable(self) 

417 

418 

419 

420@export 

421class Signal(Obj, WithDefaultExpressionMixin): 

422 """ 

423 Represents a signal. 

424 

425 As signals might have a default expression, the class :class:`~pyVHDLModel.Object.WithDefaultExpressionMixin` is inherited. 

426 

427 .. admonition:: Example 

428 

429 .. code-block:: VHDL 

430 

431 signal counter : unsigned(7 downto 0) := '0'; 

432 

433 .. seealso:: 

434 

435 * :class:`Port signal interface item <pyVHDLModel.Interface.PortSignalInterfaceItem>` 

436 * :class:`Parameter signal interface item <pyVHDLModel.Interface.ParameterSignalInterfaceItem>` 

437 """ 

438 

439 _OBJECT_KEYWORD: ClassVar[tuple[ReservedWord, ...]] = (ReservedWord.Signal,) #: The reserved words introducing this object class. 

440 

441 def __init__( 

442 self, 

443 identifiers: Iterable[str], 

444 subtype: Symbol, 

445 defaultExpression: Nullable[ExpressionUnion] = None, 

446 documentation: Nullable[str] = None, 

447 parent: Nullable[ModelEntity] = None 

448 ) -> None: 

449 """ 

450 Initializes a signal. 

451 

452 :param identifiers: A list of identifiers. 

453 :param subtype: Reference to the object's subtype. 

454 :param defaultExpression: The default value, or ``None`` if none was given. 

455 :param documentation: The documentation comment associated with this declaration. 

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

457 """ 

458 super().__init__(identifiers, subtype, documentation, parent) 

459 WithDefaultExpressionMixin.__init__(self, defaultExpression) 

460 

461 def Copy(self) -> Self: 

462 """ 

463 Create a copy of this signal. 

464 

465 The copy has no parent and no object vertex. Its subtype and default expression are copies of this signal's 

466 subtype and default expression. 

467 

468 :returns: The new signal. 

469 """ 

470 defaultExpression = None if self._defaultExpression is None else self._defaultExpression.Copy() 

471 return self.__class__(self._identifiers, self._subtype.Copy(), defaultExpression, self._documentation) 

472 

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

474 """ 

475 Walk this signal declaration, its subtype and its default expression with a visitor. 

476 

477 :param visitor: The visitor receiving the events. 

478 """ 

479 visitor.VisitSignal(self) 

480 self._subtype.Visit(visitor) 

481 self._VisitDefaultExpression(visitor) 

482 visitor.DepartSignal(self) 

483 

484 

485@export 

486class File(Obj): 

487 """ 

488 Represents a file. 

489 

490 .. todo:: File object not implemented. 

491 

492 .. seealso:: 

493 

494 * :class:`Parameter file interface item <pyVHDLModel.Interface.ParameterFileInterfaceItem>` 

495 """ 

496 

497 _OBJECT_KEYWORD: ClassVar[tuple[ReservedWord, ...]] = (ReservedWord.File,) #: The reserved words introducing this object class. 

498 

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

500 """ 

501 Walk this file declaration, its subtype with a visitor. 

502 

503 :param visitor: The visitor receiving the events. 

504 """ 

505 visitor.VisitFile(self) 

506 self._subtype.Visit(visitor) 

507 visitor.DepartFile(self)