From 27c06ce4766f348a8c280f53e51e11047c4ea84b Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Mon, 2 May 2016 09:20:27 -0700 Subject: [PATCH] Add framework for block execution The runtime now stores a mapping of opcode to function. The `wedo2` and `scratch3` packages are currently stubs. --- src/blocks/scratch3.js | 14 +++++++++++ src/blocks/wedo2.js | 14 +++++++++++ src/engine/runtime.js | 54 +++++++++++++++++++++++++++++++++++++++++ src/engine/sequencer.js | 20 ++++++++++++--- 4 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 src/blocks/scratch3.js create mode 100644 src/blocks/wedo2.js diff --git a/src/blocks/scratch3.js b/src/blocks/scratch3.js new file mode 100644 index 000000000..b035b994c --- /dev/null +++ b/src/blocks/scratch3.js @@ -0,0 +1,14 @@ + +function Scratch3Blocks() { +} + +/** + * Retrieve the block primitives implemented by this package. + * @return {Object.} Mapping of opcode to Function. + */ +Scratch3Blocks.prototype.getPrimitives = function() { + return { + }; +}; + +module.exports = Scratch3Blocks; diff --git a/src/blocks/wedo2.js b/src/blocks/wedo2.js new file mode 100644 index 000000000..cc33b9ab6 --- /dev/null +++ b/src/blocks/wedo2.js @@ -0,0 +1,14 @@ + +function WeDo2Blocks() { +} + +/** + * Retrieve the block primitives implemented by this package. + * @return {Object.} Mapping of opcode to Function. + */ +WeDo2Blocks.prototype.getPrimitives = function() { + return { + }; +}; + +module.exports = WeDo2Blocks; diff --git a/src/engine/runtime.js b/src/engine/runtime.js index c8b398820..1cc1a7de8 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -3,6 +3,11 @@ var Sequencer = require('./sequencer'); var Thread = require('./thread'); var util = require('util'); +var defaultBlockPackages = { + 'scratch3': require('../blocks/scratch3'), + 'wedo2': require('../blocks/wedo2') +}; + /** * Manages blocks, stacks, and the sequencer. */ @@ -34,6 +39,14 @@ function Runtime () { /** @type {!Sequencer} */ this.sequencer = new Sequencer(this); + + /** + * Map to look up a block primitive's implementation function by its opcode. + * This is a two-step lookup: package name first, then primitive name. + * @type {Object.} + */ + this._primitives = {}; + this._registerBlockPackages(); } /** @@ -184,6 +197,37 @@ Runtime.prototype.deleteBlock = function (e) { // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- +/** + * Register default block packages with this runtime. + * @todo Prefix opcodes with package name. + * @private + */ +Runtime.prototype._registerBlockPackages = function () { + for (var packageName in defaultBlockPackages) { + if (defaultBlockPackages.hasOwnProperty(packageName)) { + var packageObject = new (defaultBlockPackages[packageName])(); + var packageContents = packageObject.getPrimitives(); + for (var op in packageContents) { + if (packageContents.hasOwnProperty(op)) { + this._primitives[op] = packageContents[op]; + } + } + } + } +}; + +/** + * Retrieve the function associated with the given opcode. + * @param {!string} opcode The opcode to look up. + * @return {Function} The function which implements the opcode. + */ +Runtime.prototype.getOpcodeFunction = function (opcode) { + return this._primitives[opcode]; +}; + +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- + /** * Create a thread and push it to the list of threads. * @param {!string} id ID of block that starts the stack @@ -306,4 +350,14 @@ Runtime.prototype._getSubstack = function (id) { return this.blocks[id].fields['SUBSTACK']; }; +/** + * Helper to get the opcode for a particular block + * @param {?string} id ID of block to query + * @return {?string} the opcode corresponding to that block + */ +Runtime.prototype._getOpcode = function (id) { + if (typeof this.blocks[id] === 'undefined') return null; + return this.blocks[id].opcode; +}; + module.exports = Runtime; diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 350283e18..865d9744b 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -58,10 +58,22 @@ Sequencer.prototype.stepThreads = function (threads) { * @param {!Thread} thread Thread object to step */ Sequencer.prototype.stepThread = function (thread) { - // @todo Actually run the blocks - // Currently goes to the next block in the sequence. - var nextBlock = this.runtime._getNextBlock(thread.nextBlock); - thread.nextBlock = nextBlock; + var opcode = this.runtime._getOpcode(thread.nextBlock); + + if (!opcode) { + console.log('Could not get opcode for block: ' + thread.nextBlock); + } + else { + var blockFunction = this.runtime.getOpcodeFunction(opcode); + if (!blockFunction) { + console.log('Could not get implementation for opcode: ' + opcode); + } + else { + blockFunction(); + } + } + + thread.nextBlock = this.runtime._getNextBlock(thread.nextBlock); }; module.exports = Sequencer;