積木代碼編寫
Blockly應(yīng)用程序需要將積木轉(zhuǎn)換為代碼來執(zhí)行。添加積木JSON定義后墨缘,需轉(zhuǎn)到generators/目錄并選擇與您要生成的語言( JavaScript, Python, PHP颈娜, Lua, Dart等)相對(duì)應(yīng)的子目錄浙宜,編寫積木執(zhí)行代碼揭鳞。
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];
};
任何積木的代碼生成器需要生成參數(shù)和元素?cái)?shù)據(jù)。通常使用幾種函數(shù)輔助獲劝鹉巍:
getFieldValue野崇、valueToCode、statementToCode
getFieldValue
block.getFieldValue('END')
此函數(shù)從指定名稱的元素中返回值亩钟。
- 對(duì)于文本元素乓梨,此函數(shù)返回輸入的文本。例如“ Hello World”清酥。
- 如果是下拉菜單扶镀,此函數(shù)將返回與所選選項(xiàng)關(guān)聯(lián)的語言無關(guān)的文本。
- 對(duì)于變量下拉列表焰轻,此函數(shù)返回變量下拉列表的對(duì)應(yīng)的名稱臭觉。
要獲取生成的代碼中使用的Blockly變量名稱,需使用以下調(diào)用方式:
Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
valueToCode
Blockly.JavaScript.valueToCode(block, 'FROM', Blockly.JavaScript.ORDER_ADDITION) || '0'
此函數(shù)查找block值輸入('FROM')的文本辱志,然后將文本作為字符串返回蝠筑。在未卡合輸入的情況下,此函數(shù)返回null揩懒,這就是為什么通常在函數(shù)后加上布爾值“或”和默認(rèn)值的原因什乙。因此,在上面的示例中已球,如果沒有積木附加到名為“ FROM”的輸入臣镣,則此輸入的默認(rèn)代碼將為字符串“ 0”。
第三個(gè)參數(shù)指定嵌入所需的操作信息的順序智亮。每種語言生成器都有一個(gè)優(yōu)先順序列表忆某。
statementToCode
Blockly.JavaScript.statementToCode(block, 'DO')
此函數(shù)查找卡合到指定語句輸入的嵌套積木堆棧,為該堆棧生成代碼阔蛉,縮進(jìn)代碼弃舒,然后將代碼作為字符串返回。如果未卡合輸入馍忽,此函數(shù)將返回一個(gè)空字符串棒坏。
并行化
Blockly并不提供腳本的執(zhí)行的方法燕差,而是提供將腳本轉(zhuǎn)為指定的高級(jí)語言,由用戶執(zhí)行高級(jí)語言坝冕,從而完成腳本的執(zhí)行徒探。
串行程序
大多數(shù)Blockly應(yīng)用程序都是串行程序。用戶將按積木堆疊順序執(zhí)行喂窟。
工作空間中的每個(gè)(非禁用)積木都將構(gòu)成程序的一部分测暗。如果有多個(gè)堆棧積木,則首先執(zhí)行較高的堆棧磨澡。
工作空間可以隨時(shí)導(dǎo)出為可執(zhí)行代碼碗啄。此代碼可以在JavaScript的客戶端(使用eval或JS Interpreter)執(zhí)行,也可以在服務(wù)器端以任何語言執(zhí)行稳摄。
下面是獲取JavaScript代碼稚字。
//獲取代碼
var code = Blockly.JavaScript.workspaceToCode(demoWorkspace);
//執(zhí)行代碼
eval(code);
并行程序
一些Blockly應(yīng)用程序選擇并行而非串行執(zhí)行所有積木堆棧。例如音樂應(yīng)用程序厦酬,其中鼓循環(huán)與旋律同時(shí)運(yùn)行胆描。
實(shí)現(xiàn)并行執(zhí)行的一種方法是使用Hat積木生成多個(gè)代碼段:
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);
}
如果目標(biāo)語言是JavaScript,則可以使用該數(shù)組創(chuàng)建多個(gè)JS解釋器以同時(shí)執(zhí)行仗阅。
事件驅(qū)動(dòng)程序
事件處理程序只是由系統(tǒng)而不是由程序調(diào)用的函數(shù)昌讲。一些開發(fā)人員喜歡在事件積木的頂部添加一個(gè)“帽子”,以使它們看起來與其他積木不同减噪。這不是Blockly的默認(rèn)外觀短绸,但可以通過設(shè)置Blockly.BlockSvg.START_HAT = true;或添加主題并在block style上設(shè)置hat選項(xiàng)來添加。
JS Interpreter
JS-Interpreter 是用 JavaScript寫的具有沙箱環(huán)境的JavaScript 解析器筹裕。 它可以讓你任意的, 一行一行地執(zhí)行JavaScript 代碼醋闭。它的執(zhí)行過程與主要的 JavaScript 代碼環(huán)境是分離開的,JS-Interpreter 的多個(gè)實(shí)例可以允許多線程并發(fā)JavaScript, 而無需使用Web Workers饶碘。
在執(zhí)行積木堆棧時(shí)目尖,有時(shí)需要執(zhí)行的速度較慢,單步執(zhí)行扎运,每執(zhí)行一條js,積木高亮顯示饮戳,更容易發(fā)現(xiàn)積木執(zhí)行位置豪治,觀察整個(gè)執(zhí)行過程,可以使用JS Interpreter配合積木的執(zhí)行扯罐。
使用方法
引入這兩個(gè) JavaScript 源代碼
<script src="acorn.js"></script>
<script src="interpreter.js"></script>
然后, 實(shí)例化一個(gè) interpreter, 并且把你需要還原的 JavaScript 代碼放進(jìn)去负拟。
var myCode = 'var a=1; for(var i=0;i<4;i++){a*=i;} a;';
var myInterpreter = new Interpreter(myCode);
為了去一步一步地跑這些代碼, 需要重復(fù)地去調(diào)用 step 函數(shù), 直到它返回 false
function nextStep() {
if (myInterpreter.step()) {
window.setTimeout(nextStep, 0);
}
}
nextStep();
或者, 如果已知代碼里面沒有死循環(huán), 則可以直接調(diào)用 run 函數(shù)執(zhí)行一次完成全部的 step
myInterpreter.run();
API createNativeFunction的調(diào)用可以在創(chuàng)建的時(shí)候被添加到 interpreter, 下面是添加了 函數(shù)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結(jié)合積木使用
積木堆棧執(zhí)行時(shí)歹河,先生成代碼掩浙,代碼執(zhí)行的過程中會(huì)通過JS Interpreter調(diào)用wrapper函數(shù)花吟,對(duì)應(yīng)的會(huì)設(shè)置highlightBlock函數(shù),從而設(shè)置積木行為厨姚。
//綁定積木code執(zhí)行highlightBlock時(shí)衅澈,調(diào)用wrapper函數(shù)
var wrapper = function(id) {
id = id ? id.toString() : '';
return interpreter.createPrimitive(highlightBlock(id));
};
interpreter.setProperty(scope, 'highlightBlock',
interpreter.createNativeFunction(wrapper));
//設(shè)置積木高亮顯示
function highlightBlock(id) {
demoWorkspace.highlightBlock(id);
highlightPause = true;
}