I have specification of language:
```md
# BetterCookie961-Interpreter
BetterCookie961 Interpreter written in c++

# BetterCookie961 Instructions

* `k` - move the pointer right
* `i` - move the pointer left
* `K` - move the pointer right and copy the value of the left cookie
* `I` - move the pointer left and copy the value of the right cookie
* `c` - increment the current cookie value
* `C` - Adds 10 to current cookie value
* `o` - decrement the current cookie value
* `O` - decreases the current cookie value by 10
* `L` - erase current cookie value
* `9` - output the value of the current cookie (Outputs only chars)
* `a` - debug(ASCII) output. Output the current cookie value
* `e` - **replace** the value of the current cookie with input
* `6` - jump to the **matching** `1` instruction if the current cookie value is zero
* `1` - jump to the **matching** `6` instruction if the current cookie value is **not** zero
* `(` - IF construction starts
* `)` - IF construction ends
* `N` - Return to the initial cookie
* `n` - print current cookie value
* `>` - Go to next line(in output)
* `R` - Write a random value in the range 0-100 to a cookie
* `{` - Beginning of an arithmetic expression
* `}` - End of arithmetic expression
* `r` - Run file from user input
* `B[filename]` - Run file
* `S[milliseconds]` - Sleep function
* `M[WhereToMove(int)]` - Move current cookie value to another cookie
* `-` - Stop executing program
* `g` - output in which cookie we are located
* `X[Offset(int)]` - Copy current cookie value to another cookie
* `/* {your comment here} */` - Comment
* `P` - Move to the cookie whose number corresponds to the value of the current cookie and transfer the number of the current cookie to the one to which we move (for example, in order to go back).
* `J` - Move to the cookie whose number corresponds to the value of the current cookie. (without transferring the number of the current cookie to the one to which we move).
* `_` - Exit from interpretation iteration.
* `G` - Write current cookie's address into current cookie.
* `x[+/-0/1]` - Copy the value of the current cookie to the address that lies in the left or right cookie (depending on -(left) or +(right)), and also moves the cursor to the address (if 1) and does not move (if 0).
* `m[+/-0/1]` - Move the value of the current cookie to the address that lies in the left or right cookie (depending on -(left) or +(right)), and also moves the cursor to the address (if 1) and does not move (if 0).
# Some Examples

* `M[3]` - Moves the value of this cookie 3 steps to the right.
* `M[-1]` - Moves the value of this cookie 1 step to the left.
* `x[-0]` - Copy the value of the current cookie to the address from the left cookie without moving the cursor.
* `m[+1]` - Move the value of the current cookie to the address from the right cookie and move the cursor to the address from the right cookie.

# How to write IF constructions

IF construction operators:
* `>` - bigger
* `<` - less
* `=` - equal
* `~` - not equal

1) IF always starts with an expression. (k > i ! cca)

2) Always after the expression comes !, after which the body is written. {k > i - expression} {! - delimiter} {cca - body}

3) IF has no variables, so numeric values are passed like this:
* `i` - left cookie value
* `k` - right cookie value
* `t` - current cookie value
Example: (k > i ! cca) = {if (k > i): do cca}


ATTENTION! Before calling the IF, "create" all the cookies you need (move to them)!
Example: cc(k > i ! cca) - ERROR, because right cookie does not exist. kkki(k > i ! cca) - SUCCESS, right and left cookies exist.
More examples:
* `kkk(k > i ! cca)` - ERROR, right cookie does not exist.
* `ki(k < i ! cca)` - ERROR, left cookie does not exist.

You can also write IF inside the BODY of another IF.
Examples:
* `cckccckcccci(k > i ! kkcckccckcci(i > k ! cca))` - SUCCESS.
* `cckccckcccci(k > i ! (i < k ! cca))` - SUCCESS.
* `cckccckcccci(k > (i < k ! cca))` - ERROR, no body.

**IF constructs ALWAYS have !, otherwise you will get an error.**

# How to write arithmetic expressions

Arithmetic expressions have 4 operators:
* `+` - addition
* `-` - subtraction
* `*` - multiplication
* `%` - division

Numeric values are passed through:
* `k` - right cookie value
* `t` - current cookie value
* `i` - left cookie value

**After executing an arithmetic expression, the result is written to the current cookie**

Examples:

`{t + k}` - current cookie value + right cookie value
`{t - i}` - current cookie value - left cookie value

**ATTENTION! The arithmetic expression only uses 2 values and 1 operator!**

`{t + k - i}` = `{t + k}`
`{i * k - t + k}` = `{i * k}`

Program Examples:

`ekei{t + k}n` - Calculates the sum of two numbers
`ekekei{t + k}{t + i}n` - Calculates the sum of three numbers
```

