diff --git a/JSImpl/test/sprtTests.cpp b/JSImpl/test/sprtTests.cpp index 25b7665b..b64f8c44 100644 --- a/JSImpl/test/sprtTests.cpp +++ b/JSImpl/test/sprtTests.cpp @@ -423,3 +423,17 @@ TEST_F(SPASMTest, StringEscapeD) CompileAndRun(program); ASSERT_EQ(Output.str(), "the answer\\\" is 42"); } + + +TEST_F(SPASMTest, DataStackResize) +{ + const char* program = + "00: push 1025" "\n" + "01: push 15000" "\n" + "02: const 16025 123""\n" + "03: print 16025" "\n" + "" + ; + CompileAndRun(program); + ASSERT_EQ(Output.str(), "123"); +} \ No newline at end of file diff --git a/spasm/src/spasm.cpp b/spasm/src/spasm.cpp index 6a62c905..3540a589 100644 --- a/spasm/src/spasm.cpp +++ b/spasm/src/spasm.cpp @@ -75,7 +75,15 @@ Spasm::RunResult Spasm::run() case OpCodes::Push: { const auto count = PC_t(read_reg(size)); - assert(m_SP + count <= &data_stack[data_stack.size() - 1]); + if(!(m_SP + count <= &data_stack[data_stack.size() - 1])) + { + float resizeCoeff = 2.f; + if (count > data_stack.size()) + { + resizeCoeff = float(ceil(count / data_stack.size()) + 1); + } + resizeDataStack(resizeCoeff); + } std::fill(m_SP, m_SP + count, data_t{}); m_SP += count; break; @@ -236,6 +244,25 @@ Spasm::RunResult Spasm::run() return RunResult::Success; } +/*! +** Resizes the data stack. m_FP and m_SP are updated. +*/ +void Spasm::resizeDataStack(float resizeCoefficient) +{ + data_t* stackStart = &(data_stack[0]); + size_t fpOffset = m_FP - stackStart; + size_t spOffset = m_SP - stackStart; + + size_t currentSize = data_stack.size(); + size_t newSize = size_t(currentSize * resizeCoefficient); + data_stack.resize(newSize); + + stackStart = &(data_stack[0]); + m_FP = stackStart + fpOffset; + m_SP = stackStart + spOffset; +} + + /*! ** Pushes the next data_t object on the data stack */ @@ -449,7 +476,10 @@ data_t Spasm::get_local(reg_t reg) void Spasm::set_local(reg_t reg, data_t data) { assert(&data_stack[0] <= (m_FP + reg)); - assert((m_FP + reg) < &data_stack[data_stack.size() - 1]); + if(!((m_FP + reg) < &data_stack[data_stack.size() - 1])) + { + resizeDataStack(); + } m_FP[reg] = data; } @@ -462,7 +492,10 @@ data_t Spasm::pop_data() void Spasm::push_data(data_t data) { - assert(m_SP < &data_stack[data_stack.size() - 1]); + if(!(m_SP < &data_stack[data_stack.size() - 1])) + { + resizeDataStack(); + } *(m_SP++) = data; } diff --git a/spasm/src/spasm_impl.hpp b/spasm/src/spasm_impl.hpp index 04e809a0..ce20774b 100644 --- a/spasm/src/spasm_impl.hpp +++ b/spasm/src/spasm_impl.hpp @@ -115,9 +115,11 @@ class Spasm //! Input stream for read () operation std::istream* istr; - //! Output stream for print () opertion + //! Output stream for print () operation std::ostream* ostr; + void resizeDataStack(float resizeCoefficient = 2.f); + void push(reg_t reg); void popto(reg_t reg); void dup();