mirror of
https://github.com/google/blockly.git
synced 2026-01-07 17:10:11 +01:00
refactor: convert python block generators to goog.module (#5771)
* refactor: convert generators/python/colour.js to goog.module * refactor: convert generators/python/colour.js to named requires * chore: run clang-format * refactor: convert generators/python/lists.js to goog.module * refactor: convert generators/python/lists.js to named requires * chore: run clang-format * refactor: convert generators/python/logic.js to goog.module * refactor: convert generators/python/logic.js to named requires * chore: run clang-format * refactor: convert generators/python/loops.js to goog.module * refactor: convert generators/python/loops.js to named requires * chore: run clang-format * refactor: convert generators/python/math.js to goog.module * refactor: convert generators/python/math.js to named requires * chore: run clang-format * refactor: convert generators/python/procedures.js to goog.module * refactor: convert generators/python/procedures.js to named requires * chore: run clang-format * refactor: convert generators/python/text.js to goog.module * refactor: convert generators/python/text.js to named requires * chore: run clang-format * refactor: convert generators/python/variables_dynamic.js to named requires * refactor: convert generators/python/variables.js to named requires * chore: run clang-format * refactor: convert generators/python.js to goog.module * refactor: convert generators/python.js to named requires * chore: run clang-format * chore: remove spurious @private annotations * chore: rebuild
This commit is contained in:
@@ -6,35 +6,35 @@
|
||||
|
||||
/**
|
||||
* @fileoverview Helper functions for generating Python for blocks.
|
||||
* @suppress {missingRequire|checkTypes|globalThis}
|
||||
* @suppress {checkTypes|globalThis}
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Python');
|
||||
goog.module('Blockly.Python');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
goog.require('Blockly.Generator');
|
||||
goog.require('Blockly.Names');
|
||||
goog.require('Blockly.Variables');
|
||||
goog.require('Blockly.inputTypes');
|
||||
goog.require('Blockly.utils.string');
|
||||
goog.requireType('Blockly.Block');
|
||||
goog.requireType('Blockly.Workspace');
|
||||
const stringUtils = goog.require('Blockly.utils.string');
|
||||
const Variables = goog.require('Blockly.Variables');
|
||||
const {Block} = goog.requireType('Blockly.Block');
|
||||
const {Generator} = goog.require('Blockly.Generator');
|
||||
const {inputTypes} = goog.require('Blockly.inputTypes');
|
||||
const {Names, NameType} = goog.require('Blockly.Names');
|
||||
const {Workspace} = goog.requireType('Blockly.Workspace');
|
||||
|
||||
|
||||
/**
|
||||
* Python code generator.
|
||||
* @type {!Blockly.Generator}
|
||||
* @type {!Generator}
|
||||
*/
|
||||
Blockly.Python = new Blockly.Generator('Python');
|
||||
const Python = new Generator('Python');
|
||||
|
||||
/**
|
||||
* List of illegal variable names.
|
||||
* This is not intended to be a security feature. Blockly is 100% client-side,
|
||||
* so bypassing this list is trivial. This is intended to prevent users from
|
||||
* accidentally clobbering a built-in object or function.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Python.addReservedWords(
|
||||
Python.addReservedWords(
|
||||
// import keyword
|
||||
// print(','.join(sorted(keyword.kwlist)))
|
||||
// https://docs.python.org/3/reference/lexical_analysis.html#keywords
|
||||
@@ -73,75 +73,74 @@ Blockly.Python.addReservedWords(
|
||||
'issubclass,iter,len,license,list,locals,long,map,max,memoryview,min,' +
|
||||
'next,object,oct,open,ord,pow,print,property,quit,range,raw_input,reduce,' +
|
||||
'reload,repr,reversed,round,set,setattr,slice,sorted,staticmethod,str,' +
|
||||
'sum,super,tuple,type,unichr,unicode,vars,xrange,zip'
|
||||
);
|
||||
'sum,super,tuple,type,unichr,unicode,vars,xrange,zip');
|
||||
|
||||
/**
|
||||
* Order of operation ENUMs.
|
||||
* http://docs.python.org/reference/expressions.html#summary
|
||||
*/
|
||||
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; // (...)
|
||||
Python.ORDER_ATOMIC = 0; // 0 "" ...
|
||||
Python.ORDER_COLLECTION = 1; // tuples, lists, dictionaries
|
||||
Python.ORDER_STRING_CONVERSION = 1; // `expression...`
|
||||
Python.ORDER_MEMBER = 2.1; // . []
|
||||
Python.ORDER_FUNCTION_CALL = 2.2; // ()
|
||||
Python.ORDER_EXPONENTIATION = 3; // **
|
||||
Python.ORDER_UNARY_SIGN = 4; // + -
|
||||
Python.ORDER_BITWISE_NOT = 4; // ~
|
||||
Python.ORDER_MULTIPLICATIVE = 5; // * / // %
|
||||
Python.ORDER_ADDITIVE = 6; // + -
|
||||
Python.ORDER_BITWISE_SHIFT = 7; // << >>
|
||||
Python.ORDER_BITWISE_AND = 8; // &
|
||||
Python.ORDER_BITWISE_XOR = 9; // ^
|
||||
Python.ORDER_BITWISE_OR = 10; // |
|
||||
Python.ORDER_RELATIONAL = 11; // in, not in, is, is not,
|
||||
// <, <=, >, >=, <>, !=, ==
|
||||
Python.ORDER_LOGICAL_NOT = 12; // not
|
||||
Python.ORDER_LOGICAL_AND = 13; // and
|
||||
Python.ORDER_LOGICAL_OR = 14; // or
|
||||
Python.ORDER_CONDITIONAL = 15; // if else
|
||||
Python.ORDER_LAMBDA = 16; // lambda
|
||||
Python.ORDER_NONE = 99; // (...)
|
||||
|
||||
/**
|
||||
* List of outer-inner pairings that do NOT require parentheses.
|
||||
* @type {!Array<!Array<number>>}
|
||||
*/
|
||||
Blockly.Python.ORDER_OVERRIDES = [
|
||||
Python.ORDER_OVERRIDES = [
|
||||
// (foo()).bar -> foo().bar
|
||||
// (foo())[0] -> foo()[0]
|
||||
[Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_MEMBER],
|
||||
[Python.ORDER_FUNCTION_CALL, Python.ORDER_MEMBER],
|
||||
// (foo())() -> foo()()
|
||||
[Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_FUNCTION_CALL],
|
||||
[Python.ORDER_FUNCTION_CALL, Python.ORDER_FUNCTION_CALL],
|
||||
// (foo.bar).baz -> foo.bar.baz
|
||||
// (foo.bar)[0] -> foo.bar[0]
|
||||
// (foo[0]).bar -> foo[0].bar
|
||||
// (foo[0])[1] -> foo[0][1]
|
||||
[Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_MEMBER],
|
||||
[Python.ORDER_MEMBER, Python.ORDER_MEMBER],
|
||||
// (foo.bar)() -> foo.bar()
|
||||
// (foo[0])() -> foo[0]()
|
||||
[Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_FUNCTION_CALL],
|
||||
[Python.ORDER_MEMBER, Python.ORDER_FUNCTION_CALL],
|
||||
|
||||
// not (not foo) -> not not foo
|
||||
[Blockly.Python.ORDER_LOGICAL_NOT, Blockly.Python.ORDER_LOGICAL_NOT],
|
||||
[Python.ORDER_LOGICAL_NOT, Python.ORDER_LOGICAL_NOT],
|
||||
// a and (b and c) -> a and b and c
|
||||
[Blockly.Python.ORDER_LOGICAL_AND, Blockly.Python.ORDER_LOGICAL_AND],
|
||||
[Python.ORDER_LOGICAL_AND, Python.ORDER_LOGICAL_AND],
|
||||
// a or (b or c) -> a or b or c
|
||||
[Blockly.Python.ORDER_LOGICAL_OR, Blockly.Python.ORDER_LOGICAL_OR]
|
||||
[Python.ORDER_LOGICAL_OR, Python.ORDER_LOGICAL_OR]
|
||||
];
|
||||
|
||||
/**
|
||||
* Whether the init method has been called.
|
||||
* @type {?boolean}
|
||||
*/
|
||||
Blockly.Python.isInitialized = false;
|
||||
Python.isInitialized = false;
|
||||
|
||||
/**
|
||||
* Initialise the database of variable names.
|
||||
* @param {!Blockly.Workspace} workspace Workspace to generate code from.
|
||||
* @this {Blockly.Generator}
|
||||
* @param {!Workspace} workspace Workspace to generate code from.
|
||||
* @this {Generator}
|
||||
*/
|
||||
Blockly.Python.init = function(workspace) {
|
||||
Python.init = function(workspace) {
|
||||
// Call Blockly.Generator's init.
|
||||
Object.getPrototypeOf(this).init.call(this);
|
||||
|
||||
@@ -151,7 +150,7 @@ Blockly.Python.init = function(workspace) {
|
||||
this.PASS = this.INDENT + 'pass\n';
|
||||
|
||||
if (!this.nameDB_) {
|
||||
this.nameDB_ = new Blockly.Names(this.RESERVED_WORDS_);
|
||||
this.nameDB_ = new Names(this.RESERVED_WORDS_);
|
||||
} else {
|
||||
this.nameDB_.reset();
|
||||
}
|
||||
@@ -162,17 +161,19 @@ Blockly.Python.init = function(workspace) {
|
||||
|
||||
const defvars = [];
|
||||
// Add developer variables (not created or named by the user).
|
||||
const devVarList = Blockly.Variables.allDeveloperVariables(workspace);
|
||||
const devVarList = Variables.allDeveloperVariables(workspace);
|
||||
for (let i = 0; i < devVarList.length; i++) {
|
||||
defvars.push(this.nameDB_.getName(devVarList[i],
|
||||
Blockly.Names.DEVELOPER_VARIABLE_TYPE) + ' = None');
|
||||
defvars.push(
|
||||
this.nameDB_.getName(devVarList[i], Names.DEVELOPER_VARIABLE_TYPE) +
|
||||
' = None');
|
||||
}
|
||||
|
||||
// Add user variables, but only ones that are being used.
|
||||
const variables = Blockly.Variables.allUsedVarModels(workspace);
|
||||
const variables = Variables.allUsedVarModels(workspace);
|
||||
for (let i = 0; i < variables.length; i++) {
|
||||
defvars.push(this.nameDB_.getName(variables[i].getId(),
|
||||
Blockly.VARIABLE_CATEGORY_NAME) + ' = None');
|
||||
defvars.push(
|
||||
this.nameDB_.getName(variables[i].getId(), NameType.VARIABLE) +
|
||||
' = None');
|
||||
}
|
||||
|
||||
this.definitions_['variables'] = defvars.join('\n');
|
||||
@@ -184,7 +185,7 @@ Blockly.Python.init = function(workspace) {
|
||||
* @param {string} code Generated code.
|
||||
* @return {string} Completed code.
|
||||
*/
|
||||
Blockly.Python.finish = function(code) {
|
||||
Python.finish = function(code) {
|
||||
// Convert the definitions dictionary into a list.
|
||||
const imports = [];
|
||||
const definitions = [];
|
||||
@@ -211,7 +212,7 @@ Blockly.Python.finish = function(code) {
|
||||
* @param {string} line Line of generated code.
|
||||
* @return {string} Legal line of code.
|
||||
*/
|
||||
Blockly.Python.scrubNakedValue = function(line) {
|
||||
Python.scrubNakedValue = function(line) {
|
||||
return line + '\n';
|
||||
};
|
||||
|
||||
@@ -221,10 +222,9 @@ Blockly.Python.scrubNakedValue = function(line) {
|
||||
* @return {string} Python string.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Python.quote_ = function(string) {
|
||||
Python.quote_ = function(string) {
|
||||
// Can't use goog.string.quote since % must also be escaped.
|
||||
string = string.replace(/\\/g, '\\\\')
|
||||
.replace(/\n/g, '\\\n');
|
||||
string = string.replace(/\\/g, '\\\\').replace(/\n/g, '\\\n');
|
||||
|
||||
// Follow the CPython behaviour of repr() for a non-byte string.
|
||||
let quote = '\'';
|
||||
@@ -245,7 +245,7 @@ Blockly.Python.quote_ = function(string) {
|
||||
* @return {string} Python string.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Python.multiline_quote_ = function(string) {
|
||||
Python.multiline_quote_ = function(string) {
|
||||
const lines = string.split(/\n/g).map(this.quote_);
|
||||
// Join with the following, plus a newline:
|
||||
// + '\n' +
|
||||
@@ -256,26 +256,26 @@ Blockly.Python.multiline_quote_ = function(string) {
|
||||
* Common tasks for generating Python from blocks.
|
||||
* Handles comments for the specified block and any connected value blocks.
|
||||
* Calls any statements following this block.
|
||||
* @param {!Blockly.Block} block The current block.
|
||||
* @param {!Block} block The current block.
|
||||
* @param {string} code The Python code created for this block.
|
||||
* @param {boolean=} opt_thisOnly True to generate code for only this statement.
|
||||
* @return {string} Python code with comments and subsequent blocks added.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Python.scrub_ = function(block, code, opt_thisOnly) {
|
||||
Python.scrub_ = function(block, code, opt_thisOnly) {
|
||||
let commentCode = '';
|
||||
// Only collect comments for blocks that aren't inline.
|
||||
if (!block.outputConnection || !block.outputConnection.targetConnection) {
|
||||
// Collect comment for this block.
|
||||
let comment = block.getCommentText();
|
||||
if (comment) {
|
||||
comment = Blockly.utils.string.wrap(comment, this.COMMENT_WRAP - 3);
|
||||
comment = stringUtils.wrap(comment, this.COMMENT_WRAP - 3);
|
||||
commentCode += this.prefixLines(comment + '\n', '# ');
|
||||
}
|
||||
// Collect comments for all value arguments.
|
||||
// Don't collect comments for nested statements.
|
||||
for (let i = 0; i < block.inputList.length; i++) {
|
||||
if (block.inputList[i].type === Blockly.inputTypes.VALUE) {
|
||||
if (block.inputList[i].type === inputTypes.VALUE) {
|
||||
const childBlock = block.inputList[i].connection.targetBlock();
|
||||
if (childBlock) {
|
||||
comment = this.allNestedComments(childBlock);
|
||||
@@ -294,13 +294,13 @@ Blockly.Python.scrub_ = function(block, code, opt_thisOnly) {
|
||||
/**
|
||||
* Gets a property and adjusts the value, taking into account indexing.
|
||||
* If a static int, casts to an integer, otherwise returns a code string.
|
||||
* @param {!Blockly.Block} block The block.
|
||||
* @param {!Block} block The block.
|
||||
* @param {string} atId The property ID of the element to get.
|
||||
* @param {number=} opt_delta Value to add.
|
||||
* @param {boolean=} opt_negate Whether to negate the value.
|
||||
* @return {string|number}
|
||||
*/
|
||||
Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) {
|
||||
Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) {
|
||||
let delta = opt_delta || 0;
|
||||
if (block.workspace.options.oneBasedIndex) {
|
||||
delta--;
|
||||
@@ -309,7 +309,7 @@ Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) {
|
||||
const atOrder = delta ? this.ORDER_ADDITIVE : this.ORDER_NONE;
|
||||
let at = this.valueToCode(block, atId, atOrder) || defaultAtIndex;
|
||||
|
||||
if (Blockly.utils.string.isNumber(at)) {
|
||||
if (stringUtils.isNumber(at)) {
|
||||
// If the index is a naked number, adjust it right now.
|
||||
at = parseInt(at, 10) + delta;
|
||||
if (opt_negate) {
|
||||
@@ -330,3 +330,5 @@ Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) {
|
||||
}
|
||||
return at;
|
||||
};
|
||||
|
||||
exports = Python;
|
||||
|
||||
Reference in New Issue
Block a user