Generating Code
大多數塊應用程序需要將塊轉換爲執行代碼。本頁介紹如何將代碼生成器添加到自定義塊。
首先,轉到generators/目錄並選擇與要生成的語言相對應的子目錄(JavaScript、Python、PHP、Lua、Dart等)。假設您的塊不適合現有的類別,則創建一個新的JavaScript文件。這個新的JavaScript文件需要包含在編輯器HTML文件的<script…>標記列表中。
典型的塊代碼生成器如下所示:
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];
};
Collecting the Arguments
任何塊的代碼生成器的第一個任務是收集所有參數和字段數據。此任務通常使用以下幾個功能:
getFieldValue
block.getFieldValue('END')
對於文本字段,此函數返回鍵入的文本。E、 g.“Hello World”。
在下拉列表的情況下,此函數返回與所選選項關聯的語言中性文本。一個英文塊可能有一個選擇了“first”的下拉列表,而在德語中,同一個下拉列表將顯示“erste”。代碼生成器不必知道所有可能的人類語言,因此getFieldValue函數將返回在創建下拉列表時指定的語言中性文本(Blockly的核心塊通常使用大寫的英語單詞,例如“FIRST”)。
對於變量下拉列表,此函數返回變量下拉列表的面向用戶的名稱。需要注意的是,該名稱不一定與生成代碼中使用的變量名稱相同。例如,變量名“For”在Blockly中是合法的,但在大多數語言中會與保留字衝突,因此會重命名爲“for2”。同樣地,阿拉伯語變量名“متغي”在塊中是合法的,但在大多數語言中是非法的,因此將被重命名爲“_D9_85_D8_AA_D8_BA_D9_8A_D8_B1”。要獲取生成代碼中可能使用的塊變量名,請使用以下調用:
Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
注意,JavaScript應該更改爲適當的語言(Python、PHP、Lua、Dart等),因爲每種語言都有不同的保留字列表。
valueToCode
Blockly.JavaScript.valueToCode(block, 'FROM', Blockly.JavaScript.ORDER_ADDITION) || '0'
此函數用於查找連接到命名值輸入(“FROM”)的塊,生成該塊的代碼,並將代碼作爲字符串返回。如果輸入未連接,則此函數返回空值,這就是爲什麼通常使用布爾值“或”和默認值跟隨函數的原因。因此,在上面的示例中,如果沒有塊附加到名爲“FROM”的輸入,則此輸入的默認代碼將是字符串“0”。
第三個參數指定嵌入所需的操作信息的順序。每個語言生成器都有一個有序的引用列表。ValueToCu碼函數需要傳遞與將應用於返回代碼的最大力相對應的順序值。這允許valueToCode在需要時將代碼括在圓括號中。有關詳細信息,請參閱“運算符優先級”頁。
注意,JavaScript應該更改爲適當的語言(Python、PHP、Lua、Dart等)。
statementToCode
Blockly.JavaScript.statementToCode(block, 'DO')
此函數用於查找連接到指定語句輸入的嵌套塊堆棧,生成該堆棧的代碼,縮進代碼,並將代碼作爲字符串返回。如果輸入未連接,此函數將返回空字符串。
注意,JavaScript應該更改爲適當的語言(Python、PHP、Lua、Dart等)。
Assembling the Code
收集完所有參數後,就可以彙編最後的代碼了。大多數街區都是直行的。下面是while循環的一個示例:
var code = 'while (' + argument0 + ') {\n' + branch0 + '}\n';
return code;
然後,語句塊(不返回值的語句塊)可以返回代碼而無需進一步ado:
值塊(那些返回值的塊)要複雜一些。下面是一個基本算術運算符(加號、減號等)的示例:
var code = argument0 + ' ' + operator + ' ' + argument1;
這個例子說明了一個操作順序問題。考慮兩個連接的算術塊形成表達式(2*(3+4))的情況。使用上面截取的代碼,加法塊將返回字符串“3+4”,而乘法塊將此作爲輸入返回“2*3+4”。這個結果是不正確的,因爲在執行時3將更緊密地綁定到乘法。
要解決此問題,值塊必須返回一個包含兩個值的列表:代碼和適當的順序值:
return [code, Blockly.JavaScript.ORDER_ADDITION];
每個語言生成器都有一個有序的引用列表。返回的order值指定將代碼綁定在一起的最小力。有關詳細信息,請參閱“運算符優先級”頁。
如果生成的代碼要求子塊的代碼包含兩次,則應緩存參數以提高效率並防止副作用。