积木代码编写
Blockly应用程序需要将积木转换为代码来执行。添加积木JSON定义后,需转到generators/目录并选择与您要生成的语言( JavaScript, Python, PHP, Lua, Dart等)相对应的子目录,编写积木执行代码。
Blockly.JavaScript['text_indexOf'] = function(block) {
// Search the text for a substring.
var operator = block.getFieldValue('END') == 'FIRST' ? 'indexOf' : 'lastIndexOf';
var subString = Blockly.JavaScript.valueToCode(block, 'FIND',
Blockly.JavaScript.ORDER_NONE) || '\'\'';
var text = Blockly.JavaScript.valueToCode(block, 'VALUE',
Blockly.JavaScript.ORDER_MEMBER) || '\'\'';
var code = text + '.' + operator + '(' + subString + ')';
return [code, Blockly.JavaScript.ORDER_MEMBER];
};
任何积木的代码生成器需要生成参数和元素数据。通常使用几种函数辅助获取:
getFieldValue、valueToCode、statementToCode
getFieldValue
block.getFieldValue('END')
此函数从指定名称的元素中返回值。
- 对于文本元素,此函数返回输入的文本。例如“ Hello World”。
- 如果是下拉菜单,此函数将返回与所选选项关联的语言无关的文本。
- 对于变量下拉列表,此函数返回变量下拉列表的对应的名称。
要获取生成的代码中使用的Blockly变量名称,需使用以下调用方式:
Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
valueToCode
Blockly.JavaScript.valueToCode(block, 'FROM', Blockly.JavaScript.ORDER_ADDITION) || '0'
此函数查找block值输入('FROM')的文本,然后将文本作为字符串返回。在未卡合输入的情况下,此函数返回null,这就是为什么通常在函数后加上布尔值“或”和默认值的原因。因此,在上面的示例中,如果没有积木附加到名为“ FROM”的输入,则此输入的默认代码将为字符串“ 0”。
第三个参数指定嵌入所需的操作信息的顺序。每种语言生成器都有一个优先顺序列表。
statementToCode
Blockly.JavaScript.statementToCode(block, 'DO')
此函数查找卡合到指定语句输入的嵌套积木堆栈,为该堆栈生成代码,缩进代码,然后将代码作为字符串返回。如果未卡合输入,此函数将返回一个空字符串。
并行化
Blockly并不提供脚本的执行的方法,而是提供将脚本转为指定的高级语言,由用户执行高级语言,从而完成脚本的执行。
串行程序
大多数Blockly应用程序都是串行程序。用户将按积木堆叠顺序执行。
串行程序 -c
工作空间中的每个(非禁用)积木都将构成程序的一部分。如果有多个堆栈积木,则首先执行较高的堆栈。
工作空间可以随时导出为可执行代码。此代码可以在JavaScript的客户端(使用eval或JS Interpreter)执行,也可以在服务器端以任何语言执行。
下面是获取JavaScript代码。
//获取代码
var code = Blockly.JavaScript.workspaceToCode(demoWorkspace);
//执行代码
eval(code);
并行程序
一些Blockly应用程序选择并行而非串行执行所有积木堆栈。例如音乐应用程序,其中鼓循环与旋律同时运行。
实现并行执行的一种方法是使用Hat积木生成多个代码段:
var xml = Blockly.Xml.workspaceToDom(workspace);
// Find and remove all top blocks.
var topBlocks = [];
for (var i = xml.childNodes.length - 1, node; block = xml.childNodes[i]; i--) {
if (block.tagName == 'BLOCK') {
xml.removeChild(block);
topBlocks.unshift(block);
}
}
// Add each top block one by one and generate code.
var allCode = [];
for (var i = 0, block; block = topBlocks[i]; i++) {
var headless = new Blockly.Workspace();
xml.appendChild(block);
Blockly.Xml.domToWorkspace(xml, headless);
allCode.push(Blockly.JavaScript.workspaceToCode(headless));
headless.dispose();
xml.removeChild(block);
}
如果目标语言是JavaScript,则可以使用该数组创建多个JS解释器以同时执行。
事件驱动程序
事件处理程序只是由系统而不是由程序调用的函数。一些开发人员喜欢在事件积木的顶部添加一个“帽子”,以使它们看起来与其他积木不同。这不是Blockly的默认外观,但可以通过设置Blockly.BlockSvg.START_HAT = true;或添加主题并在block style上设置hat选项来添加。
帽子积木 -c
JS Interpreter
JS-Interpreter 是用 JavaScript写的具有沙箱环境的JavaScript 解析器。 它可以让你任意的, 一行一行地执行JavaScript 代码。它的执行过程与主要的 JavaScript 代码环境是分离开的,JS-Interpreter 的多个实例可以允许多线程并发JavaScript, 而无需使用Web Workers。
在执行积木堆栈时,有时需要执行的速度较慢,单步执行,每执行一条js,积木高亮显示,更容易发现积木执行位置,观察整个执行过程,可以使用JS Interpreter配合积木的执行。
使用方法
引入这两个 JavaScript 源代码
<script src="acorn.js"></script>
<script src="interpreter.js"></script>
然后, 实例化一个 interpreter, 并且把你需要还原的 JavaScript 代码放进去。
var myCode = 'var a=1; for(var i=0;i<4;i++){a*=i;} a;';
var myInterpreter = new Interpreter(myCode);
为了去一步一步地跑这些代码, 需要重复地去调用 step 函数, 直到它返回 false
function nextStep() {
if (myInterpreter.step()) {
window.setTimeout(nextStep, 0);
}
}
nextStep();
或者, 如果已知代码里面没有死循环, 则可以直接调用 run 函数执行一次完成全部的 step
myInterpreter.run();
API createNativeFunction的调用可以在创建的时候被添加到 interpreter, 下面是添加了 函数alert() 和 变量 url。
var initFunc = function(interpreter, scope) {
interpreter.setProperty(scope, 'url', String(location));
var wrapper = function(text) {
return alert(text);
};
interpreter.setProperty(scope, 'alert',
interpreter.createNativeFunction(wrapper));
};
var myInterpreter = new Interpreter(myCode, initFunc);
JS Interpreter结合积木使用
积木堆栈执行时,先生成代码,代码执行的过程中会通过JS Interpreter调用wrapper函数,对应的会设置highlightBlock函数,从而设置积木行为。
//绑定积木code执行highlightBlock时,调用wrapper函数
var wrapper = function(id) {
id = id ? id.toString() : '';
return interpreter.createPrimitive(highlightBlock(id));
};
interpreter.setProperty(scope, 'highlightBlock',
interpreter.createNativeFunction(wrapper));
//设置积木高亮显示
function highlightBlock(id) {
demoWorkspace.highlightBlock(id);
highlightPause = true;
}
网友评论