diff --git a/src/compiler/irgen.js b/src/compiler/irgen.js index 054788abf8..d35530fcf5 100644 --- a/src/compiler/irgen.js +++ b/src/compiler/irgen.js @@ -1,6 +1,8 @@ const Cast = require('../util/cast'); const StringUtil = require('../util/string-util'); const BlockType = require('../extension-support/block-type'); +const Sequencer = require('../engine/sequencer'); +const BlockUtility = require('../engine/block-utility'); const Variable = require('../engine/variable'); const Color = require('../util/color'); const log = require('../util/log'); @@ -69,6 +71,8 @@ class ScriptTreeGenerator { this.runtime = this.target.runtime; /** @private */ this.stage = this.runtime.getTargetForStage(); + /** @private */ + this.util = new BlockUtility(this.runtime.sequencer, this.thread); /** * This script's intermediate representation. @@ -1575,6 +1579,26 @@ class ScriptTreeGenerator { param: this.descendInputOfBlock(block, "PARAM"), val: this.descendInputOfBlock(block, "VALUE") }; + case 'argument_reporter_command': { + const name = block.fields.VALUE.value; + // lastIndexOf because multiple parameters with the same name will use the value of the last definition + const index = this.script.arguments.lastIndexOf(name); + if (index === -1) { return } + + const branchInfo = util.getParam(args.VALUE) || {}; + if (branchInfo.entry === null) return; + const [branchId, target] = util.getBranchAndTarget( + branchInfo.callerId, + branchInfo.entry + ) || []; + + return { + kind: 'args.command', + index: index, + branchId: branchId, + target: target + }; + } case 'procedures_call': { // setting of yields will be handled later in the analysis phase // patches output previewing diff --git a/src/compiler/jsgen.js b/src/compiler/jsgen.js index b43eae3456..e34a26a387 100644 --- a/src/compiler/jsgen.js +++ b/src/compiler/jsgen.js @@ -1074,6 +1074,10 @@ class JSGenerator { break; } + case 'args.command': + //TBD + break; + case 'compat': { // If the last command in a loop returns a promise, immediately continue to the next iteration. // If you don't do this, the loop effectively yields twice per iteration and will run at half-speed. diff --git a/src/engine/block-utility.js b/src/engine/block-utility.js index 60470db45b..b5bf4e12ab 100644 --- a/src/engine/block-utility.js +++ b/src/engine/block-utility.js @@ -131,6 +131,20 @@ class BlockUtility { this.sequencer.stepToBranch(this.thread, branchNum, isLoop); } + /** + * Get the branch for a particular C-shaped block, and it's target. + * @param {string} id ID for block to get the branch for. + * @param {string} branchId Which branch to select (e.g. for if-else). + * @return {string} ID of block in the branch. + */ + getBranchAndTarget (id, branchId) { + const result = this.thread.blockContainer.getBranch(id, branchId); + if (result) { + return [result, this.thread.target]; + } + return this.sequencer.runtime.getBranchAndTarget(id, branchId); + } + /** * Stop all threads. */ diff --git a/src/engine/runtime.js b/src/engine/runtime.js index a50338cafd..8a4e6a31c0 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -3649,6 +3649,22 @@ class Runtime extends EventEmitter { this.emit('targetWasRemoved', target); } + /** + * Get the branch for a particular C-shaped block, and it's target. + * @param {?string} id ID for block to get the branch for. + * @param {?string} branchId Which branch to select (e.g. for if-else). + * @return {?string} ID of block in the branch. + */ + getBranchAndTarget (id, branchId) { + for (const target of this.targets) { + const result = target.blocks.getBranch(id, branchId); + if (result) { + return [result, target]; + } + } + return null; + } + /** * gets a screen, if no screen can be found it will create one * @param {string} screen the screen to get