#pragma once
#include "BKToken.h"
#include "RPNChain.h"

class LabelRef
{
		uint32_t            type{ 0 };   // тип арифметического выражения, выражение может быть в команде, тогда у него есть адрес
		// или может быть в определении, тогда у него нет адреса, но есть имя.
		int                 address{ 0 };// адрес, где встретилось арифметическое выражение
		CBKToken            define; // имя определения, где встретилось арифметическое выражение
		// или имя локальной метки, для них нету арифметических выражений
		RPNChain_t chain;  // цепочка арифметического выражения.

	public:
		LabelRef() = default;
		LabelRef(uint32_t lt, int addr, CBKToken *pt, const RPNChain_t &rpn)
			: type(lt)
			, address(addr)
			, define{ pt ? * pt : CBKToken() }
			, chain(rpn)
		{}
		inline uint32_t getType() const noexcept
		{
			return type;
		}
		inline void setType(uint32_t t) noexcept
		{
			type = t;
		}
		inline int getAddress() const noexcept
		{
			return address;
		}
		inline void setAddress(int v) noexcept
		{
			address = v;
		}

		inline const CBKToken &getDefine() noexcept
		{
			return define;
		}

		inline CBKToken *getPDefine() noexcept
		{
			return &define;
		}

		inline RPNChain_t &getRPN() noexcept
		{
			return chain;
		}

		inline RPNChain_t *getPPRN() noexcept
		{
			return &chain;
		}

		void Store(FILE *f)
		{
			const OBJTags tag = OBJTags::OBJ_Refs;
			fwrite(&tag, 1, sizeof(tag), f);
			fwrite(&type, 1, sizeof(type), f);
			fwrite(&address, 1, sizeof(address), f);
			define.Store(f);
			RPNChainFunc::Store(f, chain);
		}

		bool Load(FILE *f)
		{
			OBJTags tag{};
			fread(&tag, 1, sizeof(tag), f);

			if (tag == OBJTags::OBJ_Refs)
			{
				fread(&type, 1, sizeof(type), f);
				fread(&address, 1, sizeof(address), f);

				if (define.Load(f))
				{
					if (RPNChainFunc::Load(f, chain))
					{
						return true;
					}
				}
			}

			return false;
		}
};
