87 lines
1.6 KiB
C++
87 lines
1.6 KiB
C++
|
#include "VM.hpp"
|
||
|
#include "Value.hpp"
|
||
|
#include "lib/opcodes.hpp"
|
||
|
|
||
|
namespace sk
|
||
|
{
|
||
|
/*explicit*/ VM::VM()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/*virtual*/ VM::~VM()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
std::string VM::string() const
|
||
|
{
|
||
|
std::stringstream ss;
|
||
|
|
||
|
ss << "--- constants ---" << "\n";
|
||
|
for (size_t i=0; i<m_frames.back().program->value_size(); i++)
|
||
|
{
|
||
|
ss << i << "\t" << m_frames.back().program->value(i)->string()
|
||
|
<< "\n";
|
||
|
}
|
||
|
|
||
|
ss << "--- stack ---" << "\n";
|
||
|
|
||
|
for (size_t i=0; i<m_stack.size(); i++)
|
||
|
{
|
||
|
ss << i << "\t" << m_stack[i] << "\n";
|
||
|
}
|
||
|
|
||
|
return ss.str();
|
||
|
}
|
||
|
|
||
|
void VM::exec(std::shared_ptr<Program> program)
|
||
|
{
|
||
|
Frame frame;
|
||
|
frame.program = program;
|
||
|
m_frames.push_back(frame);
|
||
|
m_pc = 0;
|
||
|
|
||
|
exec();
|
||
|
}
|
||
|
|
||
|
void VM::exec()
|
||
|
{
|
||
|
while (m_pc < program()->size())
|
||
|
{
|
||
|
Instr instr = program()->instr(m_pc);
|
||
|
|
||
|
switch (instr.opcode)
|
||
|
{
|
||
|
|
||
|
case OPCODE_PUSH_CONST: {
|
||
|
push(*instr.param);
|
||
|
m_pc++;
|
||
|
} break;
|
||
|
|
||
|
default:
|
||
|
throw std::runtime_error {std::string()
|
||
|
+ "vm cannot execute unknown opcode '"
|
||
|
+ OpcodeTypeStr[instr.opcode]
|
||
|
+ "'"};
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<Program> VM::program() const
|
||
|
{
|
||
|
return m_frames.back().program;
|
||
|
}
|
||
|
|
||
|
void VM::push(param_t param)
|
||
|
{
|
||
|
m_stack.push_back(param);
|
||
|
}
|
||
|
|
||
|
param_t VM::pop()
|
||
|
{
|
||
|
assert(m_stack.empty() == false);
|
||
|
auto param = m_stack.back();
|
||
|
m_stack.pop_back();
|
||
|
return param;
|
||
|
}
|
||
|
}
|