Skip to content

Commit edf9018

Browse files
committed
Add new test tw_operator_type_matrix
1 parent f3d6049 commit edf9018

File tree

1 file changed

+204
-0
lines changed

1 file changed

+204
-0
lines changed
+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
const { test } = require('tap');
2+
const VM = require('../../src/virtual-machine');
3+
const { BlockType, ArgumentType } = require('../../src/extension-support/tw-extension-api-common');
4+
const IRGenerator = require('../../src/compiler/irgen');
5+
const { IROptimizer } = require('../../src/compiler/iroptimizer');
6+
const { IntermediateInput } = require('../../src/compiler/intermediate');
7+
const log = require('../../src/util/log');
8+
9+
const VALUES = [
10+
NaN,
11+
12+
-Infinity,
13+
-1e+308,
14+
-1,
15+
-0.5,
16+
-1e-324,
17+
-0,
18+
0,
19+
1e-324,
20+
0.5,
21+
1,
22+
1e+308,
23+
Infinity
24+
];
25+
26+
const createBinaryOperator = (opcode) => {
27+
return {
28+
opcode,
29+
inputNames: ["NUM1", "NUM2"],
30+
fields: {}
31+
};
32+
};
33+
34+
const createMathopOperator = (name) => {
35+
return {
36+
opcode: "operator_mathop",
37+
inputNames: ["NUM"],
38+
fields: {
39+
"OPERATOR": [
40+
name,
41+
null
42+
]
43+
}
44+
};
45+
};
46+
47+
const OPERATORS = [
48+
createBinaryOperator("operator_add"),
49+
createBinaryOperator("operator_subtract"),
50+
createBinaryOperator("operator_divide"),
51+
createBinaryOperator("operator_multiply"),
52+
createBinaryOperator("operator_mod"),
53+
54+
createMathopOperator("abs"),
55+
createMathopOperator("floor"),
56+
createMathopOperator("ceiling"),
57+
createMathopOperator("sqrt"),
58+
createMathopOperator("sin"),
59+
createMathopOperator("cos"),
60+
createMathopOperator("tan"),
61+
createMathopOperator("asin"),
62+
createMathopOperator("acos"),
63+
createMathopOperator("atan"),
64+
createMathopOperator("ln"),
65+
createMathopOperator("log"),
66+
createMathopOperator("e ^"),
67+
createMathopOperator("10 ^"),
68+
];
69+
70+
const str = (number) => Object.is(number, -0) ? "-0" : number.toString();
71+
72+
test('operator type matrix', async t => {
73+
74+
const vm = new VM();
75+
log.suggest.deny('vm', 'error');
76+
77+
let reportedValue;
78+
79+
class TestExtension {
80+
getInfo() {
81+
return {
82+
id: 'test',
83+
name: 'Test',
84+
blocks: [
85+
{
86+
opcode: 'report',
87+
blockType: BlockType.COMMAND,
88+
text: 'report [INPUT]',
89+
isEdgeActivated: false,
90+
arguments: {
91+
INPUT: {
92+
type: ArgumentType.NUMBER,
93+
defaultValue: 0
94+
}
95+
}
96+
}
97+
]
98+
};
99+
}
100+
report(args) {
101+
reportedValue = args.INPUT;
102+
}
103+
}
104+
105+
vm.extensionManager.addBuiltinExtension('test', TestExtension);
106+
vm.setCompilerOptions({ enabled: true });
107+
108+
vm.on('COMPILE_ERROR', () => {
109+
t.fail('Compile error');
110+
});
111+
112+
const testOperator = async (operator, inputs) => {
113+
114+
const inputsSB3 = {};
115+
for (var i = 0; i < inputs.length; i++) {
116+
inputsSB3[operator.inputNames[i]] = [
117+
1,
118+
[
119+
4,
120+
"" + inputs[i]
121+
]
122+
];
123+
}
124+
125+
await vm.loadProject({
126+
targets: [
127+
{
128+
isStage: true,
129+
name: "Stage",
130+
variables: {},
131+
lists: {},
132+
costumes: [
133+
{
134+
"name": "dummy",
135+
"dataFormat": "svg",
136+
"assetId": "cd21514d0531fdffb22204e0ec5ed84a",
137+
"md5ext": "cd21514d0531fdffb22204e0ec5ed84a.svg"
138+
}
139+
],
140+
sounds: [],
141+
142+
blocks: {
143+
"report": {
144+
opcode: "test_report",
145+
inputs: {
146+
"INPUT": [
147+
3,
148+
"operator"
149+
]
150+
}
151+
},
152+
"operator": {
153+
opcode: operator.opcode,
154+
inputs: inputsSB3,
155+
fields: operator.fields
156+
}
157+
}
158+
}
159+
],
160+
meta: {
161+
semver: "3.0.0",
162+
vm: "0.2.0",
163+
agent: ""
164+
}
165+
});
166+
167+
const thread = vm.runtime._pushThread("report", vm.runtime.targets[0]);
168+
169+
const irGenerator = new IRGenerator(thread);
170+
const ir = irGenerator.generate();
171+
const irOptimizer = new IROptimizer(ir);
172+
irOptimizer.optimize();
173+
174+
175+
while (vm.runtime.threads.length !== 0)
176+
vm.runtime._step();
177+
178+
// The ir input representing our operator
179+
const irOperator = ir.entry.stack.blocks[0].inputs.inputs.INPUT;
180+
181+
const expectedType = IntermediateInput.getNumberInputType(reportedValue);
182+
183+
t.ok(
184+
irOperator.isSometimesType(expectedType),
185+
`${operator.opcode}${JSON.stringify(operator.fields)}[${inputs.map(str)}] outputted value ${str(reportedValue)} is of the expected type ${irOperator.type}.`
186+
);
187+
}
188+
189+
for (const operator of OPERATORS) {
190+
if (operator.inputNames.length == 2) {
191+
for (const left of VALUES) {
192+
for (const right of VALUES) {
193+
await testOperator(operator, [left, right]);
194+
}
195+
}
196+
} else {
197+
for (const value of VALUES) {
198+
await testOperator(operator, [value]);
199+
}
200+
}
201+
}
202+
203+
t.end();
204+
});

0 commit comments

Comments
 (0)