And I have source code of it debugger:
main.cpp
```cpp
#include <imgui.h>
#include <misc/cpp/imgui_stdlib.h>
#include <backends/imgui_impl_win32.h>
#include <backends/imgui_impl_dx11.h>

#include <portable-file-dialogs/portable-file-dialogs.h>

#include <d3d11.h>
#include <tchar.h>
#include <Windows.h>

#include <iostream>
#include <cstdarg>
#include <vector>
#include <stack>
#include <string>
#include <functional>
#include <memory>
#include <istream>
#include <sstream>
#include <thread>
#include <mutex>
#include <condition_variable>

#include "imgui_utils.h"
#include "BCookie961.h"
#include "utils.h"
#include "resource.h"

using namespace std::string_literals;

constexpr auto g_iInitialWidth = 1366;
constexpr auto g_iInitialHeight = 768;

void Fatal(const char* const msg, ...)
{
	va_list va;
	va_start(va, msg);
	size_t size = std::vsnprintf(nullptr, 0, msg, va) + 1;
	va_end(va);

	std::vector<char> buffer(size);
	va_start(va, msg);
	std::vsnprintf(buffer.data(), size, msg, va);
	va_end(va);

	std::fprintf(stderr, "%s\n", buffer.data());
	::MessageBoxA(NULL, buffer.data(), "ERROR!", MB_OK);

	std::exit(1);
}

struct RenderContext_t
{
	HWND m_hWnd;
	uint32_t m_iWidth;
	uint32_t m_iHeight;

	IDXGISwapChain* m_pSwapChain;

	ID3D11Device* m_pDevice;
	ID3D11DeviceContext* m_pContext;

	ID3D11RenderTargetView* m_pRenderTargetView;

	ImFont* m_pBC961Font;
	ImFont* m_pDefaultFont;
};

class IWindow
{
public:
	IWindow() = default;
	virtual ~IWindow() = default;

	virtual void Render(RenderContext_t& context) = 0;
};
using Windows_t = std::vector<std::unique_ptr<IWindow>>;

class CMainLayoutWindow final : public IWindow
{
private:
	const int m_iCellWidth = 80;
	const int m_iCellHeight = 60;

	bool m_bNeedScroll;
	std::string m_ConsoleBuffer;

	int m_iHistoryPos;
	std::vector<std::string> m_vConsoleHistory;

	COutStreamBuf m_COUTStreamBuf;
	CInStreamBuf m_CINStreamBuf;

	std::atomic_bool m_bExecute;
	std::atomic_bool m_bIntepreterThreadFileRestart;
	std::jthread m_InterpreterThread;

public:
	CMainLayoutWindow()
		: m_bNeedScroll(false), m_iHistoryPos(-1), m_bExecute(true),
		  m_COUTStreamBuf([](void* userData, char c) -> void
						  { static_cast<CMainLayoutWindow*>(userData)->m_bNeedScroll = true; },
						  this)
	{
		RestartInterpreter();
	}

	virtual ~CMainLayoutWindow()
	{
		m_COUTStreamBuf.Close();
		m_CINStreamBuf.Close();

		if (m_bExecute.exchange(false) && m_InterpreterThread.joinable()) m_InterpreterThread.join();
	}

	void Render(RenderContext_t& context) override
	{
		ImGui::SetNextWindowPos({0, 0});
		ImGui::SetNextWindowSize({(float)context.m_iWidth, m_iCellHeight + 40.f});

		ImGui::PushFont(context.m_pDefaultFont);
		const int cellsCount = getArray().size();
		if (ImGui::Begin("Cells", nullptr,
						 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
							 ImGuiWindowFlags_HorizontalScrollbar))
		{
			ImVec2 window_pos = ImGui::GetWindowPos();
			ImVec2 window_size = ImGui::GetWindowSize();
			ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);

			const auto& color = ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered];

			float posX;
			if (cellsCount * m_iCellWidth > ImGui::GetWindowSize().x)
				posX = m_iCellWidth / 2.f;
			else
				posX = ImGui::GetWindowSize().x / 2.f - ((cellsCount - 1) * m_iCellWidth / 2.f);

			for (int i = 0; i < cellsCount; ++i)
			{
				DrawCell(getArray().at(i), {posX, window_center.y}, i == getPointerLocation());
				posX += m_iCellWidth;
			}

			ImGui::End();
		}
		ImGui::PopFont();

		ImGui::SetNextWindowPos({0, m_iCellHeight + 40.f});
		ImGui::SetNextWindowSize({context.m_iWidth - 350.f, context.m_iHeight - (m_iCellHeight + 40.f)});
		if (ImGui::Begin("Debugger", nullptr,
						 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
		{
			ImGui::PushFont(context.m_pBC961Font);

			ImVec2 size = ImGui::GetWindowSize();
			size.x -= ImGui::GetStyle().FramePadding.x * 4;
			size.y -= (ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 8.5f);
			if (ImGui::BeginChild("STDOUT", size, ImGuiChildFlags_Border, ImGuiWindowFlags_HorizontalScrollbar))
			{
				ImGui::TextUnformatted(m_COUTStreamBuf.str().c_str());
				if (m_bNeedScroll)
				{
					ImGui::SetScrollHereY(1.0f);
					m_bNeedScroll = false;
				}

				ImGui::EndChild();
			}

			ImGui::PushItemWidth(size.x);
			if (ImGui::InputTextWithHint(
					"##Console", "Enter text here!", &m_ConsoleBuffer,
					ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AllowTabInput |
						ImGuiInputTextFlags_CallbackHistory,
					[](ImGuiInputTextCallbackData* data)
					{ return static_cast<CMainLayoutWindow*>(data->UserData)->ConsoleCallback(data); },
					this))
			{
				ImGui::SetKeyboardFocusHere(-1); // Do not lose focus

				if (m_ConsoleBuffer.size())
				{
					std::cout << m_ConsoleBuffer + '\n';
					m_bNeedScroll = true;

					m_CINStreamBuf.provide_data(m_ConsoleBuffer + '\n');

					m_iHistoryPos = -1;
					m_vConsoleHistory.emplace_back(m_ConsoleBuffer);
					m_ConsoleBuffer.clear();
				}
			}
			ImGui::PopItemWidth();
			ImGui::PopFont();

			ImGui::End();
		}

		extern std::atomic_bool debuggerWait;
		extern std::atomic_bool debuggerStep;
		extern std::string_view debuggerCurrentCode;
		extern std::string_view::size_type debuggerCurrentCodePos;
		static bool needToScrollCode = false;

		ImGui::SetNextWindowPos({context.m_iWidth - 350.f, m_iCellHeight + 40.f});
		ImGui::SetNextWindowSize({350.f, context.m_iHeight - (m_iCellHeight + 40.f)});
		if (ImGui::Begin("Tools", nullptr,
						 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
		{
			if (ImGui::Button("Restart BC961 Interpreter\n(On deadlock or relaunch)")) 
			{
				// ImGui popup system is very tricky
				ImGui::OpenPopup("Really?"); 
			}

			if (ImGui::Button("Execute file"))
			{
				auto result = pfd::open_file::open_file("Choose source file", ".", {"BC961 Source files", "*.bc961"});
				while (!result.ready())
					;

				if (result.result().size())
					RestartInterpreterAndExecFile(result.result().back());
			}

			// Debugger extensions
			{
				if (ImGui::Button("Stop/Play (F5)") || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_F5)))
					debuggerWait = !debuggerWait;

				ImGui::RadioButton("Is execution stoped?", debuggerWait);

				ImGui::SeparatorText("Debugger tools");
				if (!debuggerWait) ImGui::BeginDisabled(true);
				{
					if (ImGui::Button("Execute one step (F10)") ||
						ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_F10)))
					{
						needToScrollCode = true;
						debuggerStep = true;
					}
				}
				if (!debuggerWait) ImGui::EndDisabled();
			}

			if (ImGui::BeginPopupModal("Really?", nullptr, ImGuiWindowFlags_AlwaysAutoResize))
			{
				ImGui::Text("This will reset interpreter to initial state. Continue?");

				if (ImGui::Button("Hell yea", ImVec2(120, 40)))
				{
					RestartInterpreter();
					ImGui::CloseCurrentPopup();
				}
				ImGui::SameLine();
				if (ImGui::Button("Nah...", ImVec2(120, 40)))
				{
					// Does nothing _/-_^\_
					ImGui::CloseCurrentPopup();
				}

				ImGui::EndPopup();
			}

			if (!debuggerWait) ImGui::BeginDisabled(true);
			{
				// ImGui::Text("Current position in code: %zi", debuggerCurrentCodePos);
				// if (ImGui::BeginListBox("##Breakpoints"))
				//{
				//	// setBreakpoint();
				//	ImGui::EndListBox();
				// }
				// ImGui::IsItemClicked();

				if (ImGui::BeginChild("Code", ImVec2(0, 0), ImGuiChildFlags_Border,
									  ImGuiWindowFlags_HorizontalScrollbar))
				{
					if (debuggerCurrentCode.size())
					{
						ImGui::Text("%s", std::string(debuggerCurrentCode.substr(0, debuggerCurrentCodePos)).c_str());

						ImGui::TextColored(ImGui::GetStyle().Colors[ImGuiCol_ButtonActive], "%s",
										   std::string(debuggerCurrentCode.substr(debuggerCurrentCodePos, 1)).c_str());

						if (needToScrollCode)
						{
							ImGui::SetScrollHereX();
							ImGui::SetScrollHereY();
							needToScrollCode = false;
						}

						if (debuggerCurrentCodePos + 1 < debuggerCurrentCode.size())
						{
							ImGui::Text("%s",
										std::string(debuggerCurrentCode.substr(debuggerCurrentCodePos + 1)).c_str());
						}
					}
					ImGui::EndChild();
				}
			}
			if (!debuggerWait) ImGui::EndDisabled();

			ImGui::End();
		}
	}

private:
	void RestartRoutine() 
	{
		if (m_InterpreterThread.joinable())
		{
			const auto [c, u] = m_COUTStreamBuf.Close();
			m_CINStreamBuf.Close();

			m_bExecute.exchange(false);
			m_InterpreterThread.join();

			m_COUTStreamBuf.Open(c, u);
			m_CINStreamBuf.Open();
		}

		std::cout.rdbuf(&m_COUTStreamBuf);
		std::cin.rdbuf(&m_CINStreamBuf);

		m_bExecute.exchange(true);
	}

	void RestartInterpreter()
	{
		RestartRoutine();

		m_InterpreterThread = std::jthread(
			[this]()
			{
				while (m_bExecute)
				{
					try
					{
						(void)bc961_main_shell(&m_bExecute);
					}
					catch (CExitException&)
					{
					}
					catch (std::exception& e)
					{
						std::cout << "Interpreter ended with this exception: " << e.what() << std::endl;
					}

					std::cout << "Enter anything to restart interpreter" << std::endl;

					std::string s;
					while (s.size() == 0 && m_bExecute)
						std::cin >> s;

					const auto [c, u] = m_COUTStreamBuf.Close();
					m_COUTStreamBuf.Open(c, u);
				}
			});
	}

	void RestartInterpreterAndExecFile(const std::string_view filename)
	{
		RestartRoutine();

		std::jthread awaiter = std::jthread([this]() 
		{ 
			using namespace std::chrono_literals;

			if (m_InterpreterThread.joinable())
					m_InterpreterThread.join();

			if (m_bIntepreterThreadFileRestart)
			{
				RestartInterpreter();
				m_bIntepreterThreadFileRestart = false;
			}
		});
		awaiter.detach();
		
		m_InterpreterThread = std::jthread(
			[this](const std::string filename)
			{
				try
				{
					(void)bc961_main_file(&m_bExecute, filename);
				}
				catch (CExitException&)
				{
				}
				catch (std::exception& e)
				{
					std::cout << "Interpreter ended with this exception: " << e.what() << std::endl;
				}

				std::cout << "Enter anything to restart interpreter" << std::endl;

				std::string s;
				while (s.size() == 0 && m_bExecute)
					std::cin >> s;

				const auto [c, u] = m_COUTStreamBuf.Close();
				m_COUTStreamBuf.Open(c, u);

				if (s.size()) m_bIntepreterThreadFileRestart = true;
			}, std::string(filename));
	}

	int ConsoleCallback(ImGuiInputTextCallbackData* data)
	{
		if (data->EventFlag & ImGuiInputTextFlags_CallbackHistory)
		{
			const int prev_history_pos = m_iHistoryPos;

			if (data->EventKey == ImGuiKey_UpArrow)
			{
				if (m_iHistoryPos == -1)
					m_iHistoryPos = (int)m_vConsoleHistory.size() - 1;
				else if (m_iHistoryPos > 0)
					m_iHistoryPos--;
			}
			else if (data->EventKey == ImGuiKey_DownArrow)
			{
				if (m_iHistoryPos != -1)
					if (++m_iHistoryPos >= (int)m_vConsoleHistory.size()) m_iHistoryPos = -1;
			}

			if (prev_history_pos != m_iHistoryPos)
			{
				const auto& history_str = (m_iHistoryPos >= 0) ? m_vConsoleHistory[m_iHistoryPos] : "";
				data->DeleteChars(0, data->BufTextLen);
				data->InsertChars(0, history_str.c_str());
			}
		}

		return 0;
	}

	void DrawCell(int value, const ImVec2& pos, bool current = false)
	{
		float scroll = ImGui::GetScrollX();
		if (!current)
			ImGuiUtils::DrawRect({pos.x - scroll, pos.y}, {(float)m_iCellWidth, (float)m_iCellHeight},
								 ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered]);
		else
			ImGuiUtils::DrawRectFilled({pos.x - scroll, pos.y}, {(float)m_iCellWidth, (float)m_iCellHeight},
									   ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered],
									   ImGui::GetStyle().Colors[ImGuiCol_ButtonActive]);
		ImGui::SetCursorPos(pos);
		if (std::isprint((char)value))
			ImGuiUtils::TextCentered("%i\n'%c'", value, (char)value);
		else
			ImGuiUtils::TextCentered("%i", value);
	}
};

static uint32_t g_iResizeWidth = 0;
static uint32_t g_iResizeHeight = 0;
static inline LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
	if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) return TRUE;

	switch (msg)
	{
		case WM_SIZE:
			if (wParam == SIZE_MINIMIZED) return 0;
			g_iResizeWidth = (UINT)LOWORD(lParam);
			g_iResizeHeight = (UINT)HIWORD(lParam);
			break;

		case WM_SYSCOMMAND:
			if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
				return FALSE;
			break;

		case WM_DESTROY:
			PostQuitMessage(0);
			return FALSE;

		default:
			break;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

static inline HWND CreateDebuggerWindow()
{
	const TCHAR CLASS_NAME[] = _TEXT("BetterCookie961DebuggerWindow");
	WNDCLASS wc = {
		.lpfnWndProc = WndProc,
		.hInstance = GetModuleHandle(0),
		.hIcon = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_ICON1)),
		.lpszClassName = CLASS_NAME,
	};
	RegisterClass(&wc);

	int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

	const std::string sas = "BetterCookie961 Debugger (version "s + DebuggerVersion + ")";
	HWND hwnd = CreateWindowEx(0, CLASS_NAME, std::wstring(sas.begin(), sas.end()).c_str(), WS_OVERLAPPEDWINDOW,
							   nScreenWidth / 2 - g_iInitialWidth / 2, nScreenHeight / 2 - g_iInitialHeight / 2,
							   g_iInitialWidth, g_iInitialHeight, NULL, NULL, GetModuleHandle(0), NULL);

	if (!hwnd) Fatal("Can't create window! Error: %d", GetLastError());

	ShowWindow(hwnd, 1);

	return hwnd;
}

static inline void CreateRenderTarget(RenderContext_t& context)
{
	ID3D11Texture2D* pBackBuffer;
	HRESULT hr = context.m_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
	if (FAILED(hr)) Fatal("Can't get back buffer!");

	hr = context.m_pDevice->CreateRenderTargetView(pBackBuffer, nullptr, &context.m_pRenderTargetView);
	if (FAILED(hr)) Fatal("Can't create render target!");

	pBackBuffer->Release();

	context.m_pContext->OMSetRenderTargets(1, &context.m_pRenderTargetView, nullptr);
}

static inline void CleanupRenderTarget(RenderContext_t& context)
{
	if (context.m_pRenderTargetView)
	{
		context.m_pRenderTargetView->Release();
		context.m_pRenderTargetView = nullptr;
	}
}

static inline void InitDirectX11(RenderContext_t& context)
{
	RECT renderSurfaceRct;
	GetClientRect(context.m_hWnd, &renderSurfaceRct);

	DXGI_SWAP_CHAIN_DESC sd;
	{
		ZeroMemory(&sd, sizeof(sd));
		sd.BufferCount = 1;
		sd.BufferDesc.Width = renderSurfaceRct.right;
		sd.BufferDesc.Height = renderSurfaceRct.bottom;
		sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
		sd.BufferDesc.RefreshRate.Numerator = 60;
		sd.BufferDesc.RefreshRate.Denominator = 1;
		sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
		sd.OutputWindow = context.m_hWnd;
		sd.SampleDesc.Count = 1;
		sd.SampleDesc.Quality = 0;
		sd.Windowed = TRUE;
	}

	D3D_FEATURE_LEVEL FeatureLevelsRequested = D3D_FEATURE_LEVEL_11_0;
	UINT numLevelsRequested = 1;
	D3D_FEATURE_LEVEL FeatureLevelsSupported;

	HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &FeatureLevelsRequested, 1,
											   D3D11_SDK_VERSION, &sd, &context.m_pSwapChain, &context.m_pDevice,
											   &FeatureLevelsSupported, &context.m_pContext);

	D3D11_VIEWPORT vp = {
		.TopLeftX = 0,
		.TopLeftY = 0,
		.Width = (FLOAT)renderSurfaceRct.right,
		.Height = (FLOAT)renderSurfaceRct.bottom,
		.MinDepth = 0.0f,
		.MaxDepth = 1.0f,
	};
	context.m_pContext->RSSetViewports(1, &vp);

	CreateRenderTarget(context);
}

static inline void FreeDX11(RenderContext_t& context)
{
	context.m_pContext->ClearState();

	context.m_pRenderTargetView->Release();

	context.m_pSwapChain->Release();
	context.m_pContext->Release();
	context.m_pDevice->Release();
}

static inline void LoadFileInResource(int name, int type, DWORD& size, void*& data)
{
	HMODULE handle = ::GetModuleHandle(NULL);
	HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(name), MAKEINTRESOURCE(type));
	HGLOBAL rcData = ::LoadResource(handle, rc);
	size = ::SizeofResource(handle, rc);
	data = ::LockResource(rcData);
}

static inline void InitImGUI(RenderContext_t& context)
{
	IMGUI_CHECKVERSION();
	ImGui::CreateContext();

	ImGuiIO& io = ImGui::GetIO();
	io.DisplaySize.x = (float)context.m_iWidth;
	io.DisplaySize.y = (float)context.m_iHeight;
	io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
	io.IniFilename = "";

	DWORD size;
	void* fontDataTmp;
	LoadFileInResource(IDR_BCFONTFILE, FONTFILE, size, fontDataTmp);
	{
		void* fontData = malloc(size);
		memcpy(fontData, fontDataTmp, size);
		context.m_pBC961Font =
			io.Fonts->AddFontFromMemoryTTF(fontData, size, 11, 0, ImGui::GetIO().Fonts->GetGlyphRangesCyrillic());
		context.m_pDefaultFont = io.Fonts->AddFontDefault();
	}

	ImGui::StyleColorsDark();

	ImGuiStyle& style = ImGui::GetStyle();
	style.WindowRounding = 0;

	ImGui_ImplWin32_Init(context.m_hWnd);
	ImGui_ImplDX11_Init(context.m_pDevice, context.m_pContext);
}

static inline void FreeImGUI(RenderContext_t& context)
{
	ImGui_ImplDX11_Shutdown();
	ImGui_ImplWin32_Shutdown();
	ImGui::DestroyContext();
}

static inline void Render(RenderContext_t& context, Windows_t& windows)
{
	ImGui_ImplDX11_NewFrame();
	ImGui_ImplWin32_NewFrame();
	ImGui::NewFrame();
	{
		for (const auto& window : windows)
			window->Render(context);
	}
	ImGui::Render();

	float ClearColor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
	context.m_pContext->ClearRenderTargetView(context.m_pRenderTargetView, ClearColor);

	ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

	context.m_pSwapChain->Present(2, 0);
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
	AllocConsole();
	::ShowWindow(::GetConsoleWindow(), SW_HIDE);

	RenderContext_t renderCtx = {
		.m_hWnd = CreateDebuggerWindow(),
		.m_iWidth = g_iInitialWidth,
		.m_iHeight = g_iInitialHeight,
	};
	InitDirectX11(renderCtx);
	InitImGUI(renderCtx);

	std::vector<std::unique_ptr<IWindow>> windows;
	windows.emplace_back(std::make_unique<CMainLayoutWindow>());

	MSG msg = {};
	while (true)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			if (msg.message == WM_QUIT) break;
		}
		else
		{
			if (g_iResizeWidth != 0 && g_iResizeHeight != 0)
			{
				CleanupRenderTarget(renderCtx);
				{
					renderCtx.m_pSwapChain->ResizeBuffers(0, g_iResizeWidth, g_iResizeHeight, DXGI_FORMAT_UNKNOWN, 0);
					renderCtx.m_iWidth = g_iResizeWidth;
					renderCtx.m_iHeight = g_iResizeHeight;
					g_iResizeWidth = g_iResizeHeight = 0;
				}
				CreateRenderTarget(renderCtx);
			}

			Render(renderCtx, windows);
		}
	}

	FreeImGUI(renderCtx);
	FreeDX11(renderCtx);

	return 0;
}
```

