Skip to content

Commit 0111804

Browse files
authored
poop
1 parent 72a2445 commit 0111804

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

src/compiler/enums.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ const StackOpcode = {
193193
COMMENTS_LOOP: 'comments.loop',
194194

195195
PROCEDURE_RETURN: 'procedures.return',
196-
PROCEDURE_CALL: 'procedures.call'
196+
PROCEDURE_CALL: 'procedures.call',
197+
PROCEDURE_BRANCH: 'procedures.branch'
197198
};
198199

199200
/**

src/compiler/irgen.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,13 @@ class ScriptTreeGenerator {
761761
}
762762

763763
switch (block.opcode) {
764+
case 'argument_reporter_statement': {
765+
// see argument_reporter_string_number above
766+
const name = block.fields.VALUE.value;
767+
const index = this.script.arguments.lastIndexOf(name);
768+
return new IntermediateStackBlock(StackOpcode.PROCEDURE_BRANCH, {index});
769+
}
770+
764771
case 'control_all_at_once':
765772
// In Scratch 3, this block behaves like "if 1 = 1"
766773
return new IntermediateStackBlock(StackOpcode.CONTROL_IF_ELSE, {
@@ -1249,7 +1256,12 @@ class ScriptTreeGenerator {
12491256
for (let i = 0; i < paramIds.length; i++) {
12501257
let value;
12511258
if (block.inputs[paramIds[i]] && block.inputs[paramIds[i]].block) {
1252-
value = this.descendInputOfBlock(block, paramIds[i], true);
1259+
if (paramIds[i].startsWith("SUBSTACK")) {
1260+
value = this.descendSubstack(block, paramIds[i]);
1261+
} else {
1262+
value = this.descendInputOfBlock(block, paramIds[i], true);
1263+
}
1264+
12531265
} else {
12541266
value = this.createConstantInput(paramDefaults[i], true);
12551267
}

src/compiler/jsgen.js

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class JSGenerator {
106106
this.isWarp = script.isWarp;
107107
this.isProcedure = script.isProcedure;
108108
this.warpTimer = script.warpTimer;
109+
this.allowReturns = false;
109110

110111
/**
111112
* Stack of frames, most recent is last item.
@@ -461,7 +462,22 @@ class JSGenerator {
461462
const procedureReference = `thread.procedures["${sanitize(procedureVariant)}"]`;
462463
const args = [];
463464
for (const input of node.arguments) {
464-
args.push(this.descendInput(input));
465+
if (input instanceof IntermediateStack) {
466+
const oldSource = this.source;
467+
this.source = "function*(thread, target, runtime, stage) {\n";
468+
const oldWarp = this.isWarp;
469+
this.isWarp = procedureData.isWarp;
470+
const oldReturns = this.allowReturns;
471+
this.allowReturns = true;
472+
this.descendStack(input);
473+
this.source += `}`;
474+
args.push(this.source);
475+
this.allowReturns = oldReturns;
476+
this.isWarp = oldWarp;
477+
this.source = oldSource;
478+
} else {
479+
args.push(this.descendInput(input));
480+
}
465481
}
466482
const joinedArgs = args.join(',');
467483

@@ -929,6 +945,8 @@ class JSGenerator {
929945
// Direct yields.
930946
this.yieldNotWarp();
931947
}
948+
let outputVariable = this.localVariables.next();
949+
this.source += `let ${outputVariable} = `;
932950
if (procedureData.yields) {
933951
this.source += 'yield* ';
934952
if (!this.script.yields) {
@@ -938,15 +956,43 @@ class JSGenerator {
938956
this.source += `thread.procedures["${sanitize(procedureVariant)}"](`;
939957
const args = [];
940958
for (const input of node.arguments) {
941-
args.push(this.descendInput(input));
959+
if (input instanceof IntermediateStack) {
960+
const oldSource = this.source;
961+
this.source = "function*(thread, target, runtime, stage) {\n";
962+
const oldWarp = this.isWarp;
963+
this.isWarp = procedureData.isWarp;
964+
const oldReturns = this.allowReturns;
965+
this.allowReturns = true;
966+
this.descendStack(input);
967+
this.source += `}`;
968+
args.push(this.source);
969+
this.allowReturns = oldReturns;
970+
this.isWarp = oldWarp;
971+
this.source = oldSource;
972+
} else {
973+
args.push(this.descendInput(input));
974+
}
942975
}
943976
this.source += args.join(',');
944977
this.source += `);\n`;
978+
const thisData = this.ir.procedures[this.script.procedureVariant];
979+
if (thisData && !thisData.returns) {
980+
this.source += `if (${outputVariable} !== undefined) { return ${outputVariable}; };\n`
981+
}
945982
break;
946983
}
947984
case StackOpcode.PROCEDURE_RETURN:
948985
this.stopScriptAndReturn(this.descendInput(node.value));
949986
break;
987+
case StackOpcode.PROCEDURE_BRANCH:
988+
if (node.index !== -1) {
989+
let outputVariable = this.localVariables.next();
990+
this.source += `let ${outputVariable} = yield* (p${node.index} || function*(){})(thread, target, runtime, stage);\n`;
991+
this.source += `if (${outputVariable} !== undefined) {\n`;
992+
this.stopScriptAndReturn(outputVariable);
993+
this.source += `};\n`
994+
}
995+
break;
950996

951997
case StackOpcode.SENSING_TIMER_RESET:
952998
this.source += 'runtime.ioDevices.clock.resetProjectTimer();\n';
@@ -1190,7 +1236,7 @@ class JSGenerator {
11901236
* @param {string} valueJS JS code of value to return.
11911237
*/
11921238
stopScriptAndReturn (valueJS) {
1193-
if (this.isProcedure) {
1239+
if (this.isProcedure || this.allowReturns) {
11941240
this.source += `return ${valueJS};\n`;
11951241
} else {
11961242
this.retire();

0 commit comments

Comments
 (0)