From b0870518a4ffe7cf991159ea1101d4d4c6a26ba8 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 6 Oct 2017 15:34:32 -0400 Subject: [PATCH 1/3] Changing parsing of custom procedures for new style --- src/engine/blocks.js | 5 ++--- src/engine/execute.js | 2 ++ src/engine/sequencer.js | 4 +++- src/serialization/sb2.js | 31 ++++++++++++++++++++++++------- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 4a7eb72e2..5b74cf55b 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -154,7 +154,7 @@ class Blocks { const block = this._blocks[id]; if ((block.opcode === 'procedures_defnoreturn' || block.opcode === 'procedures_defreturn') && - block.mutation.proccode === name) { + this._blocks[block.inputs.custom_block.block].mutation.proccode === name) { return id; } } @@ -170,8 +170,7 @@ class Blocks { for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; const block = this._blocks[id]; - if ((block.opcode === 'procedures_defnoreturn' || - block.opcode === 'procedures_defreturn') && + if (block.opcode === 'procedures_callnoreturn_internal' && block.mutation.proccode === name) { return JSON.parse(block.mutation.argumentnames); } diff --git a/src/engine/execute.js b/src/engine/execute.js index c74823ec6..a4bf76b2a 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -148,6 +148,8 @@ const execute = function (sequencer, thread) { // Recursively evaluate input blocks. for (const inputName in inputs) { if (!inputs.hasOwnProperty(inputName)) continue; + // Do not evaluate the internal custom command block within definition + if (inputName === 'custom_block') continue; const input = inputs[inputName]; const inputBlockId = input.block; // Is there no value for this input waiting in the stack frame? diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 2846f011a..0a126d67e 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -225,7 +225,9 @@ class Sequencer { // Look for warp-mode flag on definition, and set the thread // to warp-mode if needed. const definitionBlock = thread.target.blocks.getBlock(definition); - const doWarp = definitionBlock.mutation.warp; + const innerBlock = thread.target.blocks.getBlock( + definitionBlock.inputs.custom_block.block); + const doWarp = innerBlock.mutation.warp; if (doWarp) { thread.peekStackFrame().warpMode = true; } else if (isRecursive) { diff --git a/src/serialization/sb2.js b/src/serialization/sb2.js index 84560881a..5225614a4 100644 --- a/src/serialization/sb2.js +++ b/src/serialization/sb2.js @@ -481,14 +481,31 @@ const parseBlock = function (sb2block, getVariableId) { // Mutation for procedure definition: // store all 2.0 proc data. const procData = sb2block.slice(1); - activeBlock.mutation = { - tagName: 'mutation', - proccode: procData[0], // e.g., "abc %n %b %s" - argumentnames: JSON.stringify(procData[1]), // e.g. ['arg1', 'arg2'] - argumentdefaults: JSON.stringify(procData[2]), // e.g., [1, 'abc'] - warp: procData[3], // Warp mode, e.g., true/false. - children: [] + // Create a new block and input metadata. + const inputUid = uid(); + const inputName = 'custom_block'; + activeBlock.inputs[inputName] = { + name: inputName, + block: inputUid, + shadow: inputUid }; + activeBlock.children = [{ + id: inputUid, + opcode: 'procedures_callnoreturn_internal', + inputs: {}, + fields: {}, + next: null, + shadow: true, + children: [], + mutation: { + tagName: 'mutation', + proccode: procData[0], // e.g., "abc %n %b %s" + argumentnames: JSON.stringify(procData[1]), // e.g. ['arg1', 'arg2'] + argumentdefaults: JSON.stringify(procData[2]), // e.g., [1, 'abc'] + warp: procData[3], // Warp mode, e.g., true/false. + children: [] + } + }]; } else if (oldOpcode === 'call') { // Mutation for procedure call: // string for proc code (e.g., "abc %n %b %s"). From e8c5bbbf8072df5d41dd9dfb52055159f61e5527 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 10 Oct 2017 12:19:27 -0400 Subject: [PATCH 2/3] Fix tests and make chain more resilient --- src/engine/blocks.js | 21 +++++++++++++++++---- test/unit/engine_sequencer.js | 14 ++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 5b74cf55b..f25827b39 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -152,10 +152,12 @@ class Blocks { for (const id in this._blocks) { if (!this._blocks.hasOwnProperty(id)) continue; const block = this._blocks[id]; - if ((block.opcode === 'procedures_defnoreturn' || - block.opcode === 'procedures_defreturn') && - this._blocks[block.inputs.custom_block.block].mutation.proccode === name) { - return id; + if (block.opcode === 'procedures_defnoreturn' || + block.opcode === 'procedures_defreturn') { + const internal = this._getCustomBlockInternal(block); + if (internal && internal.mutation.proccode === name) { + return id; // The outer define block id + } } } return null; @@ -546,6 +548,17 @@ class Blocks { return params; } + /** + * Helper to get the corresponding internal procedure definition block + * @param {!object} defineBlock Outer define block. + * @return {!object} internal definition block which has the mutation. + */ + _getCustomBlockInternal (defineBlock) { + if (defineBlock.inputs && defineBlock.inputs.custom_block) { + return this._blocks[defineBlock.inputs.custom_block.block]; + } + } + /** * Helper to add a stack to `this._scripts`. * @param {?string} topBlockId ID of block that starts the script. diff --git a/test/unit/engine_sequencer.js b/test/unit/engine_sequencer.js index e5dcd0be7..76323e67c 100644 --- a/test/unit/engine_sequencer.js +++ b/test/unit/engine_sequencer.js @@ -153,9 +153,19 @@ test('stepToProcedure', t => { t.strictEquals(th.peekStack(), expectedBlock); s.stepToProcedure(th, 'faceCode'); t.strictEquals(th.peekStack(), expectedBlock); - s.stepToProcedure(th, 'faceCode'); - th.target.blocks.getBlock(th.stack[th.stack.length - 4]).mutation.proccode = 'othercode'; + + th.target.blocks.createBlock({ + id: 'internalId', + opcode: 'procedures_defnoreturn_internal', + mutation: { + proccode: 'othercode' + } + }); expectedBlock = th.stack[th.stack.length - 4]; + th.target.blocks.getBlock(expectedBlock).inputs.custom_block = { + type: 'custom_block', + block: 'internalId' + }; s.stepToProcedure(th, 'othercode'); t.strictEquals(th.peekStack(), expectedBlock); From 8d722b9073ff762e21e89e9932b6d9560cecc41a Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Tue, 10 Oct 2017 15:10:03 -0400 Subject: [PATCH 3/3] Fix opcode, which isn't actually used in the code... --- test/unit/engine_sequencer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/engine_sequencer.js b/test/unit/engine_sequencer.js index 76323e67c..abf7102d2 100644 --- a/test/unit/engine_sequencer.js +++ b/test/unit/engine_sequencer.js @@ -156,7 +156,7 @@ test('stepToProcedure', t => { th.target.blocks.createBlock({ id: 'internalId', - opcode: 'procedures_defnoreturn_internal', + opcode: 'procedures_callnoreturn_internal', mutation: { proccode: 'othercode' }