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值指定将代码绑定在一起的最小力。有关详细信息,请参阅“运算符优先级”页。
如果生成的代码要求子块的代码包含两次,则应缓存参数以提高效率并防止副作用。