目录
一、引入一个生成代码的文件二、定义生成的python代码1、获取block的type2、获取参数的值3、从xml来解析一个块的组成结构三、生成python代码四、结语
在开始之前,先回顾下之前写的文章《scratch3.0二次开发之blocks生成代码思路》,在文章里大概地写了生成代码的几个步骤,读者看了可能还不太理解,这是根据我的开发经验写出来的。现在具体写写实现的方法。
一、引入一个生成代码的文件
比如要生成arduino代码,就要引入生成arduino代码的文件,要生成python代码,就要引入python文件。
这个生成代码的文件是从Blockly引入进来的,scratch-blocks是在blockly的基础上开发出来的。现在的scratch-blocks是没有generators目录的,这个也可以从blockly那里copy过来。
具体分析blockly的python.js代码:
Blockly.Python = new Blockly.Generator(\'Python\');
python是blockl.generator的一个实例,会调用generator里的方法;
Blockly.Python.addReservedWords(...);
这方法的作用是给python添加关键字,blockly的python文件已经设置了许多python的关键字在里面了。
Blockly.Python.ORDER_ATOMIC = 0; // 0 \"\" ... Blockly.Python.ORDER_COLLECTION = 1; // tuples, lists, dictionaries Blockly.Python.ORDER_STRING_CONVERSION = 1; // `expression...` Blockly.Python.ORDER_MEMBER = 2.1; // . [] Blockly.Python.ORDER_FUNCTION_CALL = 2.2; // () Blockly.Python.ORDER_EXPONENTIATION = 3; // ** Blockly.Python.ORDER_UNARY_SIGN = 4; // + - Blockly.Python.ORDER_BITWISE_NOT = 4; // ~ Blockly.Python.ORDER_MULTIPLICATIVE = 5; // * / // % Blockly.Python.ORDER_ADDITIVE = 6; // + - Blockly.Python.ORDER_BITWISE_SHIFT = 7; // << >> Blockly.Python.ORDER_BITWISE_AND = 8; // & Blockly.Python.ORDER_BITWISE_XOR = 9; // ^ Blockly.Python.ORDER_BITWISE_OR = 10; // | Blockly.Python.ORDER_RELATIONAL = 11; // in, not in, is, is not, // <, <=, >, >=, <>, !=, == Blockly.Python.ORDER_LOGICAL_NOT = 12; // not Blockly.Python.ORDER_LOGICAL_AND = 13; // and Blockly.Python.ORDER_LOGICAL_OR = 14; // or Blockly.Python.ORDER_CONDITIONAL = 15; // if else Blockly.Python.ORDER_LAMBDA = 16; // lambda Blockly.Python.ORDER_NONE = 99; // (...)
以上代码设置了优先级。
Blockly.python的其他方法请参考blockly的python文件。
二、定义生成的python代码
需要对每个block定义生成的代码。
1、获取block的type
block是根据type来区分的,每个block的type是唯一的。scratch-blocks的基本blocks的定义是在scratch-blocks\\blocks_vertical目录里。
具体可以查阅之前的博客《scratch3.0二次开发之scratch-blocks中的blocks的类型、定义和使用方法》
以下是一个type为“motion_movesteps”的block块的定义
Blockly.Blocks[\'motion_movesteps\'] = { /** * Block to move steps. * @this Blockly.Block */ init: function() { this.jsonInit({ \"message0\": Blockly.Msg.MOTION_MOVESTEPS, \"args0\": [ { \"type\": \"input_value\", \"name\": \"STEPS\" } ], \"category\": Blockly.Categories.motion, \"extensions\": [\"colours_motion\", \"shape_statement\"] }); } };
定义生成的python语句:
Blockly.Python[\'motion_movesteps\'] = function (block) { var steps = Blockly.Python.valueToCode(block, \"STEPS\", Blockly.Python.ORDER_NONE); return \'move \' + steps + \' steps\\n\'; };
2、获取参数的值
根据参数的类型,选择Blockly.Python.valueToCode、block.getFieldValue还是Blockly.Python.statementToCode来获取值。
type类型 | 方法 |
---|---|
input_value | Blockly.Python.valueToCode |
input_statement | Blockly.Python.statementToCode |
field_* | block.getFieldValue |
3、从xml来解析一个块的组成结构
这是motion_movesteps块的xml结构,它由两个block组成,\”motion_movesteps\”和“math_number”,shadow也是一个block;
<block type=\"motion_movesteps\"> <value name=\"STEPS\"> <shadow type=\"math_number\"> <field name=\"NUM\">10</field> </shadow> </value> </block>
所以除了上面已经定义好的\”motion_movesteps\”生成python语句,还需要的定义math_number的生成语句
Blockly.Python[\'math_number\'] = function(block) { // Numeric value. var code = parseFloat(block.getFieldValue(\'NUM\')); var order; if (code == Infinity) { code = \'float(\"inf\")\'; order = Blockly.Python.ORDER_FUNCTION_CALL; } else if (code == -Infinity) { code = \'-float(\"inf\")\'; order = Blockly.Python.ORDER_UNARY_SIGN; } else { order = code < 0 ? Blockly.Python.ORDER_UNARY_SIGN : Blockly.Python.ORDER_ATOMIC; } return [code, order]; }
4、根据块的形状来设置return的数据类型
形状 | return的类型 |
---|---|
![]() |
字符串 |
![]() |
字符串 |
![]() |
[code, order] 数组 |
![]() |
[code, order] 数组 |
引入模块:Blockly.Python.definitions_[模块名] = ”import xxxx\”;
声明函数:Blockly.Python.definitions_[模块名] = ”def xxx …\”;
三、生成python代码
在scratch-gui/src/containers/block.jsx文件中,对workspace添加监听
this.workspace.addChangeListener(this.generatPythonCode);
四、结语
本文主要介绍了blocks生成python代码的方法,由于篇幅有限,写的也不是很全面,不过大概地生成方法也就这些。如果在开发地过程中碰到问题,可以私信我给我留言,我尽可能地帮助大家解决问题
暂无评论内容