utils.h:
```cpp
#pragma once
#ifndef UTILS_H
#define UTILS_H

void Fatal(const char* const msg, ...);

class COutStreamBuf final : public std::streambuf
{
public:
	using PrintCallbackPtr_t = void (*)(void*, char);

private:
	bool m_bIsOpen;
	std::string m_Data;

	void* m_pUserData;
	PrintCallbackPtr_t m_pCallback;

protected:
	virtual int_type overflow(int_type c = traits_type::eof())
	{
		if (m_bIsOpen)
		{
			m_Data += (char)c;
			if (m_pCallback) m_pCallback(m_pUserData, c);
		}
		return c;
	}

public:
	COutStreamBuf(PrintCallbackPtr_t callback = nullptr, void* userData = nullptr) : m_bIsOpen(true)
	{
		Open(callback, userData);
	}

	virtual ~COutStreamBuf() { Close(); }

	void Open(PrintCallbackPtr_t callback = nullptr, void* userData = nullptr)
	{
		m_bIsOpen = true;
		m_pCallback = callback;
		m_pUserData = userData;
	}

	std::pair<PrintCallbackPtr_t, void*> Close()
	{
		m_bIsOpen = false;
		m_Data = "";

		std::pair<PrintCallbackPtr_t, void*> returnData(m_pCallback, m_pUserData);

		m_pCallback = nullptr;
		m_pUserData = nullptr;

		return returnData;
	}

	std::string& str() { return m_Data; }
};

class CInStreamBuf final : public std::streambuf
{
private:
	std::mutex m_Mutex;
	std::condition_variable m_CV;
	std::vector<char> m_Buffer;
	bool m_bDataReady;

protected:
	virtual int_type underflow()
	{
		std::unique_lock<std::mutex> lock(m_Mutex);
		m_CV.wait(lock, [this] { return m_bDataReady; });

		if (!m_Buffer.empty())
		{
			setg(m_Buffer.data(), m_Buffer.data(), m_Buffer.data() + m_Buffer.size());
			m_bDataReady = false;

			return traits_type::to_int_type(*gptr());
		}
		else
		{
			m_bDataReady = false;
			return traits_type::eof();
		}
	}

public:
	CInStreamBuf() : m_bDataReady(false) {}
	virtual ~CInStreamBuf() { Close(); }

	void Open()
	{
		m_bDataReady = false;
		m_CV.notify_one();
	}

	void Close()
	{
		m_bDataReady = true;
		m_CV.notify_one();
	}

	void provide_data(const std::string& data)
	{
		std::lock_guard<std::mutex> lock(m_Mutex);
		m_Buffer.assign(data.begin(), data.end());
		m_bDataReady = true;
		m_CV.notify_one();
	}

	void clear() { m_Buffer.clear(); }
};

#endif
```

