Skip to content

Commit 40942c8

Browse files
committed
VirtualMachine: Add more operators
1 parent e155fea commit 40942c8

File tree

2 files changed

+127
-1
lines changed

2 files changed

+127
-1
lines changed

src/engine/virtualmachine.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
using namespace libscratchcpp;
2222
using namespace vm;
2323

24+
static const double pi = std::acos(-1); // TODO: Use std::numbers::pi in C++20
25+
2426
/*! Constructs VirtualMachine. */
2527
VirtualMachine::VirtualMachine()
2628
{
@@ -108,6 +110,17 @@ unsigned int *VirtualMachine::run(unsigned int *pos)
108110
&&do_divide,
109111
&&do_mod,
110112
&&do_random,
113+
&&do_round,
114+
&&do_abs,
115+
&&do_floor,
116+
&&do_ceil,
117+
&&do_sqrt,
118+
&&do_sin,
119+
&&do_cos,
120+
&&do_tan,
121+
&&do_asin,
122+
&&do_acos,
123+
&&do_atan,
111124
&&do_greater_than,
112125
&&do_less_than,
113126
&&do_equals,
@@ -249,6 +262,106 @@ unsigned int *VirtualMachine::run(unsigned int *pos)
249262
FREE_REGS(1);
250263
DISPATCH();
251264

265+
do_round : {
266+
const Value *v = READ_REG(0, 1);
267+
if (!v->isInfinity() && !v->isNegativeInfinity())
268+
REPLACE_RET_VALUE(static_cast<long>(std::round(v->toDouble())), 1);
269+
DISPATCH();
270+
}
271+
272+
do_abs : {
273+
const Value *v = READ_REG(0, 1);
274+
if (v->isNegativeInfinity())
275+
REPLACE_RET_VALUE(Value(Value::SpecialValue::Infinity), 1);
276+
else if (!v->isInfinity())
277+
REPLACE_RET_VALUE(std::abs(v->toDouble()), 1);
278+
DISPATCH();
279+
}
280+
281+
do_floor : {
282+
const Value *v = READ_REG(0, 1);
283+
if (!v->isInfinity() && !v->isNegativeInfinity())
284+
REPLACE_RET_VALUE(std::floor(v->toDouble()), 1);
285+
DISPATCH();
286+
}
287+
288+
do_ceil : {
289+
const Value *v = READ_REG(0, 1);
290+
if (!v->isInfinity() && !v->isNegativeInfinity())
291+
REPLACE_RET_VALUE(std::ceil(v->toDouble()), 1);
292+
DISPATCH();
293+
}
294+
295+
do_sqrt : {
296+
const Value &v = *READ_REG(0, 1);
297+
if (v < 0)
298+
REPLACE_RET_VALUE(Value(Value::SpecialValue::NaN), 1);
299+
else if (!v.isInfinity())
300+
REPLACE_RET_VALUE(std::sqrt(v.toDouble()), 1);
301+
DISPATCH();
302+
}
303+
304+
do_sin : {
305+
const Value *v = READ_REG(0, 1);
306+
if (v->isInfinity() || v->isNegativeInfinity())
307+
REPLACE_RET_VALUE(Value(Value::SpecialValue::NaN), 1);
308+
else
309+
REPLACE_RET_VALUE(std::sin(v->toDouble() * pi / 180), 1);
310+
DISPATCH();
311+
}
312+
313+
do_cos : {
314+
const Value *v = READ_REG(0, 1);
315+
if (v->isInfinity() || v->isNegativeInfinity())
316+
REPLACE_RET_VALUE(Value(Value::SpecialValue::NaN), 1);
317+
else
318+
REPLACE_RET_VALUE(std::cos(v->toDouble() * pi / 180), 1);
319+
DISPATCH();
320+
}
321+
322+
do_tan : {
323+
const Value *v = READ_REG(0, 1);
324+
if (v->isInfinity() || v->isNegativeInfinity())
325+
REPLACE_RET_VALUE(Value(Value::SpecialValue::NaN), 1);
326+
else {
327+
long mod = v->toLong() % 360;
328+
if (mod == 90)
329+
REPLACE_RET_VALUE(Value(Value::SpecialValue::Infinity), 1);
330+
else if (mod == 270)
331+
REPLACE_RET_VALUE(Value(Value::SpecialValue::NegativeInfinity), 1);
332+
else
333+
REPLACE_RET_VALUE(std::tan(v->toDouble() * pi / 180), 1);
334+
}
335+
DISPATCH();
336+
}
337+
338+
do_asin : {
339+
const Value &v = *READ_REG(0, 1);
340+
if (v < -1 || v > 1)
341+
REPLACE_RET_VALUE(Value(Value::SpecialValue::NaN), 1);
342+
else
343+
REPLACE_RET_VALUE(std::asin(v.toDouble()) * 180 / pi, 1);
344+
DISPATCH();
345+
}
346+
347+
do_acos : {
348+
const Value &v = *READ_REG(0, 1);
349+
if (v < -1 || v > 1)
350+
REPLACE_RET_VALUE(Value(Value::SpecialValue::NaN), 1);
351+
else
352+
REPLACE_RET_VALUE(std::acos(v.toDouble()) * 180 / pi, 1);
353+
DISPATCH();
354+
}
355+
356+
do_atan : {
357+
const Value &v = *READ_REG(0, 1);
358+
if (v < -1 || v > 1)
359+
REPLACE_RET_VALUE(Value(Value::SpecialValue::NaN), 1);
360+
else
361+
REPLACE_RET_VALUE(std::atan(v.toDouble()) * 180 / pi, 1);
362+
DISPATCH();
363+
}
364+
252365
do_greater_than:
253366
REPLACE_RET_VALUE(*READ_REG(0, 2) > *READ_REG(1, 2), 2);
254367
FREE_REGS(1);

src/engine/virtualmachine.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ enum Opcode
3434
OP_DIVIDE, /*!< Divides the values stored in the last 2 registers and stores the result in the last registry, deleting the input registers. */
3535
OP_MOD, /*!< Calculates module of the values stored in the last 2 registers and stores the result in the last registry, deleting the input registers. */
3636
OP_RANDOM, /*!< Generates a random value in the range stored in the last 2 registers and stores the result in the last registry, deleting the input registers. */
37+
OP_ROUND, /*!< Rounds the number in the last register and stores the result in the last register. */
38+
OP_ABS, /*!< Calculates the absolute value of the number in the last register and stores the result in the last register. */
39+
OP_FLOOR, /*!< Calculates the floor of the number in the last register and stores the result in the last register. */
40+
OP_CEIL, /*!< Calculates the ceiling of the number in the last register and stores the result in the last register. */
41+
OP_SQRT, /*!< Calculates the square root of the number in the last register and stores the result in the last register. */
42+
OP_SIN, /*!< Calculates the sine of the number in the last register and stores the result in the last register. */
43+
OP_COS, /*!< Calculates the cosine of the number in the last register and stores the result in the last register. */
44+
OP_TAN, /*!< Calculates the tangent of the number in the last register and stores the result in the last register. */
45+
OP_ASIN, /*!< Calculates the arcsine of the number in the last register and stores the result in the last register. */
46+
OP_ACOS, /*!< Calculates the arccosine of the number in the last register and stores the result in the last register. */
47+
OP_ATAN, /*!< Calculates the arctangent of the number in the last register and stores the result in the last register. */
3748
OP_GREATER_THAN, /*!< Compares (>) the values stored in the last 2 registers and stores the result in the last registry, deleting the input registers. */
3849
OP_LESS_THAN, /*!< Compares (<) the values stored in the last 2 registers and stores the result in the last registry, deleting the input registers. */
3950
OP_EQUALS, /*!< Compares (==) the values stored in the last 2 registers and stores the result in the last registry, deleting the input registers. */
@@ -99,7 +110,9 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
99110
private:
100111
unsigned int *run(unsigned int *pos);
101112

102-
static inline const unsigned int instruction_arg_count[] = { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1 };
113+
static inline const unsigned int instruction_arg_count[] = {
114+
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1
115+
};
103116

104117
unsigned int *m_bytecode;
105118
std::vector<unsigned int> m_bytecodeVector;

0 commit comments

Comments
 (0)