Skip to content

Commit 070a784

Browse files
committed
JS Editor: add missing block coverage Phase 2
And Logical "and" operations && Arg Uses values passed into actions actionArgs[n] Boolean True/False toggles true / false Bottom Pos Gets the bottom boundary mouse.BOTTOMPOS Box / Box 1 / Box 2 Variable storage mouse.getBox() / mouse.setBox() Camera Accesses camera properties mouse.CAMERA
1 parent a234436 commit 070a784

File tree

8 files changed

+535
-39
lines changed

8 files changed

+535
-39
lines changed

js/js-export/ASTutils.js

Lines changed: 201 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,29 @@
2929
* JavaScript based Music Blocks code.
3030
*/
3131
class ASTUtils {
32+
static _isValidIdentifier(name) {
33+
return typeof name === "string" && /^[A-Za-z_$][0-9A-Za-z_$]*$/.test(name);
34+
}
35+
36+
static _getMouseCallExpression(methodName, args) {
37+
return {
38+
type: "CallExpression",
39+
callee: {
40+
type: "MemberExpression",
41+
object: {
42+
type: "Identifier",
43+
name: "mouse"
44+
},
45+
computed: false,
46+
property: {
47+
type: "Identifier",
48+
name: methodName
49+
}
50+
},
51+
arguments: args
52+
};
53+
}
54+
3255
/**
3356
* @static
3457
* Abstract Syntax Tree for the bare minimum program code
@@ -304,9 +327,34 @@ class ASTUtils {
304327
* @returns {Object} Abstract Syntax Tree of increment assignment statement
305328
*/
306329
static _getIncrementStmntAST(args, isIncrement) {
307-
const identifier = args[0].split("_")[1];
330+
const identifier =
331+
typeof args[0] === "string" && args[0].startsWith("box_") ? args[0].slice(4) : args[0];
308332
const arg = ASTUtils._getArgsAST([args[1]])[0];
309333

334+
if (!ASTUtils._isValidIdentifier(identifier)) {
335+
const deltaAst = isIncrement
336+
? arg
337+
: {
338+
type: "UnaryExpression",
339+
operator: "-",
340+
argument: arg,
341+
prefix: true
342+
};
343+
return {
344+
type: "ExpressionStatement",
345+
expression: {
346+
type: "AwaitExpression",
347+
argument: ASTUtils._getMouseCallExpression("incrementBox", [
348+
{
349+
type: "Literal",
350+
value: identifier
351+
},
352+
deltaAst
353+
])
354+
}
355+
};
356+
}
357+
310358
return {
311359
type: "ExpressionStatement",
312360
expression: {
@@ -353,6 +401,22 @@ class ASTUtils {
353401
{
354402
type: "Identifier",
355403
name: "mouse"
404+
},
405+
{
406+
type: "AssignmentPattern",
407+
left: {
408+
type: "Identifier",
409+
name: "actionArgs"
410+
},
411+
right: {
412+
type: "ArrayExpression",
413+
elements: [
414+
{
415+
type: "Literal",
416+
value: null
417+
}
418+
]
419+
}
356420
}
357421
],
358422
body: {
@@ -430,6 +494,18 @@ class ASTUtils {
430494
name: "mouse"
431495
}
432496
];
497+
if (args !== undefined && args !== null) {
498+
AST["expression"]["argument"]["arguments"].push({
499+
type: "ArrayExpression",
500+
elements: [
501+
{
502+
type: "Literal",
503+
value: null
504+
},
505+
...ASTUtils._getArgsAST(args)
506+
]
507+
});
508+
}
433509
}
434510
if (props.statement === false) {
435511
AST = AST["expression"];
@@ -448,6 +524,44 @@ class ASTUtils {
448524
* @returns {Object} - Abstract Syntax Tree of method call
449525
*/
450526
static _getArgExpAST(methodName, args) {
527+
if (methodName === "arg") {
528+
const indexAst = ASTUtils._getArgsAST(args)[0] || {
529+
type: "Literal",
530+
value: 1
531+
};
532+
return {
533+
type: "MemberExpression",
534+
object: {
535+
type: "Identifier",
536+
name: "actionArgs"
537+
},
538+
property: indexAst,
539+
computed: true
540+
};
541+
}
542+
543+
if (methodName === "box") {
544+
const nameAst = ASTUtils._getArgsAST(args)[0];
545+
if (nameAst && nameAst.type === "Identifier") {
546+
return nameAst;
547+
}
548+
if (nameAst && nameAst.type === "Literal" && typeof nameAst.value === "string") {
549+
if (ASTUtils._isValidIdentifier(nameAst.value)) {
550+
return {
551+
type: "Identifier",
552+
name: nameAst.value
553+
};
554+
}
555+
}
556+
if (!nameAst) {
557+
return {
558+
type: "Identifier",
559+
name: "undefined"
560+
};
561+
}
562+
return ASTUtils._getMouseCallExpression("getBox", [nameAst]);
563+
}
564+
451565
const mathOps = {
452566
plus: ["binexp", "+"],
453567
minus: ["binexp", "-"],
@@ -457,8 +571,8 @@ class ASTUtils {
457571
equal: ["binexp", "=="],
458572
less: ["binexp", "<"],
459573
greater: ["binexp", ">"],
460-
or: ["binexp", "|"],
461-
and: ["binexp", "&"],
574+
or: ["binexp", "||"],
575+
and: ["binexp", "&&"],
462576
xor: ["binexp", "^"],
463577
not: ["unexp", "!"],
464578
neg: ["unexp", "-"],
@@ -470,7 +584,10 @@ class ASTUtils {
470584

471585
function getBinaryExpAST(operator, operand1, operand2) {
472586
return {
473-
type: "BinaryExpression",
587+
type:
588+
operator === "&&" || operator === "||"
589+
? "LogicalExpression"
590+
: "BinaryExpression",
474591
left: ASTUtils._getArgsAST([operand1])[0],
475592
right: ASTUtils._getArgsAST([operand2])[0],
476593
operator: `${operator}`
@@ -538,17 +655,35 @@ class ASTUtils {
538655
);
539656
}
540657
} else {
541-
if (typeof arg === "string" && arg.split("_").length > 1) {
542-
const [type, argVal] = arg.split("_");
658+
if (typeof arg === "string" && arg.includes("_")) {
659+
const sepIndex = arg.indexOf("_");
660+
const type = arg.slice(0, sepIndex);
661+
const argVal = arg.slice(sepIndex + 1);
543662
if (type === "bool") {
544663
ASTs.push({
545664
type: "Literal",
546665
value: argVal === "true"
547666
});
548667
} else if (type === "box") {
668+
if (ASTUtils._isValidIdentifier(argVal)) {
669+
ASTs.push({
670+
type: "Identifier",
671+
name: argVal
672+
});
673+
} else {
674+
ASTs.push(
675+
ASTUtils._getMouseCallExpression("getBox", [
676+
{
677+
type: "Literal",
678+
value: argVal
679+
}
680+
])
681+
);
682+
}
683+
} else {
549684
ASTs.push({
550-
type: "Identifier",
551-
name: argVal
685+
type: "Literal",
686+
value: arg
552687
});
553688
}
554689
} else {
@@ -674,23 +809,13 @@ class ASTUtils {
674809
} else if (flow[0] === "decrementOne") {
675810
ASTs.push(ASTUtils._getIncrementStmntAST([flow[1][0], 1], false));
676811
} else if (flow[0] === "storein") {
677-
ASTs.push({
678-
type: "VariableDeclaration",
679-
kind: "var",
680-
declarations: [
681-
{
682-
type: "VariableDeclarator",
683-
id: {
684-
type: "Identifier",
685-
name: flow[1][0]
686-
},
687-
init: ASTUtils._getArgsAST([flow[1][1]])[0]
688-
}
689-
]
690-
});
691-
} else if (flow[0].split("_").length > 1) {
692-
const [instruction, idName] = flow[0].split("_");
693-
if (instruction === "storein2") {
812+
const nameAst = ASTUtils._getArgsAST([flow[1][0]])[0];
813+
const valueAst = ASTUtils._getArgsAST([flow[1][1]])[0];
814+
if (
815+
nameAst &&
816+
nameAst.type === "Literal" &&
817+
ASTUtils._isValidIdentifier(nameAst.value)
818+
) {
694819
ASTs.push({
695820
type: "VariableDeclaration",
696821
kind: "var",
@@ -699,14 +824,63 @@ class ASTUtils {
699824
type: "VariableDeclarator",
700825
id: {
701826
type: "Identifier",
702-
name: idName
827+
name: nameAst.value
703828
},
704-
init: ASTUtils._getArgsAST(flow[1])[0]
829+
init: valueAst
705830
}
706831
]
707832
});
833+
} else {
834+
ASTs.push({
835+
type: "ExpressionStatement",
836+
expression: {
837+
type: "AwaitExpression",
838+
argument: ASTUtils._getMouseCallExpression("setBox", [
839+
nameAst,
840+
valueAst
841+
])
842+
}
843+
});
844+
}
845+
} else if (flow[0].split("_").length > 1) {
846+
const splitIndex = flow[0].indexOf("_");
847+
const instruction = flow[0].slice(0, splitIndex);
848+
const idName = flow[0].slice(splitIndex + 1);
849+
if (instruction === "storein2") {
850+
if (ASTUtils._isValidIdentifier(idName)) {
851+
ASTs.push({
852+
type: "VariableDeclaration",
853+
kind: "var",
854+
declarations: [
855+
{
856+
type: "VariableDeclarator",
857+
id: {
858+
type: "Identifier",
859+
name: idName
860+
},
861+
init: ASTUtils._getArgsAST(flow[1])[0]
862+
}
863+
]
864+
});
865+
} else {
866+
ASTs.push({
867+
type: "ExpressionStatement",
868+
expression: {
869+
type: "AwaitExpression",
870+
argument: ASTUtils._getMouseCallExpression("setBox", [
871+
{
872+
type: "Literal",
873+
value: idName
874+
},
875+
ASTUtils._getArgsAST(flow[1])[0]
876+
])
877+
}
878+
});
879+
}
708880
} else if (instruction === "nameddo") {
709881
ASTs.push(ASTUtils._getMethodCallAST(idName, flow[1], { action: true }));
882+
} else if (instruction === "nameddoArg") {
883+
ASTs.push(ASTUtils._getMethodCallAST(idName, flow[1], { action: true }));
710884
}
711885
} else {
712886
if (JSInterface.isSetter(flow[0])) {

js/js-export/__tests__/ASTutils.test.js

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ describe("ASTUtils", () => {
244244

245245
describe("_getIncrementStmntAST", () => {
246246
it("should return the AST for an increment statement", () => {
247-
const args = ["var_testIdentifier", "testArg"];
247+
const args = ["box_testIdentifier", "testArg"];
248248
const isIncrement = true;
249249
const result = ASTUtils._getIncrementStmntAST(args, isIncrement);
250250
expect(result).toEqual({
@@ -270,7 +270,7 @@ describe("ASTUtils", () => {
270270
});
271271

272272
it("should return the AST for a decrement statement", () => {
273-
const args = ["var_testIdentifier", "testArg"];
273+
const args = ["box_testIdentifier", "testArg"];
274274
const isIncrement = false;
275275
const result = ASTUtils._getIncrementStmntAST(args, isIncrement);
276276
expect(result).toEqual({
@@ -316,6 +316,22 @@ describe("ASTUtils", () => {
316316
{
317317
type: "Identifier",
318318
name: "mouse"
319+
},
320+
{
321+
type: "AssignmentPattern",
322+
left: {
323+
type: "Identifier",
324+
name: "actionArgs"
325+
},
326+
right: {
327+
type: "ArrayExpression",
328+
elements: [
329+
{
330+
type: "Literal",
331+
value: null
332+
}
333+
]
334+
}
319335
}
320336
],
321337
body: {
@@ -397,6 +413,16 @@ describe("ASTUtils", () => {
397413
{
398414
type: "Identifier",
399415
name: "mouse"
416+
},
417+
{
418+
type: "ArrayExpression",
419+
elements: [
420+
{
421+
type: "Literal",
422+
value: null
423+
},
424+
...ASTUtils._getArgsAST(args)
425+
]
400426
}
401427
]
402428
}
@@ -796,6 +822,22 @@ describe("ASTUtils", () => {
796822
{
797823
type: "Identifier",
798824
name: "mouse"
825+
},
826+
{
827+
type: "AssignmentPattern",
828+
left: {
829+
type: "Identifier",
830+
name: "actionArgs"
831+
},
832+
right: {
833+
type: "ArrayExpression",
834+
elements: [
835+
{
836+
type: "Literal",
837+
value: null
838+
}
839+
]
840+
}
799841
}
800842
],
801843
body: {

0 commit comments

Comments
 (0)