#include "runtime.hpp" #include #include #include namespace Interpreter { Runtime::Runtime() : mContext(nullptr) , mCode(nullptr) , mCodeSize(0) , mPC(0) { } int Runtime::getPC() const { return mPC; } int Runtime::getIntegerLiteral(int index) const { if (index < 0 || index >= static_cast(mCode[1])) throw std::out_of_range("out of range"); const Type_Code* literalBlock = mCode + 4 + mCode[0]; return *reinterpret_cast(&literalBlock[index]); } float Runtime::getFloatLiteral(int index) const { if (index < 0 || index >= static_cast(mCode[2])) throw std::out_of_range("out of range"); const Type_Code* literalBlock = mCode + 4 + mCode[0] + mCode[1]; return *reinterpret_cast(&literalBlock[index]); } std::string_view Runtime::getStringLiteral(int index) const { if (index < 0 || static_cast(mCode[3]) <= 0) throw std::out_of_range("out of range"); const char* literalBlock = reinterpret_cast(mCode + 4 + mCode[0] + mCode[1] + mCode[2]); size_t offset = 0; for (; index; --index) { offset += std::strlen(literalBlock + offset) + 1; if (offset / 4 >= mCode[3]) throw std::out_of_range("out of range"); } return literalBlock + offset; } void Runtime::configure(const Type_Code* code, int codeSize, Context& context) { clear(); mContext = &context; mCode = code; mCodeSize = codeSize; mPC = 0; } void Runtime::clear() { mContext = nullptr; mCode = nullptr; mCodeSize = 0; mStack.clear(); } void Runtime::setPC(int PC) { mPC = PC; } void Runtime::push(const Data& data) { mStack.push_back(data); } void Runtime::push(Type_Integer value) { Data data; data.mInteger = value; push(data); } void Runtime::push(Type_Float value) { Data data; data.mFloat = value; push(data); } void Runtime::pop() { if (mStack.empty()) throw std::runtime_error("stack underflow"); mStack.pop_back(); } Data& Runtime::operator[](int Index) { if (Index < 0 || Index >= static_cast(mStack.size())) throw std::runtime_error("stack index out of range"); return mStack[mStack.size() - Index - 1]; } Context& Runtime::getContext() { assert(mContext); return *mContext; } }