diff --git a/src/engine/virtualmachine_p.cpp b/src/engine/virtualmachine_p.cpp index f3af91d8..d6c93591 100644 --- a/src/engine/virtualmachine_p.cpp +++ b/src/engine/virtualmachine_p.cpp @@ -228,10 +228,9 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) atEnd = true; return pos; } else { - if (callTree.size() == 1) - warp = false; - - pos = callTree.back(); + const auto &oldState = callTree.back(); + pos = oldState.first; + warp = oldState.second; callTree.pop_back(); procedureArgTree.pop_back(); if (procedureArgTree.empty()) @@ -797,7 +796,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset) unsigned int *procedurePos = procedures[pos[1]]; if (procedurePos) { - callTree.push_back(++pos); + callTree.push_back({ ++pos, warp }); procedureArgs = nextProcedureArgs; nextProcedureArgs = nullptr; pos = procedurePos; diff --git a/src/engine/virtualmachine_p.h b/src/engine/virtualmachine_p.h index 173db80e..7b1f1c6c 100644 --- a/src/engine/virtualmachine_p.h +++ b/src/engine/virtualmachine_p.h @@ -46,7 +46,7 @@ struct VirtualMachinePrivate bool running = false; bool atEnd = false; std::vector loops; - std::vector callTree; + std::vector> callTree; std::vector> procedureArgTree; std::vector *procedureArgs = nullptr; std::vector *nextProcedureArgs = nullptr; diff --git a/test/virtual_machine/virtual_machine_test.cpp b/test/virtual_machine/virtual_machine_test.cpp index 0f702476..27819ba2 100644 --- a/test/virtual_machine/virtual_machine_test.cpp +++ b/test/virtual_machine/virtual_machine_test.cpp @@ -1466,6 +1466,27 @@ TEST(VirtualMachineTest, RunProcedures) ASSERT_EQ(vm.registerCount(), 0); } +TEST(VirtualMachineTest, RunNestedWarpProcedures) +{ + static unsigned int bytecode[] = { OP_START, OP_INIT_PROCEDURE, OP_CALL_PROCEDURE, 0, OP_HALT }; + static unsigned int procedure1[] = { OP_START, OP_INIT_PROCEDURE, OP_CALL_PROCEDURE, 1, OP_CONST, 0, OP_REPEAT_LOOP, OP_BREAK_FRAME, OP_LOOP_END, OP_HALT }; + static unsigned int procedure2[] = { OP_START, OP_WARP, OP_CONST, 0, OP_REPEAT_LOOP, OP_BREAK_FRAME, OP_LOOP_END, OP_HALT }; + static unsigned int *procedures[] = { procedure1, procedure2 }; + static Value constValues[] = { 1 }; + + VirtualMachine vm; + vm.setBytecode(bytecode); + vm.setProcedures(procedures); + vm.setConstValues(constValues); + vm.run(); + ASSERT_FALSE(vm.atEnd()); // the procedure should still run in warp mode even after running a warp procedure (#470) + ASSERT_EQ(vm.registerCount(), 0); + + vm.run(); + ASSERT_TRUE(vm.atEnd()); + ASSERT_EQ(vm.registerCount(), 0); +} + TEST(VirtualMachineTest, RunUndefinedProcedure) { static unsigned int bytecode[] = {