diff --git a/src/vm/stack.cc b/src/vm/stack.cc index b9240e7..4497843 100644 --- a/src/vm/stack.cc +++ b/src/vm/stack.cc @@ -47,6 +47,21 @@ Value Stack::at(int pos) const } } +void Stack::set(int pos, Value const& val) +{ + try { + if (pos >= 0) { + stack_.at(fps_.top() + pos) = val; + } else { + if ((int) fps_.top() + (int) stack_.size() + pos < 0) + throw VMStackOutOfRange(); + stack_.at(stack_.size() + pos) = val; + } + } catch (std::out_of_range&) { + throw VMStackOutOfRange(); + } +} + size_t Stack::size() const { return stack_.size() - fps_.top(); diff --git a/src/vm/stack.hh b/src/vm/stack.hh index b17fcd1..53d99be 100644 --- a/src/vm/stack.hh +++ b/src/vm/stack.hh @@ -19,6 +19,8 @@ public: [[nodiscard]] Value at(int pos) const; [[nodiscard]] size_t size() const; + void set(int pos, Value const& val); + void push_fp(); void pop_fp(); diff --git a/src/vm/tests.cc b/src/vm/tests.cc index 8ef8dd7..23ed175 100644 --- a/src/vm/tests.cc +++ b/src/vm/tests.cc @@ -270,15 +270,19 @@ TEST(VM, StringString) TEST(VM, LocalVariables) { - /* - ASSERT_EQ(run(R"( + VM vm = run(R"( .func 0 - pushv 2 - pushi 3 - setv 0 - pushi - )").to_integer(-1), 4); - */ + pushv 2 ; local a, b + pushi 3 ; a = 3 + set 0 + pushi 4 ; b = 4 + set 1 + dupv 0 ; return a + ret + )"); + + ASSERT_EQ(vm.stack_sz(), 1); + ASSERT_EQ(vm.to_integer(-1), 3); } int main(int argc, char** argv) diff --git a/src/vm/vm.cc b/src/vm/vm.cc index d3408dd..ab8ac99 100644 --- a/src/vm/vm.cc +++ b/src/vm/vm.cc @@ -131,6 +131,33 @@ void VM::step() stack_.push(stack_.peek()); break; + // + // variables + // + + case Instruction::PushValues8: + case Instruction::PushValues16: + case Instruction::PushValues32: + for (int i = 0; i < op.operator_; ++i) + push_nil(); + break; + + case Instruction::SetValue8: + case Instruction::SetValue16: + case Instruction::SetValue32: { + Value a = stack_.pop(); + stack_.set(op.operator_, a); + break; + } + + case Instruction::DuplicateValue8: + case Instruction::DuplicateValue16: + case Instruction::DuplicateValue32: { + Value a = stack_.at(op.operator_); + stack_.push(a); + break; + } + // // logical/arithmetic // diff --git a/src/vm/vm.hh b/src/vm/vm.hh index 4477e41..4367df6 100644 --- a/src/vm/vm.hh +++ b/src/vm/vm.hh @@ -33,7 +33,7 @@ public: [[nodiscard]] float to_float(int index) const; [[nodiscard]] std::string to_string(int index) const; - [[nodiscard]] std::string debug_stack() const { return stack_.debug(); } + [[nodiscard]] std::string debug_stack() const { return stack_.debug(); } private: void run_until_return();