Skip to content

Commit e5500ee

Browse files
authored
Merge pull request #143 from scratchcpp/virtualmachine_test
Complete VirtualMachine test
2 parents f15e012 + 6be2f04 commit e5500ee

File tree

6 files changed

+946
-29
lines changed

6 files changed

+946
-29
lines changed

include/scratchcpp/virtualmachine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
109109

110110
unsigned int *bytecode() const;
111111

112+
size_t registerCount() const;
113+
112114
Target *target() const;
113115
IEngine *engine() const;
114116
Script *script() const;

src/engine/virtualmachine.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ unsigned int *VirtualMachine::bytecode() const
6969
return impl->bytecode;
7070
}
7171

72+
/*! Returns number of currently used registers. */
73+
size_t VirtualMachine::registerCount() const
74+
{
75+
return impl->regCount;
76+
}
77+
7278
/*! Returns the Target the VM belongs to. */
7379
Target *VirtualMachine::target() const
7480
{
@@ -99,7 +105,13 @@ void VirtualMachine::addReturnValue(const Value &v)
99105
*impl->regs[impl->regCount++] = v;
100106
}
101107

102-
/*! Replaces the given register (last register minus offset). */
108+
/*!
109+
* Replaces the given register. For example:
110+
* \code
111+
* replaceReturnValue("...", 1) // write to last register
112+
* replaceReturnValue("...", 2) // write to second last register
113+
* \endcode
114+
*/
103115
void VirtualMachine::replaceReturnValue(const Value &v, unsigned int offset)
104116
{
105117
*impl->regs[impl->regCount - offset] = v;

src/engine/virtualmachine_p.cpp

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ VirtualMachinePrivate::~VirtualMachinePrivate()
115115
delete regs;
116116
}
117117

118-
unsigned int *VirtualMachinePrivate::run(unsigned int *pos)
118+
unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset)
119119
{
120120
static const void *dispatch_table[] = {
121121
nullptr,
@@ -186,9 +186,11 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos)
186186
unsigned int *loopStart;
187187
unsigned int *loopEnd;
188188
size_t loopCount;
189-
atEnd = false;
190-
atomic = true;
191-
warp = false;
189+
if (reset) {
190+
atEnd = false;
191+
atomic = true;
192+
warp = false;
193+
}
192194
DISPATCH();
193195

194196
do_halt:
@@ -279,7 +281,7 @@ do_repeat_loop_index1 : {
279281
}
280282

281283
do_until_loop:
282-
loopStart = run(pos);
284+
loopStart = run(pos, false);
283285
if (!READ_LAST_REG()->toBool()) {
284286
Loop l;
285287
l.isRepeatLoop = false;
@@ -314,7 +316,7 @@ do_loop_end : {
314316
engine->breakFrame();
315317
return pos - 1;
316318
}
317-
loopStart = run(l.start);
319+
loopStart = run(l.start, false);
318320
if (!READ_LAST_REG()->toBool())
319321
pos = loopStart;
320322
else
@@ -330,31 +332,26 @@ do_loop_end : {
330332
DISPATCH();
331333

332334
do_add:
333-
REPLACE_RET_VALUE(*READ_REG(0, 2), 2);
334335
READ_REG(0, 2)->add(*READ_REG(1, 2));
335336
FREE_REGS(1);
336337
DISPATCH();
337338

338339
do_subtract:
339-
REPLACE_RET_VALUE(*READ_REG(0, 2), 2);
340340
READ_REG(0, 2)->subtract(*READ_REG(1, 2));
341341
FREE_REGS(1);
342342
DISPATCH();
343343

344344
do_multiply:
345-
REPLACE_RET_VALUE(*READ_REG(0, 2), 2);
346345
READ_REG(0, 2)->multiply(*READ_REG(1, 2));
347346
FREE_REGS(1);
348347
DISPATCH();
349348

350349
do_divide:
351-
REPLACE_RET_VALUE(*READ_REG(0, 2), 2);
352350
READ_REG(0, 2)->divide(*READ_REG(1, 2));
353351
FREE_REGS(1);
354352
DISPATCH();
355353

356354
do_mod:
357-
REPLACE_RET_VALUE(*READ_REG(0, 2), 2);
358355
READ_REG(0, 2)->mod(*READ_REG(1, 2));
359356
FREE_REGS(1);
360357
DISPATCH();
@@ -651,10 +648,16 @@ do_list_get_item : {
651648
FREE_REGS(1);
652649
DISPATCH();
653650

654-
do_str_at:
655-
REPLACE_RET_VALUE(READ_REG(0, 2)->toUtf16()[READ_REG(1, 2)->toLong()], 2);
651+
do_str_at : {
652+
size_t index = READ_REG(1, 2)->toLong() - 1;
653+
std::u16string str = READ_REG(0, 2)->toUtf16();
654+
if (index < 0 || index >= str.size())
655+
REPLACE_RET_VALUE("", 2);
656+
else
657+
REPLACE_RET_VALUE(utf8::utf16to8(std::u16string({ str[index] })), 2);
656658
FREE_REGS(1);
657659
DISPATCH();
660+
}
658661

659662
do_str_length:
660663
REPLACE_RET_VALUE(static_cast<long>(READ_REG(0, 1)->toUtf16().size()), 1);
@@ -668,7 +671,7 @@ do_list_get_item : {
668671
do_exec : {
669672
auto ret = functions[*++pos](vm);
670673
if (updatePos) {
671-
pos = pos;
674+
pos = this->pos;
672675
updatePos = false;
673676
}
674677
if (stop) {
@@ -677,17 +680,16 @@ do_exec : {
677680
procedureArgTree.clear();
678681
procedureArgs = nullptr;
679682
nextProcedureArgs = nullptr;
680-
if (!atomic && !warp)
683+
if (!atomic)
681684
engine->breakFrame();
682685
if (goBack) {
683686
goBack = false;
684687
pos -= instruction_arg_count[OP_EXEC] + 1;
688+
// NOTE: Going back leaks all registers for the next time the same function is called.
689+
// This is for example used in the wait block (to call it again with the same time value).
685690
} else
686691
FREE_REGS(ret);
687-
if (warp)
688-
DISPATCH();
689-
else
690-
return pos;
692+
return pos;
691693
}
692694
FREE_REGS(ret);
693695
DISPATCH();

src/engine/virtualmachine_p.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct VirtualMachinePrivate
2222
VirtualMachinePrivate(const VirtualMachinePrivate &) = delete;
2323
~VirtualMachinePrivate();
2424

25-
unsigned int *run(unsigned int *pos);
25+
unsigned int *run(unsigned int *pos, bool reset = true);
2626

2727
static const unsigned int instruction_arg_count[];
2828

test/virtual_machine/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ target_link_libraries(
88
GTest::gtest_main
99
GTest::gmock_main
1010
scratchcpp
11+
scratchcpp_mocks
1112
)
1213

1314
gtest_discover_tests(virtual_machine_test)

0 commit comments

Comments
 (0)