mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-01-08 14:01:58 -05:00
Add framework for block execution
The runtime now stores a mapping of opcode to function. The `wedo2` and `scratch3` packages are currently stubs.
This commit is contained in:
parent
f90fccb0d1
commit
27c06ce476
4 changed files with 98 additions and 4 deletions
14
src/blocks/scratch3.js
Normal file
14
src/blocks/scratch3.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
function Scratch3Blocks() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the block primitives implemented by this package.
|
||||
* @return {Object.<string, Function>} Mapping of opcode to Function.
|
||||
*/
|
||||
Scratch3Blocks.prototype.getPrimitives = function() {
|
||||
return {
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = Scratch3Blocks;
|
14
src/blocks/wedo2.js
Normal file
14
src/blocks/wedo2.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
function WeDo2Blocks() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the block primitives implemented by this package.
|
||||
* @return {Object.<string, Function>} Mapping of opcode to Function.
|
||||
*/
|
||||
WeDo2Blocks.prototype.getPrimitives = function() {
|
||||
return {
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = WeDo2Blocks;
|
|
@ -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.<string, Function>}
|
||||
*/
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue