diff --git a/src/vm/tests.cc b/src/vm/tests.cc index 0f92135..47b29fe 100644 --- a/src/vm/tests.cc +++ b/src/vm/tests.cc @@ -5,6 +5,7 @@ #include "../bytecode/bytecode.hh" #include "code.hh" #include "stack.hh" +#include "vm.hh" using namespace tyche; @@ -68,6 +69,27 @@ TEST(Stack, FramePointer) 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) { testing::InitGoogleTest(&argc, argv); diff --git a/src/vm/vm.cc b/src/vm/vm.cc index 4874fd5..18c4ed9 100644 --- a/src/vm/vm.cc +++ b/src/vm/vm.cc @@ -25,6 +25,18 @@ void VM::call(size_t n_params) 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() { size_t level = stack_.fp_level(); @@ -37,9 +49,21 @@ void VM::step() { Operation op = code_.operation(loc_.top()); 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; } +void VM::assert_type(Value const& val, Type type) +{ + if (val.type() != type) + throw VMTypeError(type, val.type()); +} + } // tyche diff --git a/src/vm/vm.hh b/src/vm/vm.hh index 76f49b9..ef8554b 100644 --- a/src/vm/vm.hh +++ b/src/vm/vm.hh @@ -13,10 +13,16 @@ public: void call(size_t n_params); + [[nodiscard]] int32_t to_integer(int index) const; + + void push_integer(int32_t value); + private: void run_until_return(); void step(); + static void assert_type(Value const& val, Type type); + Stack stack_; Code code_; std::stack loc_; diff --git a/src/vm/vm_exceptions.hh b/src/vm/vm_exceptions.hh index 7bebf3c..d20eac5 100644 --- a/src/vm/vm_exceptions.hh +++ b/src/vm/vm_exceptions.hh @@ -30,6 +30,11 @@ public: 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)) {} +}; }