scratch-vm/src/blocks/scratch3_data.js

165 lines
5.3 KiB
JavaScript
Raw Normal View History

2017-04-17 15:10:04 -04:00
const Cast = require('../util/cast');
2017-04-17 19:42:48 -04:00
class Scratch3DataBlocks {
constructor (runtime) {
/**
* The runtime instantiating this block package.
* @type {Runtime}
*/
this.runtime = runtime;
}
/**
2017-04-17 19:42:48 -04:00
* Retrieve the block primitives implemented by this package.
* @return {object.<string, Function>} Mapping of opcode to Function.
*/
2017-04-17 19:42:48 -04:00
getPrimitives () {
return {
data_variable: this.getVariable,
data_setvariableto: this.setVariableTo,
data_changevariableby: this.changeVariableBy,
data_listcontents: this.getListContents,
data_addtolist: this.addToList,
data_deleteoflist: this.deleteOfList,
data_insertatlist: this.insertAtList,
data_replaceitemoflist: this.replaceItemOfList,
data_itemoflist: this.getItemOfList,
data_lengthoflist: this.lengthOfList,
data_listcontainsitem: this.listContainsItem
};
}
2017-04-17 19:42:48 -04:00
getVariable (args, util) {
const variable = util.target.lookupOrCreateVariable(
args.VARIABLE.id, args.VARIABLE.name);
2017-04-17 19:42:48 -04:00
return variable.value;
}
2017-04-17 19:42:48 -04:00
setVariableTo (args, util) {
const variable = util.target.lookupOrCreateVariable(
args.VARIABLE.id, args.VARIABLE.name);
2017-04-17 19:42:48 -04:00
variable.value = args.VALUE;
}
2017-04-17 19:42:48 -04:00
changeVariableBy (args, util) {
const variable = util.target.lookupOrCreateVariable(
args.VARIABLE.id, args.VARIABLE.name);
2017-04-17 19:42:48 -04:00
const castedValue = Cast.toNumber(variable.value);
const dValue = Cast.toNumber(args.VALUE);
variable.value = castedValue + dValue;
}
2017-04-17 19:42:48 -04:00
getListContents (args, util) {
const list = util.target.lookupOrCreateList(
args.LIST.id, args.LIST.name);
2017-04-17 19:42:48 -04:00
// Determine if the list is all single letters.
// If it is, report contents joined together with no separator.
// If it's not, report contents joined together with a space.
let allSingleLetters = true;
for (let i = 0; i < list.value.length; i++) {
const listItem = list.value[i];
2017-04-17 19:42:48 -04:00
if (!((typeof listItem === 'string') &&
(listItem.length === 1))) {
allSingleLetters = false;
break;
}
}
2017-04-17 19:42:48 -04:00
if (allSingleLetters) {
return list.value.join('');
2017-04-17 19:42:48 -04:00
}
return list.value.join(' ');
2017-04-17 19:42:48 -04:00
}
2017-04-17 19:42:48 -04:00
addToList (args, util) {
const list = util.target.lookupOrCreateList(
args.LIST.id, args.LIST.name);
if (list.value.length < Scratch3DataBlocks.LIST_ITEM_LIMIT) list.value.push(args.ITEM);
}
2017-04-17 19:42:48 -04:00
deleteOfList (args, util) {
const list = util.target.lookupOrCreateList(
args.LIST.id, args.LIST.name);
const index = Cast.toListIndex(args.INDEX, list.value.length);
2017-04-17 19:42:48 -04:00
if (index === Cast.LIST_INVALID) {
return;
} else if (index === Cast.LIST_ALL) {
list.value = [];
2017-04-17 19:42:48 -04:00
return;
}
list.value.splice(index - 1, 1);
}
2017-04-17 19:42:48 -04:00
insertAtList (args, util) {
const item = args.ITEM;
const list = util.target.lookupOrCreateList(
args.LIST.id, args.LIST.name);
const index = Cast.toListIndex(args.INDEX, list.value.length + 1);
2017-04-17 19:42:48 -04:00
if (index === Cast.LIST_INVALID) {
return;
}
const listLimit = Scratch3DataBlocks.LIST_ITEM_LIMIT;
if (index > listLimit) return;
list.value.splice(index - 1, 0, item);
if (list.value.length > listLimit) {
// If inserting caused the list to grow larger than the limit,
// remove the last element in the list
list.value.pop();
}
}
2017-04-17 19:42:48 -04:00
replaceItemOfList (args, util) {
const item = args.ITEM;
const list = util.target.lookupOrCreateList(
args.LIST.id, args.LIST.name);
const index = Cast.toListIndex(args.INDEX, list.value.length);
2017-04-17 19:42:48 -04:00
if (index === Cast.LIST_INVALID) {
return;
}
list.value.splice(index - 1, 1, item);
}
2017-04-17 19:42:48 -04:00
getItemOfList (args, util) {
const list = util.target.lookupOrCreateList(
args.LIST.id, args.LIST.name);
const index = Cast.toListIndex(args.INDEX, list.value.length);
2017-04-17 19:42:48 -04:00
if (index === Cast.LIST_INVALID) {
return '';
}
return list.value[index - 1];
2017-04-17 19:42:48 -04:00
}
2017-04-17 19:42:48 -04:00
lengthOfList (args, util) {
const list = util.target.lookupOrCreateList(
args.LIST.id, args.LIST.name);
return list.value.length;
}
2017-04-17 19:42:48 -04:00
listContainsItem (args, util) {
const item = args.ITEM;
const list = util.target.lookupOrCreateList(
args.LIST.id, args.LIST.name);
if (list.value.indexOf(item) >= 0) {
return true;
}
2017-04-17 19:42:48 -04:00
// Try using Scratch comparison operator on each item.
// (Scratch considers the string '123' equal to the number 123).
for (let i = 0; i < list.value.length; i++) {
if (Cast.compare(list.value[i], item) === 0) {
2017-04-17 19:42:48 -04:00
return true;
}
}
return false;
}
/**
* Type representation for list variables.
* @const {string}
*/
static get LIST_ITEM_LIMIT () {
return 200000;
}
2017-04-17 19:42:48 -04:00
}
module.exports = Scratch3DataBlocks;