diff --git a/src/compiler/irgen.js b/src/compiler/irgen.js index dd92c768..fc777249 100644 --- a/src/compiler/irgen.js +++ b/src/compiler/irgen.js @@ -80,6 +80,8 @@ class ScriptTreeGenerator { * @private */ this.variableCache = {}; + + this.usesTimer = false; } setProcedureVariant (procedureVariant) { @@ -620,6 +622,7 @@ class ScriptTreeGenerator { object: this.descendInputOfBlock(block, 'OBJECT') }; case 'sensing_timer': + this.usesTimer = true; return { kind: 'timer.get' }; @@ -751,16 +754,26 @@ class ScriptTreeGenerator { times: this.descendInputOfBlock(block, 'TIMES'), do: this.descendSubstack(block, 'SUBSTACK') }; - case 'control_repeat_until': + case 'control_repeat_until': { this.analyzeLoop(); + // Dirty hack: automatically enable warp timer for this block if it uses timer + // This fixes project that do things like "repeat until timer > 0.5" + this.usesTimer = false; + const condition = this.descendInputOfBlock(block, 'CONDITION'); + const needsWarpTimer = this.usesTimer; + if (needsWarpTimer) { + this.script.yields = true; + } return { kind: 'control.while', condition: { kind: 'op.not', - operand: this.descendInputOfBlock(block, 'CONDITION') + operand: condition }, - do: this.descendSubstack(block, 'SUBSTACK') + do: this.descendSubstack(block, 'SUBSTACK'), + warpTimer: needsWarpTimer }; + } case 'control_stop': { const level = block.fields.STOP_OPTION.value; if (level === 'all') { @@ -798,7 +811,9 @@ class ScriptTreeGenerator { return { kind: 'control.while', condition: this.descendInputOfBlock(block, 'CONDITION'), - do: this.descendSubstack(block, 'SUBSTACK') + do: this.descendSubstack(block, 'SUBSTACK'), + // We should consider analyzing this like we do for control_repeat_until + warpTimer: false }; case 'data_addtolist': diff --git a/src/compiler/jsgen.js b/src/compiler/jsgen.js index 93ac816d..a23a662d 100644 --- a/src/compiler/jsgen.js +++ b/src/compiler/jsgen.js @@ -794,7 +794,11 @@ class JSGenerator { this.resetVariableInputs(); this.source += `while (${this.descendInput(node.condition).asBoolean()}) {\n`; this.descendStack(node.do, new Frame(true)); - this.yieldLoop(); + if (node.warpTimer) { + this.yieldStuckOrNotWarp(); + } else { + this.yieldLoop(); + } this.source += `}\n`; break; diff --git a/test/fixtures/execute/tw-warp-repeat-until-timer-greater-than.sb3 b/test/fixtures/execute/tw-warp-repeat-until-timer-greater-than.sb3 new file mode 100644 index 00000000..77ef3f28 Binary files /dev/null and b/test/fixtures/execute/tw-warp-repeat-until-timer-greater-than.sb3 differ