pyVHDLModel.Namespace

pyVHDLModel/Namespace.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# ==================================================================================================================== #
#             __     ___   _ ____  _     __  __           _      _                                                     #
#   _ __  _   \ \   / / | | |  _ \| |   |  \/  | ___   __| | ___| |                                                    #
#  | '_ \| | | \ \ / /| |_| | | | | |   | |\/| |/ _ \ / _` |/ _ \ |                                                    #
#  | |_) | |_| |\ V / |  _  | |_| | |___| |  | | (_) | (_| |  __/ |                                                    #
#  | .__/ \__, | \_/  |_| |_|____/|_____|_|  |_|\___/ \__,_|\___|_|                                                    #
#  |_|    |___/                                                                                                        #
# ==================================================================================================================== #
# Authors:                                                                                                             #
#   Patrick Lehmann                                                                                                    #
#                                                                                                                      #
# License:                                                                                                             #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Boetzingen, Germany                                                            #
# Copyright 2016-2017 Patrick Lehmann - Dresden, Germany                                                               #
#                                                                                                                      #
# Licensed under the Apache License, Version 2.0 (the "License");                                                      #
# you may not use this file except in compliance with the License.                                                     #
# You may obtain a copy of the License at                                                                              #
#                                                                                                                      #
#   http://www.apache.org/licenses/LICENSE-2.0                                                                         #
#                                                                                                                      #
# Unless required by applicable law or agreed to in writing, software                                                  #
# distributed under the License is distributed on an "AS IS" BASIS,                                                    #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                                             #
# See the License for the specific language governing permissions and                                                  #
# limitations under the License.                                                                                       #
#                                                                                                                      #
# SPDX-License-Identifier: Apache-2.0                                                                                  #
# ==================================================================================================================== #
#
"""
This module contains parts of an abstract document language model for VHDL.

A helper class to implement namespaces and scopes.
"""
from typing             import TypeVar, Generic, Dict

from pyVHDLModel.Object import Obj, Signal, Constant, Variable

from pyVHDLModel.Symbol import ComponentInstantiationSymbol, Symbol, PossibleReference
from pyVHDLModel.Type   import Subtype, FullType, BaseType

K = TypeVar("K")
O = TypeVar("O")


class Namespace(Generic[K, O]):
	_name:            str
	_parentNamespace: 'Namespace'
	_subNamespaces:   Dict[str, 'Namespace']
	_elements:        Dict[K, O]

	def __init__(self, name: str, parentNamespace: 'Namespace' = None):
		self._name = name
		self._parentNamespace = parentNamespace
		self._subNamespaces = {}
		self._elements = {}

	@property
	def Name(self) -> str:
		return self._name

	@property
	def ParentNamespace(self) -> 'Namespace':
		return self._parentNamespace

	@ParentNamespace.setter
	def ParentNamespace(self, value: 'Namespace'):
		self._parentNamespace = value
		value._subNamespaces[self._name] = self

	@property
	def SubNamespaces(self) -> Dict[str, 'Namespace']:
		return self._subNamespaces

	def Elements(self) -> Dict[K, O]:
		return self._elements

	def FindComponent(self, componentSymbol: ComponentInstantiationSymbol) -> 'Component':
		from pyVHDLModel.DesignUnit import Component

		try:
			element = self._elements[componentSymbol._name._normalizedIdentifier]
			if isinstance(element, Component):
				return element
			else:
				raise TypeError(f"Found element '{componentSymbol._name._identifier}', but it is not a component.")
		except KeyError:
			parentNamespace = self._parentNamespace
			if parentNamespace is None:
				raise KeyError(f"Component '{componentSymbol._name._identifier}' not found in '{self._name}'.")

			return parentNamespace.FindComponent(componentSymbol)

	def FindSubtype(self, subtypeSymbol: Symbol) -> BaseType:
		try:
			element = self._elements[subtypeSymbol._name._normalizedIdentifier]
			if isinstance(element, Subtype):
				if PossibleReference.Subtype in subtypeSymbol._possibleReferences:
					return element
				else:
					raise TypeError(f"Found subtype '{subtypeSymbol._name._identifier}', but it was not expected.")
			elif isinstance(element, FullType):
				if PossibleReference.Type in subtypeSymbol._possibleReferences:
					return element
				else:
					raise TypeError(f"Found type '{subtypeSymbol._name._identifier}', but it was not expected.")
			else:
				raise TypeError(f"Found element '{subtypeSymbol._name._identifier}', but it is not a type or subtype.")
		except KeyError:
			parentNamespace = self._parentNamespace
			if parentNamespace is None:
				raise KeyError(f"Subtype '{subtypeSymbol._name._identifier}' not found in '{self._name}'.")

			return parentNamespace.FindSubtype(subtypeSymbol)

	def FindObject(self, objectSymbol: Symbol) -> Obj:
		try:
			element = self._elements[objectSymbol._name._normalizedIdentifier]
			if isinstance(element, Signal):
				if PossibleReference.Signal in objectSymbol._possibleReferences:
					return element
				elif PossibleReference.SignalAttribute in objectSymbol._possibleReferences:
					return element
				else:
					raise TypeError(f"Found signal '{objectSymbol._name._identifier}', but it was not expected.")
			elif isinstance(element, Constant):
				if PossibleReference.Constant in objectSymbol._possibleReferences:
					return element
				else:
					raise TypeError(f"Found constant '{objectSymbol._name._identifier}', but it was not expected.")
			elif isinstance(element, Variable):
				if PossibleReference.Variable in objectSymbol._possibleReferences:
					return element
				else:
					raise TypeError(f"Found variable '{objectSymbol._name._identifier}', but it was not expected.")
			else:
				raise TypeError(f"Found element '{objectSymbol._name._identifier}', but it is not a type or subtype.")
		except KeyError:
			parentNamespace = self._parentNamespace
			if parentNamespace is None:
				raise KeyError(f"Subtype '{objectSymbol._name._identifier}' not found in '{self._name}'.")

			return parentNamespace.FindObject(objectSymbol)