From 67cb7cfc5d47a3ca72c173abe3fdc8d07de0d993 Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Wed, 8 Oct 2025 18:42:43 -0500 Subject: [PATCH 1/3] Remove unnecessary string casts --- src/compiler/iroptimizer.js | 22 +++++++++++++++++-- .../tw-sensing-of.sb3.tw-snapshot | 2 +- ...w-simple-string-operations.sb3.tw-snapshot | 8 +++---- .../warp-timer/tw-sensing-of.sb3.tw-snapshot | 2 +- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/compiler/iroptimizer.js b/src/compiler/iroptimizer.js index ae7d98e495f..ebd2545b8e1 100644 --- a/src/compiler/iroptimizer.js +++ b/src/compiler/iroptimizer.js @@ -162,12 +162,20 @@ class IROptimizer { const innerType = inputs.target.type; if (innerType & InputType.NUMBER) return innerType; return InputType.NUMBER; - } case InputOpcode.CAST_NUMBER_OR_NAN: { + } + + case InputOpcode.CAST_NUMBER_OR_NAN: { const innerType = inputs.target.type; if (innerType & InputType.NUMBER_OR_NAN) return innerType; return InputType.NUMBER_OR_NAN; } + case InputOpcode.CAST_STRING: { + const innerType = inputs.target.type; + if (innerType & InputType.STRING) return innerType; + return InputType.STRING; + } + case InputOpcode.OP_ADD: { const leftType = inputs.left.type; const rightType = inputs.right.type; @@ -699,13 +707,23 @@ class IROptimizer { return input.inputs.target; } return input; - } case InputOpcode.CAST_NUMBER_OR_NAN: { + } + + case InputOpcode.CAST_NUMBER_OR_NAN: { const targetType = input.inputs.target.type; if ((targetType & InputType.NUMBER_OR_NAN) === targetType) { return input.inputs.target; } return input; } + + case InputOpcode.CAST_STRING: { + const targetType = input.inputs.target.type; + if ((targetType & InputType.STRING) === targetType) { + return input.inputs.target; + } + return input; + } } return input; diff --git a/test/snapshot/__snapshots__/tw-sensing-of.sb3.tw-snapshot b/test/snapshot/__snapshots__/tw-sensing-of.sb3.tw-snapshot index a370af3e46d..b15bc894fa8 100644 --- a/test/snapshot/__snapshots__/tw-sensing-of.sb3.tw-snapshot +++ b/test/snapshot/__snapshots__/tw-sensing-of.sb3.tw-snapshot @@ -52,7 +52,7 @@ if (compareEqual((b4 ? b4.value : 0), 0)) { yield* executeInCompatibilityLayer({"MESSAGE":"pass non existent variable",}, b0, false, false, ")nnN?*l+E)dC(fT5(_@q", null); } b5.value = (("" + randomInt(1, 9)) + ("" + randomInt(1, 9))); -if (compareEqual(runtime.ext_scratch3_sensing.getAttributeOf({OBJECT: ("" + b5.value), PROPERTY: "backdrop #" }), 0)) { +if (compareEqual(runtime.ext_scratch3_sensing.getAttributeOf({OBJECT: b5.value, PROPERTY: "backdrop #" }), 0)) { yield* executeInCompatibilityLayer({"MESSAGE":"pass NE backdrop #",}, b0, false, false, "UFr{fbR3@a.u_paq:r]F", null); } if (compareEqual(runtime.ext_scratch3_sensing.getAttributeOf({OBJECT: ("" + b5.value), PROPERTY: "backdrop name" }), 0)) { diff --git a/test/snapshot/__snapshots__/tw-simple-string-operations.sb3.tw-snapshot b/test/snapshot/__snapshots__/tw-simple-string-operations.sb3.tw-snapshot index 78cdbd86e7f..a290411e64c 100644 --- a/test/snapshot/__snapshots__/tw-simple-string-operations.sb3.tw-snapshot +++ b/test/snapshot/__snapshots__/tw-simple-string-operations.sb3.tw-snapshot @@ -24,11 +24,11 @@ return function funXYZ_a () { b0.value = "ababa"; b1.value = ""; b2.value = 1; -for (var a0 = ("" + b0.value).length; a0 > 0; a0--) { -if ((((("" + b0.value))[(b2.value | 0) - 1] || "").toLowerCase() === "a".toLowerCase())) { -b1.value = (("" + b1.value) + "b"); +for (var a0 = b0.value.length; a0 > 0; a0--) { +if ((((b0.value)[(b2.value | 0) - 1] || "").toLowerCase() === "a".toLowerCase())) { +b1.value = (b1.value + "b"); } else { -b1.value = (("" + b1.value) + "a"); +b1.value = (b1.value + "a"); } b2.value = (b2.value + 1); } diff --git a/test/snapshot/__snapshots__/warp-timer/tw-sensing-of.sb3.tw-snapshot b/test/snapshot/__snapshots__/warp-timer/tw-sensing-of.sb3.tw-snapshot index a370af3e46d..b15bc894fa8 100644 --- a/test/snapshot/__snapshots__/warp-timer/tw-sensing-of.sb3.tw-snapshot +++ b/test/snapshot/__snapshots__/warp-timer/tw-sensing-of.sb3.tw-snapshot @@ -52,7 +52,7 @@ if (compareEqual((b4 ? b4.value : 0), 0)) { yield* executeInCompatibilityLayer({"MESSAGE":"pass non existent variable",}, b0, false, false, ")nnN?*l+E)dC(fT5(_@q", null); } b5.value = (("" + randomInt(1, 9)) + ("" + randomInt(1, 9))); -if (compareEqual(runtime.ext_scratch3_sensing.getAttributeOf({OBJECT: ("" + b5.value), PROPERTY: "backdrop #" }), 0)) { +if (compareEqual(runtime.ext_scratch3_sensing.getAttributeOf({OBJECT: b5.value, PROPERTY: "backdrop #" }), 0)) { yield* executeInCompatibilityLayer({"MESSAGE":"pass NE backdrop #",}, b0, false, false, "UFr{fbR3@a.u_paq:r]F", null); } if (compareEqual(runtime.ext_scratch3_sensing.getAttributeOf({OBJECT: ("" + b5.value), PROPERTY: "backdrop name" }), 0)) { From 3b947da95e1f35f41881626b9cff793984e2938b Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Wed, 8 Oct 2025 18:43:50 -0500 Subject: [PATCH 2/3] Remove unnecessary number index casts --- src/compiler/iroptimizer.js | 14 ++++++++++++++ .../tw-simple-string-operations.sb3.tw-snapshot | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/compiler/iroptimizer.js b/src/compiler/iroptimizer.js index ebd2545b8e1..d5d284360ab 100644 --- a/src/compiler/iroptimizer.js +++ b/src/compiler/iroptimizer.js @@ -164,6 +164,12 @@ class IROptimizer { return InputType.NUMBER; } + case InputOpcode.CAST_NUMBER_INDEX: { + const innerType = inputs.target.type; + if (innerType & InputType.NUMBER_INDEX) return innerType; + return InputType.NUMBER_INDEX; + } + case InputOpcode.CAST_NUMBER_OR_NAN: { const innerType = inputs.target.type; if (innerType & InputType.NUMBER_OR_NAN) return innerType; @@ -709,6 +715,14 @@ class IROptimizer { return input; } + case InputOpcode.CAST_NUMBER_INDEX: { + const targetType = input.inputs.target.type; + if ((targetType & InputType.NUMBER_INDEX) === targetType) { + return input.inputs.target; + } + return input; + } + case InputOpcode.CAST_NUMBER_OR_NAN: { const targetType = input.inputs.target.type; if ((targetType & InputType.NUMBER_OR_NAN) === targetType) { diff --git a/test/snapshot/__snapshots__/tw-simple-string-operations.sb3.tw-snapshot b/test/snapshot/__snapshots__/tw-simple-string-operations.sb3.tw-snapshot index a290411e64c..7899f9ed374 100644 --- a/test/snapshot/__snapshots__/tw-simple-string-operations.sb3.tw-snapshot +++ b/test/snapshot/__snapshots__/tw-simple-string-operations.sb3.tw-snapshot @@ -25,7 +25,7 @@ b0.value = "ababa"; b1.value = ""; b2.value = 1; for (var a0 = b0.value.length; a0 > 0; a0--) { -if ((((b0.value)[(b2.value | 0) - 1] || "").toLowerCase() === "a".toLowerCase())) { +if ((((b0.value)[b2.value - 1] || "").toLowerCase() === "a".toLowerCase())) { b1.value = (b1.value + "b"); } else { b1.value = (b1.value + "a"); From efb502a8acf320abe40cf173f5def583c64a0014 Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Wed, 8 Oct 2025 18:44:51 -0500 Subject: [PATCH 3/3] Remove unnecessary boolean casts --- src/compiler/iroptimizer.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/compiler/iroptimizer.js b/src/compiler/iroptimizer.js index d5d284360ab..481bccd5b7d 100644 --- a/src/compiler/iroptimizer.js +++ b/src/compiler/iroptimizer.js @@ -158,6 +158,12 @@ class IROptimizer { case InputOpcode.ADDON_CALL: break; + case InputOpcode.CAST_BOOLEAN: { + const innerType = inputs.target.type; + if (innerType & InputType.BOOLEAN) return innerType; + return InputType.BOOLEAN; + } + case InputOpcode.CAST_NUMBER: { const innerType = inputs.target.type; if (innerType & InputType.NUMBER) return innerType; @@ -707,6 +713,14 @@ class IROptimizer { } switch (input.opcode) { + case InputOpcode.CAST_BOOLEAN: { + const targetType = input.inputs.target.type; + if ((targetType & InputType.BOOLEAN) === targetType) { + return input.inputs.target; + } + return input; + } + case InputOpcode.CAST_NUMBER: { const targetType = input.inputs.target.type; if ((targetType & InputType.NUMBER) === targetType) {