Files
forklang/furvm/src/executor.cpp
T

86 lines
2.3 KiB
C++

#include "furvm/executor.hpp"
#include "furvm/context.hpp" // IWYU pragma: keep
#include "furvm/instruction.hpp"
#include "furvm/thing.hpp"
#include <stdexcept>
namespace furvm {
executor::executor(egzekutor, executor_handle id, const context_p& context)
: m_id(id), m_context(context) {}
executor::~executor() {
m_context->m_executors[m_id] = nullptr;
}
executor_p executor::create(const context_p& context) {
auto ex = std::make_shared<executor>(egzekutor{}, context->m_executors.size(), context);
context->m_executors.push_back(ex);
return std::move(ex);
}
void executor::push_frame(const mod_p& mod, std::size_t position) {
m_frames.emplace((struct executor::frame){ mod, position, m_stack.size() });
}
struct executor::frame executor::pop_frame() {
struct executor::frame frame = m_frames.top();
m_frames.pop();
return frame;
}
struct executor::frame executor::frame() const {
return m_frames.top();
}
void executor::push_thing(const thing_p& thing) {
m_stack.push(thing);
}
thing_p executor::pop_thing() {
if (m_frames.top().stackBase >= m_stack.size()) return {};
thing_p top = std::move(m_stack.top());
m_stack.pop();
return top;
}
thing_p executor::thing() const {
if (m_frames.top().stackBase >= m_stack.size()) return {};
return m_stack.top();
}
void executor::step() {
if ((m_flags & executor_flags::Suspended) == executor_flags::Suspended) return;
struct frame& frame = m_frames.top();
instruction_t instr = static_cast<instruction_t>(frame.mod->byte(frame.position++));
switch (instr) {
case instruction_t::NoOperation: break;
case instruction_t::PushB2I: {
auto thing = thing::create(m_context, thing_t::Int32);
thing->int32() = frame.mod->byte(frame.position++);
m_stack.push(std::move(thing));
} break;
case instruction_t::Drop: {
m_stack.pop();
} break;
case instruction_t::Return: {
pop_frame();
if (m_frames.empty()) m_flags = m_flags | executor_flags::Done;
} break;
case instruction_t::ReturnValue: {
auto value = pop_thing();
pop_frame();
m_stack.push(std::move(value));
} break;
case instruction_t::PushConstant:
case instruction_t::Duplicate: {
throw std::runtime_error("unimplemented");
}
}
}
} // namespace furvm