imgui_utils.h:
```cpp
#pragma once
#ifndef IMGUI_UTILS_H
#define IMGUI_UTILS_H

#include <imgui.h>
#include <cstdint>

namespace ImGuiUtils
{
	static inline uint32_t ConvertVecToColor32(const ImVec4& color)
	{
		return IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255);
	}

	static inline void DrawRect(const ImVec2& pos, const ImVec2& size, uint32_t color, const uint32_t thickness = 14)
	{
		ImGui::GetWindowDrawList()->AddRect({pos.x - size.x / 2, pos.y - size.y / 2},
											{pos.x + size.x / 2, pos.y + size.y / 2}, color, 0, 1);
	}

	static inline void DrawRectFilled(const ImVec2& pos, const ImVec2& size, uint32_t color, uint32_t fillColor,
									  const uint32_t thickness = 14)
	{
		ImGui::GetWindowDrawList()->AddRect({pos.x - size.x / 2, pos.y - size.y / 2},
											{pos.x + size.x / 2, pos.y + size.y / 2}, color, 0, 1);
		ImGui::GetWindowDrawList()->AddRectFilled(
			{pos.x - size.x / 2 + thickness / 2, pos.y - size.y / 2 + thickness / 2},
			{pos.x + size.x / 2 - thickness / 2, pos.y + size.y / 2 - thickness / 2}, fillColor, 0, 1);
	}

	static inline void DrawRect(const ImVec2& pos, const ImVec2& size, const ImVec4& color,
								const uint32_t thickness = 14)
	{
		DrawRect(pos, size, ConvertVecToColor32(color), thickness);
	}

	static inline void DrawRectFilled(const ImVec2& pos, const ImVec2& size, const ImVec4& color,
									  const ImVec4& fillColor, const uint32_t thickness = 14)
	{
		DrawRectFilled(pos, size, ConvertVecToColor32(color), ConvertVecToColor32(fillColor), thickness);
	}

	static inline void TextCentered(const char* msg, ...)
	{
		va_list va;
		va_start(va, msg);
		char* buff = (char*)alloca(vsnprintf(nullptr, 0, msg, va) + 1);
		vsprintf(buff, msg, va);
		va_end(va);

		const ImVec2 textSize = ImGui::CalcTextSize(buff);
		ImGui::SetCursorPosX((ImGui::GetCursorPosX() - textSize.x * 0.5f));
		ImGui::SetCursorPosY((ImGui::GetCursorPosY() - textSize.y * 0.5f));
		ImGui::Text(buff);
	}
} // namespace ImGuiUtils

#endif
```

