# coding:utf8
"""
Модуль для базового типа поля.
Тип поля может быть:
1. Переменные
2. Поля в типах
3. Поля в процедурах.
"""

if True:
	from пакОберон.пакКомпилятор.пакСущность.пакРод import тРод
	from пакОберон.пакКомпилятор.пакСущность.пакОшибка import тОшибка

class тПолеБаза:
	__slots__ = ("ошб", )
	def __init__(сам, пОберон, пДанные):
		def Слова_Проверить():
			if type(пДанные['слова']) != dict:
				стрОш = "В секцию  должен передаваться словарь слов, type=" + str(type(пДанные['слова']))
				сам.ошб.Внутр("Слова_Проверить()", стрОш)
				return
			if пДанные['секция'] != "VAR":
				стрОш =  "Ошибочное использование типа в секции VAR, секция=" + пДанные['секция']
				сам.ошб.Внутр("Слова_Проверить()", стрОш)

		сам.ошб = тОшибка(пОберон, "тПолеБаза")

		Слова_Проверить()
		if сам.ошб.бВнутр:
			return
		сам.слова_секции = пДанные['слова']
		сам.__имя = пДанные['имя'] # имя в полях низкого уровня не обрабатывается
		сам.__бЭкспорт = пДанные['бЭкспорт'] # эксопрт в полях низкого уровня не вычисляется
		сам.__бЭкспорт_бПрисвоено = False # Защёлка присвоения экспорта
		сам.__бЭкспорт = False # бЭкспорт будет выясняться самими силами поля
		сам.__бСсылка_бПрисвоено = False # Защёлка присвоения ссылки
		сам.__бСсылка = False
		сам.__предок = тРод.сБезПредка

	@property
	def бЭкспорт(сам):
		return сам.__бЭкспорт

	def СловаСекции_Обрезать(сам):
		"""
		Уменьшает слова секции на 1 с головы.
		"""
		новый_список = {}
		for ключ in range(1, len(сам.слова_секции)):
			новый_список[ключ-1]=сам.слова_секции[ключ]
		сам.слова_секции = {}
		сам.слова_секции = новый_список

	def Предок_Проверить(сам):
		"""
		Проверяет предка поля. Должно быть разрешённой строкой.
		конечный символ ";" или ")"
		Кроме того, имя может быть составным
		===== Улучшенная проверенная версия =======
		"""
		слово_предок = сам.слова_секции[0]
		предок = слово_предок.строка
		if not слово_предок.ЕслиСтр_Допустимо():
			стрОш = "Имя поля должно быть допустимым именем"
			стрОш += слово_предок.стрИмя + слово_предок.стрИсх
			сам.ошб.Внутр("Предок_Проверить()", стрОш)
			return
		if сам.предок != тРод.сБезТипа:
			сам.__бОшВнутр = True
			стрОш = "Предок уже назначен \"" + сам.предок + "\"" + слово_предок.стрИсх
			сам.ошб.Внутр("Предок_Проверить()", стрОш)
			return
		сам.__предок = ""
		усл1 = (предок == ".") or (слово_предок.ЕслиСтр_Допустимо())
		усл2 = not (предок == ";") or (предок==")")
		while True:
			if (not усл1) and усл2:
				break
			сам.СловаСекции_Обрезать()
			сам.__предок += предок
			слово_предок = сам.слова_секции[0]
			предок = слово_предок.Проверить()
			усл1 = (предок == ".") or (слово_предок.ЕслиСтр_Допустимо())
			усл2 = not (предок == ";") or (предок==")")

		#if not (слово_предок.ЕслиСтр_Допустимо() or предок=="."):
		#	assert False, стрОш + слово_предок.строка + слово_предок.стрИсх

	def Разделитель_Обрезать(сам):
		"""
		В полях последнее слово ";" или ")"
		Поэтому его необходимо обрезать
		"""
		слово_раздел = сам.слова_секции[0]
		if слово_раздел.род == тСлово.кТочкаЗапятая:
			сам.СловаСекции_Обрезать()
		elif слово_раздел.строка == ")":
			pass # скобку обрабатывает уровень выше
		else:
			# В типе всегда есть разделитель в конце
			стрОш = "еправильный разделитель типа" + слово_раздел.стрИсх
			сам.ошб.Исх("Разделитель_Обрезать()", стрОш)
			return

	@property
	def имя(сам):
		return сам.__имя

	def бЭксорт_Уст(сам, пЭкспорт):
		"""
		Устанавливает экспорт с проверкой.
		Разрешаетися устанавливать один раз.
		Процедура с защёлкой.
		"""
		if type(пЭкспорт) != BOOLEAN:
			стрОш = "пЭкспорт должен быть BOOLEAN, type=" + str(type(пЭкспорт))
			сам.ошб.Внутр("бЭксорт_Уст", стрОш)
			return
		if сам.__бЭкспорт_бПрисвоено != False:
			стрОш = "пЭкспорт уже присвоен, экспорт=" + сам.__бЭкспорт
			сам.ошб.Внутр("бЭксорт_Уст", стрОш)
			return
		сам.__бЭкспорт_бПрисвоено = True
		сам.__бЭкспорт = пЭкспорт

	@property
	def бЭкспорт(сам):
		return сам.__бЭкспорт

	def бСсылка_Уст(сам, пСсылка):
		"""
		Устанавливает ссылку с проверкой.
		Разрешаетися устанавливать один раз.
		Процедура с защёлкой.
		"""
		#TODO: надо сделать отдельный тип для ссылки
		if type(пСсылка) != bool:
			стрОш = "пСсылка должен быть BOOLEAN, type=" + str(type(пСсылка))
			сам.ошб.Внутр("бСсылка_Уст()", стрОш)
			return
		if сам.__бСсылка_бПрисвоено != False:
			стрОш = "пСсылка уже присвоен, экспорт=" + сам.__бСсылка
			сам.ошб.Внутр("бСсылка_Уст()", стрОш)
			return
		сам.__бСсылка_бПрисвоено = True
		сам.__бСсылка = пСсылка

	@property
	def бСсылка(сам):
		return сам.__бСсылка

	def Предок_Уст(сам, пПредок):
		"""
		Устанавливает имя с проверкой.
		Разрешаетися устанавливать один раз.
		Процедура с защёлкой.
		"""
		# TODO: имя предка может быть составным
		if type(пПредок) != str:
			стрОш = "пПредок должен быть str, type=" + str(type(пПредок))
			сам.ош.Внутр("Предок_Уст()", стрОш)
			return
		if пПредок == "":
			стрОш = "тпПредок не может быть пустым"
			сам.ош.Внутр("Предок_Уст()", стрОш)
			return
		if сам.__предок != тРод.сБезПредка:
			стрОш = "Имя уже присвоено, имя=" + сам.__предок
			сам.ош.Внутр("Предок_Уст()", стрОш)
			return
		сам.__предок = пПредок

	@property
	def предок(сам):
		return сам.__предок

	def Имя_Уст(сам, пИмя:str):
		"""
		Устанавливает имя с проверкой.
		Разрешаетися устанавливать один раз.
		Процедура с защёлкой.
		"""
		if type(пИмя) != str:
			стрОш = "пИмя должен быть str, type=" + str(type(пИмя))
			сам.ош.Внутр("Имя_Уст()", стрОш)
			return
		if пИмя == "":
			сам.ош.Внутр("Имя_Уст()", "пИмя не может быть пустым")
			return
		if сам.__имя != "":
			стрОш = "Имя уже присвоено, имя=" + сам.__имя
			сам.ош.Внутр("Имя_Уст()", стрОш)
			return
		сам.__имя = пИмя

	@property
	def имя(сам):
		return сам.__имя
