Fix some smaller bugs

This commit is contained in:
Thomas Weber committed 2020-08-03 22:53:36 -05:00
1 parent 921022f33f
commit 235e2a00cd
8 files changed
+99 -76

No files matched your search

+25 -23
View File
@@ -27,6 +27,14 @@ const compatBlocks = require('./compat-blocks');
* @property {string} kind
*/
const createVariableData = (scope, varObj) => ({
scope,
// todo: maybe just return varObj
id: varObj.id,
name: varObj.name,
isCloud: varObj.isCloud
});
class ScriptTreeGenerator {
constructor (thread) {
this.thread = thread;
@@ -1029,29 +1037,32 @@ class ScriptTreeGenerator {
return result;
}
descendVariable (block, name, type) {
// todo: cache variables by ID
const variable = block.fields[name];
descendVariable (block, fieldName, type) {
const variable = block.fields[fieldName];
const id = variable.id;
if (this.variableCache.hasOwnProperty(id)) {
return this.variableCache[id];
}
const data = this.variableCache[id] = this._descendVariable(id, variable.value, type);
this.variableCache[id] = data;
return data;
}
_descendVariable (id, name, type) {
const target = this.target;
const stage = this.stage;
// Look for by ID in target...
if (target.variables.hasOwnProperty(id)) {
return {
scope: 'target',
id
};
return createVariableData('target', target.variables[id]);
}
// Look for by ID in stage...
if (!target.isStage) {
if (stage && stage.variables.hasOwnProperty(id)) {
return {
scope: 'stage',
id
};
return createVariableData('stage', stage.variables[id]);
}
}
@@ -1060,10 +1071,7 @@ class ScriptTreeGenerator {
if (target.variables.hasOwnProperty(varId)) {
const currVar = target.variables[varId];
if (currVar.name === name && currVar.type === type) {
return {
scope: 'target',
id: varId
};
return createVariableData('target', currVar);
}
}
}
@@ -1074,10 +1082,7 @@ class ScriptTreeGenerator {
if (stage.variables.hasOwnProperty(varId)) {
const currVar = stage.variables[varId];
if (currVar.name === name && currVar.type === type) {
return {
sccope: 'stage',
id: varId
};
return createVariableData('stage', currVar);
}
}
}
@@ -1086,10 +1091,7 @@ class ScriptTreeGenerator {
// Create it locally...
const newVariable = new Variable(id, name, type, false);
target.variables[id] = newVariable;
return {
scope: 'target',
id: id
};
return createVariableData('target', newVariable);
}
descendCompatLayer (block) {
+24 -24
View File
@@ -1,42 +1,42 @@
const stacked = [
'control_clear_counter',
'control_get_counter',
'control_incr_counter',
'control_clear_counter',
'motion_glideto',
'motion_glidesecstoxy',
'motion_goto',
'sound_play',
'sound_playuntildone',
'sound_stopallsounds',
'sound_seteffectto',
'sound_changeeffectby',
'sound_cleareffects',
'sound_setvolumeto',
'sensing_askandwait',
'sound_seteffectto',
'sound_changeeffectby',
'sound_changevolumeby',
'looks_nextcostume',
'looks_changeeffectby',
'looks_nextbackdrop',
'looks_nextcostume',
'looks_say',
'looks_sayforsecs',
'looks_think',
'looks_changeeffectby',
'looks_seteffectto',
'looks_think',
'looks_thinkforsecs',
'motion_glidesecstoxy',
'motion_glideto',
'motion_goto',
'motion_pointtowards',
'sensing_askandwait',
'sensing_setdragmode',
'motion_pointtowards'
'sound_changeeffectby',
'sound_changeeffectby',
'sound_changevolumeby',
'sound_cleareffects',
'sound_play',
'sound_playuntildone',
'sound_seteffectto',
'sound_seteffectto',
'sound_setvolumeto',
'sound_stopallsounds'
];
const inputs = [
'sound_volume',
'sensing_of',
'sensing_distanceto',
'sensing_answer',
'sensing_current',
'sensing_dayssince2000',
'sensing_loudness',
'sensing_distanceto',
'sensing_loud',
'sensing_answer'
'sensing_loudness',
'sensing_of',
'sound_volume'
];
module.exports = {
+1 -1
View File
@@ -5,7 +5,7 @@ const compile = thread => {
const astGenerator = new ASTGenerator(thread);
const ast = astGenerator.generate();
const jsGenerator = new JSGenerator(ast);
const jsGenerator = new JSGenerator(ast, thread.target);
const js = jsGenerator.compile();
return js;
+9 -6
View File
@@ -3,8 +3,17 @@ const Timer = require('../util/timer');
const Cast = require('../util/cast');
const log = require('../util/log');
/* eslint-disable no-unused-vars */
const compatibilityLayerBlockUtility = require('./compat-block-utility');
/**
* The currently running thread.
* @type {Thread}
*/
var thread;
// All the functions defined here will be available to compiled scripts.
// The JSDoc annotations define the function's contract.
// Most of these functions are only used at runtime by generated scripts. Despite what your editor may say, they are not unused.
@@ -443,12 +452,6 @@ const mod = (n, modulus) => {
return result;
};
/**
* The currently running thread.
* @type {Thread}
*/
var thread;
/**
* Step a compiled thread.
* @param {Thread} _thread
+36 -18
View File
@@ -120,9 +120,10 @@ class ConstantInput {
}
class ScriptCompiler {
constructor (script, ast) {
constructor (script, ast, target) {
this.script = script;
this.ast = ast;
this.target = target;
this.source = '';
this.localVariables = new VariablePool('a');
this._setupVariablesPool = new VariablePool('b');
@@ -131,7 +132,7 @@ class ScriptCompiler {
/**
* @param {object} node Input node to compile.
* @returns {Input}
* @returns {Input} Compiled input.
*/
descendInput (node) {
switch (node.kind) {
@@ -144,8 +145,7 @@ class ScriptCompiler {
return new TypedInput(`(${this.generateCompatCall(node)})`, TYPE_UNKNOWN);
case 'constant':
// todo: converting to number sometimes break things, need to check for those conditions
return new ConstantInput(node.value);
return this.safeConstantInput(node.value);
case 'list.contains':
return new TypedInput(`listContains(${this.referenceVariable(node.list)}, ${this.descendInput(node.item).asUnknown()})`, TYPE_BOOLEAN);
@@ -287,7 +287,6 @@ class ScriptCompiler {
this.source += `runtime.ext_scratch3_control._createClone(${this.descendInput(node.target).asString()}, target);\n`;
break;
case 'control.deleteClone':
// TODO: actually stop thread
this.source += 'if (!target.isOriginal) {\n';
this.source += ' runtime.disposeTarget(target);\n';
this.source += ' runtime.stopForTarget(target);\n';
@@ -373,16 +372,16 @@ class ScriptCompiler {
this.source += `yield* waitThreads(startHats("event_whenbroadcastreceived", { BROADCAST_OPTION: ${this.descendInput(node.broadcast).asString()} }));\n`;
break;
case 'list.add':
this.source += `${this.referenceVariable(node.list)}.value.push(${this.descendInput(node.item).asUnknown()});\n`;
// todo _monitorUpToDate
case 'list.add': {
const list = this.referenceVariable(node.list);
this.source += `${list}._monitorUpToDate = false;\n`;
break;
}
case 'list.delete':
this.source += `listDelete(${this.referenceVariable(node.list)}, ${this.descendInput(node.index).asUnknown()});\n`;
break;
case 'list.deleteAll':
this.source += `${this.referenceVariable(node.list)}.value = [];\n`;
// todo _monitorUpToDate
break;
case 'list.hide':
this.source += `runtime.monitorBlocks.changeBlock({ id: "${sanitize(node.list.id)}", element: "checkbox", value: false }, runtime);\n`;
@@ -424,7 +423,7 @@ class ScriptCompiler {
this.source += 'runtime.ext_scratch3_looks._renderBubble(target);\n';
break;
case 'looks.switchBackdrop':
this.source += `runtime.ext_scratch3_looks._setBackdrop(stage, ${this.descendInput(node.backdrop)});\n`;
this.source += `runtime.ext_scratch3_looks._setBackdrop(stage, ${this.descendInput(node.backdrop).asUnknown()});\n`;
break;
case 'looks.switchCostume':
this.source += `runtime.ext_scratch3_looks._setCostume(target, ${this.descendInput(node.costume).asUnknown()});\n`;
@@ -512,18 +511,23 @@ class ScriptCompiler {
case 'var.change': {
const variable = this.referenceVariable(node.variable);
// todo: cloud
this.source += `${variable}.value = (+${variable}.value || 0) + ${this.descendInput(node.value).asNumber()};\n`;
if (node.variable.isCloud) {
this.source += `ioQuery("cloud", "requestUpdateVariable", ["${sanitize(node.variable.name)}", ${variable}.value]);\n`;
}
break;
}
case 'var.hide':
this.source += `runtime.monitorBlocks.changeBlock({ id: "${sanitize(node.variable.id)}", element: "checkbox", value: false }, runtime);\n`;
break;
case 'var.set':
// todo: cloud
this.source += `${this.referenceVariable(node.variable)}.value = ${this.descendInput(node.value).asUnknown()};\n`;
case 'var.set': {
const variable = this.referenceVariable(node.variable);
this.source += `${variable}.value = ${this.descendInput(node.value).asUnknown()};\n`;
if (node.variable.isCloud) {
this.source += `ioQuery("cloud", "requestUpdateVariable", ["${sanitize(node.variable.name)}", ${variable}.value]);\n`;
}
break;
}
case 'var.show':
this.source += `runtime.monitorBlocks.changeBlock({ id: "${sanitize(node.variable.id)}", element: "checkbox", value: true }, runtime);\n`;
break;
@@ -541,7 +545,6 @@ class ScriptCompiler {
}
referenceVariable (variable) {
// todo: factoryVariables
if (variable.scope === 'target') {
return this.evaluateOnce(`target.variables["${sanitize(variable.id)}"]`);
}
@@ -567,6 +570,20 @@ class ScriptCompiler {
}
}
safeConstantInput (value) {
if (typeof value === 'string') {
if (this.isNameOfCostume(value)) {
return new TypedInput(`"${sanitize(value)}"`, TYPE_STRING);
}
}
return new ConstantInput(value);
}
isNameOfCostume (stringValue) {
// todo: also check backdrop
return this.target.getCostumeIndexByName(stringValue) !== -1;
}
generateCompatCall (node) {
const opcode = node.opcode;
@@ -650,8 +667,9 @@ disableToString(TypedInput.prototype.asBoolean);
disableToString(TypedInput.prototype.asUnknown);
class JSCompiler {
constructor (ast) {
constructor (ast, target) {
this.ast = ast;
this.target = target;
this.compilingProcedures = [];
this.compiledProcedures = {};
}
@@ -676,7 +694,7 @@ class JSCompiler {
this.compilingProcedures.pop();
}
const compiler = new ScriptCompiler(script, this.ast);
const compiler = new ScriptCompiler(script, this.ast, this.target);
return compiler.compile();
}
+2 -2
View File
@@ -2,7 +2,7 @@ class VariablePool {
/**
* @param {string} prefix The prefix at the start of the variable name.
*/
constructor(prefix) {
constructor (prefix) {
if (prefix.trim().length === 0) {
throw new Error('prefix cannot be empty');
}
@@ -13,7 +13,7 @@ class VariablePool {
this.count = 0;
}
next() {
next () {
return `${this.prefix}${this.count++}`;
}
}
+1 -1
View File
@@ -362,7 +362,7 @@ class Sequencer {
thread.requestScriptGlowInFrame = false;
thread.status = Thread.STATUS_DONE;
if (thread.isCompiled) {
thread.procedures = {};
thread.procedures = null;
thread.generator = null;
}
}
+1 -1
View File
@@ -209,7 +209,7 @@ class Thread {
/**
* @type {Object.<string, import('../compiler/compiler').CompiledScript>}
*/
this.procedures = {};
this.procedures = null;
}
/**