BCookie961.h:
```cpp
#pragma once
#ifndef BCOOKIE961_H
#define BCOOKIE961_H

#include <atomic>
#include <vector>

class CExitException : public std::exception
{
public:
	CExitException() = default;
	virtual ~CExitException() = default;
};

int bc961_main_file(std::atomic_bool* run_ptr, const std::string_view file);
int bc961_main_shell(std::atomic_bool* run_ptr);

const std::vector<int>& getArray();
const int getPointerLocation();

void setBreakpoint(std::string_view::size_type pos, bool enable);

const char DebuggerVersion[8 + 1] = {
	// First month letter, Oct Nov Dec = '1' otherwise '0'
	(__DATE__[0] == 'O' || __DATE__[0] == 'N' || __DATE__[0] == 'D') ? '1' : '0',

	// Second month letter
	(__DATE__[0] == 'J')   ? ((__DATE__[1] == 'a') ? '1' : // Jan, Jun or Jul
                                ((__DATE__[2] == 'n') ? '6' : '7'))
	: (__DATE__[0] == 'F') ? '2'
						   : // Feb
		(__DATE__[0] == 'M') ? (__DATE__[2] == 'r') ? '3' : '5'
							 : // Mar or May
		(__DATE__[0] == 'A') ? (__DATE__[1] == 'p') ? '4' : '8'
							 : // Apr or Aug
		(__DATE__[0] == 'S') ? '9'
							 : // Sep
		(__DATE__[0] == 'O') ? '0'
							 : // Oct
		(__DATE__[0] == 'N') ? '1'
							 : // Nov
		(__DATE__[0] == 'D') ? '2'
							 : // Dec
		0,

	'.',

	// First day letter, replace space with digit
	__DATE__[4] == ' ' ? '0' : __DATE__[4],

	// Second day letter
	__DATE__[5],

	'.',

	// YY year
	__DATE__[9], __DATE__[10],

	'\0'
};

#endif
```

