This commit is contained in:
Andre Wagner
2026-04-30 09:38:43 -05:00
parent 5843a19b2f
commit 50b55eaeef
4 changed files with 58 additions and 1 deletions

View File

@@ -5,6 +5,7 @@
#include "../bytecode/bytecode.hh" #include "../bytecode/bytecode.hh"
#include "code.hh" #include "code.hh"
#include "stack.hh" #include "stack.hh"
#include "vm.hh"
using namespace tyche; using namespace tyche;
@@ -68,6 +69,27 @@ TEST(Stack, FramePointer)
ASSERT_EQ(stack.at(-2).as_integer(), 10); ASSERT_EQ(stack.at(-2).as_integer(), 10);
} }
TEST(VM, BasicCode)
{
// code (2+3)
BytecodePrototype bp;
bp.functions.emplace_back(0, 0);
bp.functions.at(0).code.append_byte((uint8_t) Instruction::PushInt8);
bp.functions.at(0).code.append_int8(2);
bp.functions.at(0).code.append_byte((uint8_t) Instruction::PushInt8);
bp.functions.at(0).code.append_int8(3);
bp.functions.at(0).code.append_byte((uint8_t) Instruction::Sum);
bp.functions.at(0).code.append_byte((uint8_t) Instruction::Return);
ByteArray ba = Bytecode::generate(bp);
VM vm;
vm.load_bytecode(std::move(ba));
vm.call(0);
int32_t result = vm.to_integer(-1);
ASSERT_EQ(result, 5);
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
testing::InitGoogleTest(&argc, argv); testing::InitGoogleTest(&argc, argv);

View File

@@ -25,6 +25,18 @@ void VM::call(size_t n_params)
loc_.pop(); loc_.pop();
} }
int32_t VM::to_integer(int index) const
{
Value i = stack_.at(index);
assert_type(i, Type::Integer);
return i.as_integer();
}
void VM::push_integer(int32_t value)
{
stack_.push(Value::CreateInteger(value));
}
void VM::run_until_return() void VM::run_until_return()
{ {
size_t level = stack_.fp_level(); size_t level = stack_.fp_level();
@@ -37,9 +49,21 @@ void VM::step()
{ {
Operation op = code_.operation(loc_.top()); Operation op = code_.operation(loc_.top());
switch (op.instruction) { switch (op.instruction) {
// TODO case Instruction::PushInt8:
case Instruction::PushInt16:
case Instruction::PushInt32:
push_integer(op.operator_);
break;
default:
throw VMInvalidOpcode((uint8_t) op.instruction);
} }
loc_.top() = op.next_location; loc_.top() = op.next_location;
} }
void VM::assert_type(Value const& val, Type type)
{
if (val.type() != type)
throw VMTypeError(type, val.type());
}
} // tyche } // tyche

View File

@@ -13,10 +13,16 @@ public:
void call(size_t n_params); void call(size_t n_params);
[[nodiscard]] int32_t to_integer(int index) const;
void push_integer(int32_t value);
private: private:
void run_until_return(); void run_until_return();
void step(); void step();
static void assert_type(Value const& val, Type type);
Stack stack_; Stack stack_;
Code code_; Code code_;
std::stack<Location> loc_; std::stack<Location> loc_;

View File

@@ -30,6 +30,11 @@ public:
explicit VMTypeError(Type expected, Type found) : VMRuntimeError("Type error") {} // TODO - print types explicit VMTypeError(Type expected, Type found) : VMRuntimeError("Type error") {} // TODO - print types
}; };
class VMInvalidOpcode : public VMRuntimeError
{
public:
explicit VMInvalidOpcode(uint8_t opcode) : VMRuntimeError("Invalid opcode " + std::to_string(opcode)) {}
};
} }