Coverage for pyVHDLModel/Name.py: 80%
92 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 22:13 +0000
« 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.
35VHDL uses *names* to express cross-references from *usage locations* to *declarations*. Here, *names* are single or
36combined identifiers. :mod:`Symbols <pyVHDLModel.Symbol>` are structures representing a *name* and a reference
37(pointer) to the referenced vhdl language entity.
38"""
39from typing import List, Iterable, Optional as Nullable
41from pyTooling.Decorators import export, readonly
43from pyVHDLModel.Base import ModelEntity, ExpressionUnion
46@export
47class Name(ModelEntity):
48 """``Name`` is the base-class for all *names* in the VHDL language model."""
50 _identifier: str
51 _normalizedIdentifier: str
52 _root: Nullable['Name'] # TODO: seams to be unused. There is no reverse linking, or?
53 _prefix: Nullable['Name']
55 def __init__(self, identifier: str, prefix: Nullable["Name"] = None, parent: ModelEntity = None) -> None:
56 super().__init__(parent)
58 self._identifier = identifier
59 self._normalizedIdentifier = identifier.lower()
61 if prefix is None:
62 self._prefix = None
63 self._root = self
64 else:
65 self._prefix = prefix
66 self._root = prefix._root
68 @readonly
69 def Identifier(self) -> str:
70 """
71 The identifier the name is referencing.
73 :returns: The referenced identifier.
74 """
75 return self._identifier
77 @readonly
78 def NormalizedIdentifier(self) -> str:
79 """
80 The normalized identifier the name is referencing.
82 :returns: The referenced identifier (normalized).
83 """
84 return self._normalizedIdentifier
86 @readonly
87 def Root(self) -> 'Name':
88 """
89 The root (left-most) element in a chain of names.
91 In case the name is a :class:`simple name <SimpleName>`, the root points to the name itself.
93 :returns: The name's root element.
94 """
95 return self._root
97 @readonly
98 def Prefix(self) -> Nullable['Name']:
99 """
100 The name's prefix in a chain of names.
102 :returns: The name left from current name, if not a simple name, otherwise ``None``.
103 """
104 return self._prefix
106 @readonly
107 def HasPrefix(self) -> bool:
108 """
109 Returns true, if the name has a prefix.
111 This is true for all names except :class:`simple names <SimpleName>`.
113 :returns: ``True``, if the name as a prefix.
114 """
115 return self._prefix is not None
117 def __repr__(self) -> str:
118 return f"Name: '{self.__str__()}'"
120 def __str__(self) -> str:
121 return self._identifier
124@export
125class SimpleName(Name):
126 """
127 A *simple name* is a name made from a single word.
129 For example, the entity name in an architecture declaration is a simple name, while the name of the architecture
130 itself is an identifier. The simple name references is again an identifier in the entity declaration, thus names
131 reference other (already) declared language entities.
132 """
135@export
136class ParenthesisName(Name):
137 _associations: List
139 def __init__(self, prefix: Name, associations: Iterable, parent: ModelEntity = None) -> None:
140 super().__init__("", prefix, parent)
142 self._associations = []
143 for association in associations:
144 self._associations.append(association)
145 association._parent = self
147 @readonly
148 def Associations(self) -> List:
149 return self._associations
151 def __str__(self) -> str:
152 return f"{self._prefix!s}({', '.join(str(a) for a in self._associations)})"
155@export
156class IndexedName(Name):
157 _indices: List[ExpressionUnion]
159 def __init__(self, prefix: Name, indices: Iterable[ExpressionUnion], parent: ModelEntity = None) -> None:
160 super().__init__("", prefix, parent)
162 self._indices = []
163 for index in indices:
164 self._indices.append(index)
165 index._parent = self
167 @readonly
168 def Indices(self) -> List[ExpressionUnion]:
169 return self._indices
171 def __str__(self) -> str:
172 return f"{self._prefix!s}({', '.join(str(i) for i in self._indices)})"
175@export
176class SlicedName(Name):
177 pass
180@export
181class SelectedName(Name):
182 """
183 A *selected name* is a name made from multiple words separated by a dot (``.``).
185 For example, the library and entity name in a direct entity instantiation is a selected name. Here the entity
186 identifier is a selected name. The library identifier is a :class:`simple name <SimpleName>`, which is
187 referenced by the selected name via the :attr:`~pyVHDLModel.Name.Prefix` property.
188 """
190 def __init__(self, identifier: str, prefix: Name, parent: ModelEntity = None) -> None:
191 super().__init__(identifier, prefix, parent)
193 def __str__(self) -> str:
194 return f"{self._prefix!s}.{self._identifier}"
197@export
198class AttributeName(Name):
199 def __init__(self, identifier: str, prefix: Name, parent: ModelEntity = None) -> None:
200 super().__init__(identifier, prefix, parent)
202 def __str__(self) -> str:
203 return f"{self._prefix!s}'{self._identifier}"
206@export
207class AllName(SelectedName):
208 """
209 The *all name* represents the reserved word ``all`` used in names.
211 Most likely this name is used in use-statements.
212 """
213 def __init__(self, prefix: Name, parent: ModelEntity = None) -> None:
214 super().__init__("all", prefix, parent) # TODO: the case of 'ALL' is not preserved
217@export
218class OpenName(Name):
219 """
220 The *open name* represents the reserved word ``open``.
222 Most likely this name is used in port associations.
223 """
224 def __init__(self, parent: ModelEntity = None) -> None:
225 super().__init__("open", parent) # TODO: the case of 'OPEN' is not preserved
227 def __str__(self) -> str:
228 return "open"