BCookie961.cpp:
```cpp
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <atomic>
#include <mutex>
#include <stack>
#include <unordered_set>
#include <stdlib.h>
#include <cstdlib>
#include <ctime>
#include <time.h>
#include <windows.h>

#include "BCookie961.h"

/*


UPDATE LOG:

3.2 - Fixed Random Number Generator

3.3 - Comments added!

3.4 - Fixed 6-1 cycles and if constructions!

3.5 - Added P and J commands!

3.6 - Added _(break), x/m[+/-0/1], and G


*/

std::atomic_bool debuggerStep = false;
std::atomic_bool debuggerWait = false;
std::string_view debuggerCurrentCode = "";
std::string_view::size_type debuggerCurrentCodePos = 0;

std::mutex mutex;
std::unordered_set<std::string_view::size_type> debuggerBreakpoints;

std::atomic_bool* runPtr;

std::vector<int> array{0};
int pointerLocation = 0;

const std::vector<int>& getArray() { return array; }

const int getPointerLocation() { return pointerLocation; }

void setBreakpoint(std::string_view::size_type pos, bool enable)
{
	std::lock_guard<std::mutex> lock(mutex);
	if (enable)
		debuggerBreakpoints.insert(pos);
	else
		debuggerBreakpoints.erase(pos);
}

bool endsWith(const std::string_view str, const std::string_view suffix)
{
	if (str.length() < suffix.length()) { return false; }
	return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
}

std::string readFile(const std::string_view fileName)
{
	std::ifstream f(fileName.data());
	if (!f.is_open())
	{
		std::cout << "Error! File not found!" << std::endl;
		exit(0);
	}
	f.seekg(0, std::ios::end);
	size_t size = f.tellg();
	std::string s;
	s.resize(size);
	f.seekg(0);
	f.read(&s[0], size);
	return s;
}

void ifFunc(std::string code);
void arythm(std::string code);

void interpret(std::string code)
{
	int i = 0;
	int c = 0;
	while (i < code.length() && *runPtr)
	{
		/*std::lock_guard<std::mutex> lock(mutex);
		if (debuggerBreakpoints.contains(i))
		{
			debuggerWait = true;
		}*/

		if (debuggerWait)
		{
			debuggerCurrentCode = code;
			debuggerCurrentCodePos = i;
		}

		while (debuggerWait && *runPtr)
		{
			Sleep(25);
			if (debuggerStep) debuggerWait = false;
		}

		if (debuggerStep)
		{
			debuggerStep = false;
			debuggerWait = true;
		}

		if (code[i] == 'i')
		{
			if (pointerLocation > 0) { pointerLocation -= 1; }
		}
		else if (code[i] == 'I')
		{
			if (pointerLocation > 0)
			{
				pointerLocation -= 1;
				array[pointerLocation] = array[pointerLocation + 1];
			}
		}
		else if (code[i] == 'k')
		{
			pointerLocation += 1;
			if (array.size() <= pointerLocation) { array.push_back(0); }
		}
		else if (code[i] == 'K')
		{
			pointerLocation += 1;
			if (array.size() <= pointerLocation) { array.push_back(0); }
			array[pointerLocation] = array[pointerLocation - 1];
		}
		else if (code[i] == 'r')
		{
			std::string flnm;
			std::cout << "File Name: ";
			std::cin >> flnm;
			if (endsWith(flnm, ".bc961")) { interpret(readFile(flnm)); }
			else
			{
				std::cout << "Error! Unknown extension.";
				exit(0);
			}
		}
		else if (code[i] == 'N') { pointerLocation = 0; }
		else if (code[i] == 'P')
		{
			int tmp = pointerLocation;
			pointerLocation = array[pointerLocation];
			if (pointerLocation >= array.size()) { array.resize(pointerLocation + 1, 0); }
			array[pointerLocation] = tmp;
		}
		else if (code[i] == 'J')
		{
			pointerLocation = array[pointerLocation];
			if (pointerLocation >= array.size()) { array.resize(pointerLocation + 1, 0); }
		}
		else if (code[i] == 'n') { std::cout << array[pointerLocation]; }
		else if (code[i] == 'g') { std::cout << pointerLocation; }
		else if (code[i] == 'R') { array[pointerLocation] = rand() % 101; }
		else if (code[i] == 'c') { array[pointerLocation] += 1; }
		else if (code[i] == 'C') { array[pointerLocation] += 10; }
		else if (code[i] == 'o')
		{
			if (array[pointerLocation] > 0) { array[pointerLocation] -= 1; }
		}
		else if (code[i] == '-')
		{
			throw CExitException();
		}
		else if (code[i] == '>') { std::cout << std::endl; }
		else if (code[i] == 'O')
		{
			if (array[pointerLocation] > 10) { array[pointerLocation] -= 10; }
		}
		else if (code[i] == 'L') { array[pointerLocation] = 0; }
		else if (code[i] == '(')
		{
			int open_braces777 = 1;
			int ifend = i + 1;
			std::string to_execute = "";
			while (open_braces777 != 0)
			{
				if (code[ifend] == '(') { open_braces777++; }
				else if (code[ifend] == ')') { open_braces777--; }
				if (open_braces777 != 0) { to_execute += code[ifend]; }
				ifend++;
			}
			i = ifend - 1;
			ifFunc(to_execute);
		}
		/*else if (code[i] == '(') {
			int ifend = i + 1;
			std::string to_execute = "";
			while (code[ifend] != ')') {
				to_execute += code[ifend];
				ifend++;
				i++;
			}
			ifFunc(to_execute);
		}*/
		else if (code[i] == '{')
		{
			int arend = i + 1;
			std::string to_count = "";
			while (code[arend] != '}')
			{
				to_count += code[arend];
				arend++;
				i++;
			}
			arythm(to_count);
		}
		else if (code[i] == 'B')
		{
			if (code[++i] == '[')
			{
				int nigg = i + 1;
				std::string filename = "";
				while (code[nigg] != ']')
				{
					filename += code[nigg];
					nigg++;
					i++;
				}
				interpret(readFile(filename));
			}
			else
			{
				i--;
				std::cout << "Error! File not found!" << std::endl;
			}
		}
		else if (code[i] == 'S')
		{
			if (code[i + 1] == '[')
			{
				int nigge = i + 2;
				std::string times = "";
				while (code[nigge] != ']')
				{
					times += code[nigge];
					nigge++;
					i++;
				}
				Sleep(stoi(times));
			}
		}
		else if (code[i] == '9')
		{
			if (array[pointerLocation] >= 0) { std::cout << char(array[pointerLocation]); }
			else { std::cout << char(0); }
		}
		else if (code[i] == 'a')
		{
			if (array[pointerLocation] >= 0)
			{
				std::cout << array[pointerLocation] << " " << char(array[pointerLocation]) << std::endl;
			}
			else { std::cout << array[pointerLocation] << " " << char(0) << std::endl; }
		}
		else if (code[i] == 'e')
		{
			std::string x;
			std::cin >> x;
			int y;
			try
			{
				y = std::stoi(x);
			}
			catch (std::invalid_argument)
			{
				y = int(x[0]);
			}
			array[pointerLocation] = y;
		}
		else if (code[i] == '6')
		{
			if (array[pointerLocation] == 0)
			{
				int open_braces6 = 1;
				while (open_braces6 > 0)
				{
					i += 1;
					if (code[i] == '6') { open_braces6 += 1; }
					else if (code[i] == '1') { open_braces6 -= 1; }
					else if (code[i] == '[')
					{
						int open_brackets1 = 1;
						while (open_brackets1 > 0)
						{
							i += 1;
							if (code[i] == '[') { open_brackets1 += 1; }
							else if (code[i] == ']') { open_brackets1 -= 1; }
						}
						i += 1;
					}
				}
				i += 1;
			}
		}
		/*else if (code[i] == '6') {
			if (array[pointerLocation] == 0) {
				int open_braces = 1;
				while (open_braces > 0) {
					i += 1;
					if (code[i] == '6') {
						open_braces += 1;
					}
					else if (code[i] == '1') {
						open_braces -= 1;
					}
				}
			}
		}*/
		else if (code[i] == '1')
		{
			int open_braces = 1;
			while (open_braces > 0)
			{
				i -= 1;
				if (code[i] == '6') { open_braces -= 1; }
				else if (code[i] == '1') { open_braces += 1; }
				else if (code[i] == ']')
				{
					int open_brackets1 = 1;
					while (open_brackets1 > 0)
					{
						i -= 1;
						if (code[i] == '[') { open_brackets1 -= 1; }
						else if (code[i] == ']') { open_brackets1 += 1; }
					}
					i -= 1;
				}
			}
			i -= 1;
		}
		/*else if (code[i] == '1') {
			int open_braces = 1;
			while (open_braces > 0) {
				i -= 1;
				if (code[i] == '6') {
					open_braces -= 1;
				}
				else if (code[i] == '1') {
					open_braces += 1;
				}
			}
			i -= 1;
		}*/
		else if (code[i] == 'M')
		{
			if (code[i + 1] == '[')
			{
				int m_start = i + 2;
				int m_end = m_start;
				while (code[m_end] != ']')
				{
					m_end++;
				}
				std::string m_str = code.substr(m_start, m_end - m_start);
				int m = std::stoi(m_str);
				if (pointerLocation + m < 0)
				{
					std::cout << "Error! Pointer Location is negative." << std::endl;
					return;
				}
				else if (pointerLocation + m >= array.size())
				{
					while (array.size() <= pointerLocation + m)
					{
						array.push_back(0);
					}
				}
				int temp = array[pointerLocation];
				array[pointerLocation] = array[pointerLocation + m];
				array[pointerLocation + m] = temp;
				i = m_end;
				pointerLocation += m;
			}
			else
			{
				std::cout << "Error! Invalid syntax for M command." << std::endl;
				return;
			}
		}
		else if (code[i] == 'X')
		{
			if (code[i + 1] == '[')
			{
				int m_start = i + 2;
				int m_end = m_start;
				while (code[m_end] != ']')
				{
					m_end++;
				}
				std::string m_str = code.substr(m_start, m_end - m_start);
				int m = std::stoi(m_str);
				if (pointerLocation + m < 0)
				{
					std::cout << "Error! Pointer Location is negative." << std::endl;
					return;
				}
				else if (pointerLocation + m >= array.size())
				{
					while (array.size() <= pointerLocation + m)
					{
						array.push_back(0);
					}
				}
				array[pointerLocation + m] = array[pointerLocation];
				i = m_end;
				pointerLocation += m;
			}
			else
			{
				std::cout << "Error! Invalid syntax for M command." << std::endl;
				return;
			}
		}
		else if (code[i] == '/' && (i + 1 < code.length()) && code[i + 1] == '*')
		{
			i += 2;
			while (i < code.length() - 1 && !(code[i] == '*' && code[i + 1] == '/'))
			{
				i++;
			}
			i--;
			if (i < code.length() - 1) { i += 2; }
		}
		else if (code[i] == '_') { return; }
		else if (code[i] == 'x' && i + 4 < code.length() && code[i + 1] == '[' &&
				 (code[i + 2] == '+' || code[i + 2] == '-') && (code[i + 3] == '0' || code[i + 3] == '1') &&
				 code[i + 4] == ']')
		{
			int target_index = 0;
			if (code[i + 2] == '+') { target_index = array[pointerLocation + 1]; }
			else if (code[i + 2] == '-')
			{
				if (pointerLocation == 0)
				{
					std::cout << "Error! No left cell available." << std::endl;
					return;
				}
				target_index = array[pointerLocation - 1];
			}

			if (target_index < 0)
			{
				std::cout << "Error! Invalid target index." << std::endl;
				return;
			}

			if (array.size() <= target_index) { array.resize(target_index + 1, 0); }

			array[target_index] = array[pointerLocation];

			if (code[i + 3] == '1') { pointerLocation = target_index; }

			i += 4;
		}
		else if (code[i] == 'm' && i + 4 < code.length() && code[i + 1] == '[' &&
				 (code[i + 2] == '+' || code[i + 2] == '-') && (code[i + 3] == '0' || code[i + 3] == '1') &&
				 code[i + 4] == ']')
		{
			int target_index = 0;
			if (code[i + 2] == '+') { target_index = array[pointerLocation + 1]; }
			else if (code[i + 2] == '-')
			{
				if (pointerLocation == 0)
				{
					std::cout << "Error! No left cell available." << std::endl;
					return;
				}
				target_index = array[pointerLocation - 1];
			}

			if (target_index < 0)
			{
				std::cout << "Error! Invalid target index." << std::endl;
				return;
			}

			if (array.size() <= target_index) { array.resize(target_index + 1, 0); }

			array[target_index] = array[pointerLocation];
			array[pointerLocation] = 0;

			if (code[i + 3] == '1') { pointerLocation = target_index; }

			i += 4;
		}
		else if (code[i] == 'G') { array[pointerLocation] = pointerLocation; }
		i += 1;
	}

	debuggerCurrentCode = "";
	debuggerCurrentCodePos = 0;
}

void arythm(std::string code)
{
	int nums[1024];
	std::vector<int> actions;
	int pointnow = 0;
	bool actyes = false;

	for (int i = 0; i < code.length(); i++)
	{
		if (code[i] == 'k')
		{
			nums[pointnow] = array[pointerLocation + 1];
			pointnow += 1;
		}
		else if (code[i] == 'i')
		{
			nums[pointnow] = array[pointerLocation - 1];
			pointnow += 1;
		}
		else if (code[i] == 't')
		{
			nums[pointnow] = array[pointerLocation];
			pointnow += 1;
		}
		else if (code[i] == '+')
		{
			actions.push_back(1);
			actyes = true;
		}
		else if (code[i] == '-')
		{
			actions.push_back(0);
			actyes = true;
		}
		else if (code[i] == '*')
		{
			actions.push_back(2);
			actyes = true;
		}
		else if (code[i] == '%')
		{
			actions.push_back(3);
			actyes = true;
		}
	}

	if (actions[0] == 0) { array[pointerLocation] = nums[0] - nums[1]; }
	else if (actions[0] == 1) { array[pointerLocation] = nums[0] + nums[1]; }
	else if (actions[0] == 2) { array[pointerLocation] = nums[0] * nums[1]; }
	else if (actions[0] == 3) { array[pointerLocation] = nums[0] / nums[1]; }
	else
	{
		std::cout << "ERROR! Action not found!";
		exit(0);
	}
}

void ifFunc(std::string code)
{
	int nums[2];
	int action = 0;
	int pointnow = 0;
	bool ends = false;
	std::string execute = "";
	for (int i = 0; i < code.length(); i++)
	{
		if (code[i] == 'i')
		{
			nums[pointnow] = array[pointerLocation - 1];
			pointnow += 1;
		}
		else if (code[i] == 'k')
		{
			nums[pointnow] = array[pointerLocation + 1];
			pointnow += 1;
		}
		else if (code[i] == 't')
		{
			nums[pointnow] = array[pointerLocation];
			pointnow += 1;
		}
		else if (code[i] == '>') { action = 1; }
		else if (code[i] == '<') { action = 2; }
		else if (code[i] == '=') { action = 0; }
		else if (code[i] == '~') { action = 3; }
		else if (code[i] == '!')
		{
			execute = code.substr(i + 1, code.length());
			bool anif1 = false;
			bool anif2 = false;
			for (int p = 0; p < execute.length(); p++)
			{
				if (execute[p] == '(')
				{
					anif1 = true;
					for (int j = 0; j < execute.length(); j++)
					{
						if (execute[j] == ')') { anif2 = true; }
					}
				}
			}
			if (anif1 == true && anif2 == false) { execute += ')'; }
			ends = true;
			break;
		}
	}
	if (ends == true)
	{
		if (action == 0)
		{
			if (nums[0] == nums[1]) { interpret(execute); }
		}
		else if (action == 1)
		{
			if (nums[0] > nums[1]) { interpret(execute); }
		}
		else if (action == 2)
		{
			if (nums[0] < nums[1]) { interpret(execute); }
		}
		else if (action == 3)
		{
			if (nums[0] != nums[1]) { interpret(execute); }
		}
	}
	else { std::cout << "Error! If without body!" << std::endl; }
}

void ExceptionHandler(unsigned int, struct _EXCEPTION_POINTERS* ep)
{
	std::string reasonStr;
#define EXCEPTION_NAME(x)                                                                                              \
	case x:                                                                                                            \
		reasonStr = #x;                                                                                                \
		break

	switch (ep->ExceptionRecord->ExceptionCode)
	{
		EXCEPTION_NAME(EXCEPTION_ACCESS_VIOLATION);
		EXCEPTION_NAME(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
		EXCEPTION_NAME(EXCEPTION_BREAKPOINT);
		EXCEPTION_NAME(EXCEPTION_DATATYPE_MISALIGNMENT);
		EXCEPTION_NAME(EXCEPTION_FLT_DENORMAL_OPERAND);
		EXCEPTION_NAME(EXCEPTION_FLT_DIVIDE_BY_ZERO);
		EXCEPTION_NAME(EXCEPTION_FLT_INEXACT_RESULT);
		EXCEPTION_NAME(EXCEPTION_FLT_INVALID_OPERATION);
		EXCEPTION_NAME(EXCEPTION_FLT_OVERFLOW);
		EXCEPTION_NAME(EXCEPTION_FLT_STACK_CHECK);
		EXCEPTION_NAME(EXCEPTION_FLT_UNDERFLOW);
		EXCEPTION_NAME(EXCEPTION_ILLEGAL_INSTRUCTION);
		EXCEPTION_NAME(EXCEPTION_IN_PAGE_ERROR);
		EXCEPTION_NAME(EXCEPTION_INT_DIVIDE_BY_ZERO);
		EXCEPTION_NAME(EXCEPTION_INT_OVERFLOW);
		EXCEPTION_NAME(EXCEPTION_INVALID_DISPOSITION);
		EXCEPTION_NAME(EXCEPTION_NONCONTINUABLE_EXCEPTION);
		EXCEPTION_NAME(EXCEPTION_PRIV_INSTRUCTION);
		EXCEPTION_NAME(EXCEPTION_SINGLE_STEP);
		EXCEPTION_NAME(EXCEPTION_STACK_OVERFLOW);
		EXCEPTION_NAME(CONTROL_C_EXIT);
		default:
			reasonStr += "UNKNOWN!";
			break;
	}
#undef EXCEPTION_NAME

	throw std::runtime_error(reasonStr);
}

const std::string label = "Welcome to Better Cookie961 language Compiler v3.6 (Debugger version)";

int bc961_main_file(std::atomic_bool* run_ptr, const std::string_view filename)
{
	debuggerStep = false;
	debuggerWait = false;

	array = {0};
	pointerLocation = 0;

	runPtr = run_ptr;

	_set_se_translator(ExceptionHandler);

	srand(time(NULL));

	std::cout << label << std::endl;
	std::cout << " " << std::endl;

	if (endsWith(filename, ".bc961"))
	{
		const std::string foilData = readFile(filename);
		interpret(foilData);
		std::cout << " " << std::endl;
	}
	else
	{
		std::cout << "Error! Unknown extension.";
		return 0;
	}

	return 0;
}

int bc961_main_shell(std::atomic_bool* run_ptr)
{
	debuggerStep = false;
	debuggerWait = false;

	array = {0};
	pointerLocation = 0;

	runPtr = run_ptr;

	_set_se_translator(ExceptionHandler);

	srand(time(NULL));

	std::cout << label << std::endl;
	std::cout << " " << std::endl;
	int nig = 0;
	while (nig != 1)
	{
		std::string code;
		std::cout << "Code: ";
		std::getline(std::cin, code);
		interpret(code);
		std::cout << " " << std::endl;
		nig += 1;
	}

	return 0;
}
```

Task: fix all bugs with threads and restructurize this app.