From 26901654ea98c1ca9b6d6aafa2b2016286d6a229 Mon Sep 17 00:00:00 2001 From: Christopher Allen Date: Wed, 14 Jun 2023 00:39:12 +0100 Subject: [PATCH] refactor(generators): Introduce DartGenerator class, Order enum (#7160) * refactor(generators): Introduce DartGenerator class, Order enum * refactor(generators): Use Order.* instead of .ORDER_* * refactor(generators): Don't rename dartGenerator --- generators/dart.js | 512 ++++++++++++++------------- generators/dart/colour.js | 61 ++-- generators/dart/lists.js | 193 +++++----- generators/dart/logic.js | 75 ++-- generators/dart/loops.js | 83 +++-- generators/dart/math.js | 225 ++++++------ generators/dart/procedures.js | 70 ++-- generators/dart/text.js | 192 +++++----- generators/dart/variables.js | 16 +- generators/dart/variables_dynamic.js | 10 +- 10 files changed, 760 insertions(+), 677 deletions(-) diff --git a/generators/dart.js b/generators/dart.js index bff1476e6..db778f0bc 100644 --- a/generators/dart.js +++ b/generators/dart.js @@ -21,282 +21,296 @@ import {Names, NameType} from '../core/names.js'; import {inputTypes} from '../core/inputs/input_types.js'; -/** - * Dart code generator. - * @type {!CodeGenerator} - */ -const Dart = new CodeGenerator('Dart'); - -/** - * 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. - */ -Dart.addReservedWords( - // https://www.dartlang.org/docs/spec/latest/dart-language-specification.pdf - // Section 16.1.1 - 'assert,break,case,catch,class,const,continue,default,do,else,enum,' + - 'extends,false,final,finally,for,if,in,is,new,null,rethrow,return,super,' + - 'switch,this,throw,true,try,var,void,while,with,' + - // https://api.dartlang.org/dart_core.html - 'print,identityHashCode,identical,BidirectionalIterator,Comparable,' + - 'double,Function,int,Invocation,Iterable,Iterator,List,Map,Match,num,' + - 'Pattern,RegExp,Set,StackTrace,String,StringSink,Type,bool,DateTime,' + - 'Deprecated,Duration,Expando,Null,Object,RuneIterator,Runes,Stopwatch,' + - 'StringBuffer,Symbol,Uri,Comparator,AbstractClassInstantiationError,' + - 'ArgumentError,AssertionError,CastError,ConcurrentModificationError,' + - 'CyclicInitializationError,Error,Exception,FallThroughError,' + - 'FormatException,IntegerDivisionByZeroException,NoSuchMethodError,' + - 'NullThrownError,OutOfMemoryError,RangeError,StackOverflowError,' + - 'StateError,TypeError,UnimplementedError,UnsupportedError' -); - /** * Order of operation ENUMs. * https://dart.dev/guides/language/language-tour#operators */ -Dart.ORDER_ATOMIC = 0; // 0 "" ... -Dart.ORDER_UNARY_POSTFIX = 1; // expr++ expr-- () [] . ?. -Dart.ORDER_UNARY_PREFIX = 2; // -expr !expr ~expr ++expr --expr -Dart.ORDER_MULTIPLICATIVE = 3; // * / % ~/ -Dart.ORDER_ADDITIVE = 4; // + - -Dart.ORDER_SHIFT = 5; // << >> -Dart.ORDER_BITWISE_AND = 6; // & -Dart.ORDER_BITWISE_XOR = 7; // ^ -Dart.ORDER_BITWISE_OR = 8; // | -Dart.ORDER_RELATIONAL = 9; // >= > <= < as is is! -Dart.ORDER_EQUALITY = 10; // == != -Dart.ORDER_LOGICAL_AND = 11; // && -Dart.ORDER_LOGICAL_OR = 12; // || -Dart.ORDER_IF_NULL = 13; // ?? -Dart.ORDER_CONDITIONAL = 14; // expr ? expr : expr -Dart.ORDER_CASCADE = 15; // .. -Dart.ORDER_ASSIGNMENT = 16; // = *= /= ~/= %= += -= <<= >>= &= ^= |= -Dart.ORDER_NONE = 99; // (...) - -/** - * Whether the init method has been called. - * @type {?boolean} - */ -Dart.isInitialized = false; - -/** - * Initialise the database of variable names. - * @param {!Workspace} workspace Workspace to generate code from. - */ -Dart.init = function(workspace) { - // Call Blockly.CodeGenerator's init. - Object.getPrototypeOf(this).init.call(this); - - if (!this.nameDB_) { - this.nameDB_ = new Names(this.RESERVED_WORDS_); - } else { - this.nameDB_.reset(); - } - - this.nameDB_.setVariableMap(workspace.getVariableMap()); - this.nameDB_.populateVariables(workspace); - this.nameDB_.populateProcedures(workspace); - - const defvars = []; - // Add developer variables (not created or named by the user). - const devVarList = Variables.allDeveloperVariables(workspace); - for (let i = 0; i < devVarList.length; i++) { - defvars.push(this.nameDB_.getName(devVarList[i], - NameType.DEVELOPER_VARIABLE)); - } - - // Add user variables, but only ones that are being used. - const variables = Variables.allUsedVarModels(workspace); - for (let i = 0; i < variables.length; i++) { - defvars.push(this.nameDB_.getName(variables[i].getId(), - NameType.VARIABLE)); - } - - // Declare all of the variables. - if (defvars.length) { - this.definitions_['variables'] = - 'var ' + defvars.join(', ') + ';'; - } - this.isInitialized = true; +export const Order = { + ATOMIC: 0, // 0 "" ... + UNARY_POSTFIX: 1, // expr++ expr-- () [] . ?. + UNARY_PREFIX: 2, // -expr !expr ~expr ++expr --expr + MULTIPLICATIVE: 3, // * / % ~/ + ADDITIVE: 4, // + - + SHIFT: 5, // << >> + BITWISE_AND: 6, // & + BITWISE_XOR: 7, // ^ + BITWISE_OR: 8, // | + RELATIONAL: 9, // >= > <= < as is is! + EQUALITY: 10, // == != + LOGICAL_AND: 11, // && + LOGICAL_OR: 12, // || + IF_NULL: 13, // ?? + CONDITIONAL: 14, // expr ? expr : expr + CASCADE: 15, // .. + ASSIGNMENT: 16, // = *= /= ~/= %= += -= <<= >>= &= ^= |= + NONE: 99, // (...) }; /** - * Prepend the generated code with import statements and variable definitions. - * @param {string} code Generated code. - * @return {string} Completed code. + * Dart code generator class. */ -Dart.finish = function(code) { - // Indent every line. - if (code) { - code = this.prefixLines(code, this.INDENT); - } - code = 'main() {\n' + code + '}'; +export class DartGenerator extends CodeGenerator { + constructor(name) { + super(name ?? 'Dart'); + this.isInitialized = false; - // Convert the definitions dictionary into a list. - const imports = []; - const definitions = []; - for (let name in this.definitions_) { - const def = this.definitions_[name]; - if (def.match(/^import\s/)) { - imports.push(def); - } else { - definitions.push(def); + // Copy Order values onto instance for backwards compatibility + // while ensuring they are not part of the publically-advertised + // API. + // + // TODO(#7085): deprecate these in due course. (Could initially + // replace data properties with get accessors that call + // deprecate.warn().) + for (const key in Order) { + this['ORDER_' + key] = Order[key]; } + + // 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. + this.addReservedWords( + // https://www.dartlang.org/docs/spec/latest/dart-language-specification.pdf + // Section 16.1.1 + 'assert,break,case,catch,class,const,continue,default,do,else,enum,' + + 'extends,false,final,finally,for,if,in,is,new,null,rethrow,return,' + + 'super,switch,this,throw,true,try,var,void,while,with,' + + // https://api.dartlang.org/dart_core.html + 'print,identityHashCode,identical,BidirectionalIterator,Comparable,' + + 'double,Function,int,Invocation,Iterable,Iterator,List,Map,Match,num,' + + 'Pattern,RegExp,Set,StackTrace,String,StringSink,Type,bool,DateTime,' + + 'Deprecated,Duration,Expando,Null,Object,RuneIterator,Runes,Stopwatch,' + + 'StringBuffer,Symbol,Uri,Comparator,AbstractClassInstantiationError,' + + 'ArgumentError,AssertionError,CastError,ConcurrentModificationError,' + + 'CyclicInitializationError,Error,Exception,FallThroughError,' + + 'FormatException,IntegerDivisionByZeroException,NoSuchMethodError,' + + 'NullThrownError,OutOfMemoryError,RangeError,StackOverflowError,' + + 'StateError,TypeError,UnimplementedError,UnsupportedError' + ); } - // Call Blockly.CodeGenerator's finish. - code = Object.getPrototypeOf(this).finish.call(this, code); - this.isInitialized = false; - this.nameDB_.reset(); - const allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); - return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; -}; + /** + * Initialise the database of variable names. + * @param {!Workspace} workspace Workspace to generate code from. + */ + init(workspace) { + super.init(); -/** - * Naked values are top-level blocks with outputs that aren't plugged into - * anything. A trailing semicolon is needed to make this legal. - * @param {string} line Line of generated code. - * @return {string} Legal line of code. - */ -Dart.scrubNakedValue = function(line) { - return line + ';\n'; -}; + if (!this.nameDB_) { + this.nameDB_ = new Names(this.RESERVED_WORDS_); + } else { + this.nameDB_.reset(); + } -/** - * Encode a string as a properly escaped Dart string, complete with quotes. - * @param {string} string Text to encode. - * @return {string} Dart string. - * @protected - */ -Dart.quote_ = function(string) { - // Can't use goog.string.quote since $ must also be escaped. - string = string.replace(/\\/g, '\\\\') - .replace(/\n/g, '\\\n') - .replace(/\$/g, '\\$') - .replace(/'/g, '\\\''); - return '\'' + string + '\''; -}; + this.nameDB_.setVariableMap(workspace.getVariableMap()); + this.nameDB_.populateVariables(workspace); + this.nameDB_.populateProcedures(workspace); -/** - * Encode a string as a properly escaped multiline Dart string, complete with - * quotes. - * @param {string} string Text to encode. - * @return {string} Dart string. - * @protected - */ -Dart.multiline_quote_ = function (string) { - const lines = string.split(/\n/g).map(this.quote_); - // Join with the following, plus a newline: - // + '\n' + - return lines.join(' + \'\\n\' + \n'); -}; + const defvars = []; + // Add developer variables (not created or named by the user). + const devVarList = Variables.allDeveloperVariables(workspace); + for (let i = 0; i < devVarList.length; i++) { + defvars.push(this.nameDB_.getName(devVarList[i], + NameType.DEVELOPER_VARIABLE)); + } -/** - * Common tasks for generating Dart from blocks. - * Handles comments for the specified block and any connected value blocks. - * Calls any statements following this block. - * @param {!Block} block The current block. - * @param {string} code The Dart code created for this block. - * @param {boolean=} opt_thisOnly True to generate code for only this statement. - * @return {string} Dart code with comments and subsequent blocks added. - * @protected - */ -Dart.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 = stringUtils.wrap(comment, this.COMMENT_WRAP - 3); - if (block.getProcedureDef) { - // Use documentation comment for function comments. - commentCode += this.prefixLines(comment + '\n', '/// '); + // Add user variables, but only ones that are being used. + const variables = Variables.allUsedVarModels(workspace); + for (let i = 0; i < variables.length; i++) { + defvars.push(this.nameDB_.getName(variables[i].getId(), + NameType.VARIABLE)); + } + + // Declare all of the variables. + if (defvars.length) { + this.definitions_['variables'] = + 'var ' + defvars.join(', ') + ';'; + } + this.isInitialized = true; + } + + /** + * Prepend the generated code with import statements and variable definitions. + * @param {string} code Generated code. + * @return {string} Completed code. + */ + finish(code) { + // Indent every line. + if (code) { + code = this.prefixLines(code, this.INDENT); + } + code = 'main() {\n' + code + '}'; + + // Convert the definitions dictionary into a list. + const imports = []; + const definitions = []; + for (let name in this.definitions_) { + const def = this.definitions_[name]; + if (def.match(/^import\s/)) { + imports.push(def); } else { - commentCode += this.prefixLines(comment + '\n', '// '); + definitions.push(def); } } - // 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 === inputTypes.VALUE) { - const childBlock = block.inputList[i].connection.targetBlock(); - if (childBlock) { - comment = this.allNestedComments(childBlock); - if (comment) { - commentCode += this.prefixLines(comment, '// '); + // Call Blockly.CodeGenerator's finish. + code = super.finish(code); + this.isInitialized = false; + + this.nameDB_.reset(); + const allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); + return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; + } + + /** + * Naked values are top-level blocks with outputs that aren't plugged into + * anything. A trailing semicolon is needed to make this legal. + * @param {string} line Line of generated code. + * @return {string} Legal line of code. + */ + scrubNakedValue(line) { + return line + ';\n'; + } + + /** + * Encode a string as a properly escaped Dart string, complete with quotes. + * @param {string} string Text to encode. + * @return {string} Dart string. + * @protected + */ + quote_(string) { + // Can't use goog.string.quote since $ must also be escaped. + string = string.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\\n') + .replace(/\$/g, '\\$') + .replace(/'/g, '\\\''); + return '\'' + string + '\''; + } + + /** + * Encode a string as a properly escaped multiline Dart string, complete with + * quotes. + * @param {string} string Text to encode. + * @return {string} Dart string. + * @protected + */ + multiline_quote_(string) { + const lines = string.split(/\n/g).map(this.quote_); + // Join with the following, plus a newline: + // + '\n' + + return lines.join(' + \'\\n\' + \n'); + } + + /** + * Common tasks for generating Dart from blocks. + * Handles comments for the specified block and any connected value blocks. + * Calls any statements following this block. + * @param {!Block} block The current block. + * @param {string} code The Dart code created for this block. + * @param {boolean=} opt_thisOnly True to generate code for only this + * statement. + * @return {string} Dart code with comments and subsequent blocks added. + * @protected + */ + scrub_(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 = stringUtils.wrap(comment, this.COMMENT_WRAP - 3); + if (block.getProcedureDef) { + // Use documentation comment for function comments. + commentCode += this.prefixLines(comment + '\n', '/// '); + } else { + 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 === inputTypes.VALUE) { + const childBlock = block.inputList[i].connection.targetBlock(); + if (childBlock) { + comment = this.allNestedComments(childBlock); + if (comment) { + commentCode += this.prefixLines(comment, '// '); + } } } } } - } - const nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - const nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock); - return commentCode + code + nextCode; -}; - -/** - * Gets a property and adjusts the value while taking into account indexing. - * @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. - * @param {number=} opt_order The highest order acting on this value. - * @return {string|number} - */ -Dart.getAdjusted = function(block, atId, opt_delta, opt_negate, - opt_order) { - let delta = opt_delta || 0; - let order = opt_order || this.ORDER_NONE; - if (block.workspace.options.oneBasedIndex) { - delta--; - } - const defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; - - /** @type {number} */ - let outerOrder; - let innerOrder; - if (delta) { - outerOrder = this.ORDER_ADDITIVE; - innerOrder = this.ORDER_ADDITIVE; - } else if (opt_negate) { - outerOrder = this.ORDER_UNARY_PREFIX; - innerOrder = this.ORDER_UNARY_PREFIX; - } else { - outerOrder = order; + const nextBlock = + block.nextConnection && block.nextConnection.targetBlock(); + const nextCode = opt_thisOnly ? '' : this.blockToCode(nextBlock); + return commentCode + code + nextCode; } - /** @type {string|number} */ - let at = this.valueToCode(block, atId, outerOrder) || defaultAtIndex; - - if (stringUtils.isNumber(at)) { - // If the index is a naked number, adjust it right now. - at = parseInt(at, 10) + delta; - if (opt_negate) { - at = -at; + /** + * Gets a property and adjusts the value while taking into account indexing. + * @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. + * @param {number=} opt_order The highest order acting on this value. + * @return {string|number} + */ + getAdjusted(block, atId, opt_delta, opt_negate, opt_order) { + let delta = opt_delta || 0; + let order = opt_order || this.ORDER_NONE; + if (block.workspace.options.oneBasedIndex) { + delta--; } - } else { - // If the index is dynamic, adjust it in code. - if (delta > 0) { - at = at + ' + ' + delta; - } else if (delta < 0) { - at = at + ' - ' + -delta; + const defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; + + /** @type {number} */ + let outerOrder; + let innerOrder; + if (delta) { + outerOrder = this.ORDER_ADDITIVE; + innerOrder = this.ORDER_ADDITIVE; + } else if (opt_negate) { + outerOrder = this.ORDER_UNARY_PREFIX; + innerOrder = this.ORDER_UNARY_PREFIX; + } else { + outerOrder = order; } - if (opt_negate) { - if (delta) { - at = '-(' + at + ')'; - } else { - at = '-' + at; + + /** @type {string|number} */ + let at = this.valueToCode(block, atId, outerOrder) || defaultAtIndex; + + if (stringUtils.isNumber(at)) { + // If the index is a naked number, adjust it right now. + at = parseInt(at, 10) + delta; + if (opt_negate) { + at = -at; + } + } else { + // If the index is dynamic, adjust it in code. + if (delta > 0) { + at = at + ' + ' + delta; + } else if (delta < 0) { + at = at + ' - ' + -delta; + } + if (opt_negate) { + if (delta) { + at = '-(' + at + ')'; + } else { + at = '-' + at; + } + } + innerOrder = Math.floor(innerOrder); + order = Math.floor(order); + if (innerOrder && order >= innerOrder) { + at = '(' + at + ')'; } } - innerOrder = Math.floor(innerOrder); - order = Math.floor(order); - if (innerOrder && order >= innerOrder) { - at = '(' + at + ')'; - } + return at; } - return at; -}; -export {Dart as dartGenerator}; +} + +/** + * Dart code generator. + * @type {!DartGenerator} + */ +export const dartGenerator = new DartGenerator(); diff --git a/generators/dart/colour.js b/generators/dart/colour.js index b4d4ec7f7..74f1406ce 100644 --- a/generators/dart/colour.js +++ b/generators/dart/colour.js @@ -11,22 +11,23 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.colour'); -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator, Order} from '../dart.js'; -Dart.addReservedWords('Math'); +dartGenerator.addReservedWords('Math'); -Dart.forBlock['colour_picker'] = function(block) { +dartGenerator.forBlock['colour_picker'] = function(block) { // Colour picker. - const code = Dart.quote_(block.getFieldValue('COLOUR')); - return [code, Dart.ORDER_ATOMIC]; + const code = dartGenerator.quote_(block.getFieldValue('COLOUR')); + return [code, Order.ATOMIC]; }; -Dart.forBlock['colour_random'] = function(block) { +dartGenerator.forBlock['colour_random'] = function(block) { // Generate a random colour. - Dart.definitions_['import_dart_math'] = "import 'dart:math' as Math;"; - const functionName = Dart.provideFunction_('colour_random', ` -String ${Dart.FUNCTION_NAME_PLACEHOLDER_}() { + dartGenerator.definitions_['import_dart_math'] = + "import 'dart:math' as Math;"; + const functionName = dartGenerator.provideFunction_('colour_random', ` +String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}() { String hex = '0123456789abcdef'; var rnd = new Math.Random(); return '#\${hex[rnd.nextInt(16)]}\${hex[rnd.nextInt(16)]}' @@ -35,21 +36,19 @@ String ${Dart.FUNCTION_NAME_PLACEHOLDER_}() { } `); const code = functionName + '()'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['colour_rgb'] = function(block) { +dartGenerator.forBlock['colour_rgb'] = function(block) { // Compose a colour from RGB components expressed as percentages. - const red = Dart.valueToCode(block, 'RED', - Dart.ORDER_NONE) || 0; - const green = Dart.valueToCode(block, 'GREEN', - Dart.ORDER_NONE) || 0; - const blue = Dart.valueToCode(block, 'BLUE', - Dart.ORDER_NONE) || 0; + const red = dartGenerator.valueToCode(block, 'RED', Order.NONE) || 0; + const green = dartGenerator.valueToCode(block, 'GREEN', Order.NONE) || 0; + const blue = dartGenerator.valueToCode(block, 'BLUE', Order.NONE) || 0; - Dart.definitions_['import_dart_math'] = "import 'dart:math' as Math;"; - const functionName = Dart.provideFunction_('colour_rgb', ` -String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(num r, num g, num b) { + dartGenerator.definitions_['import_dart_math'] = + "import 'dart:math' as Math;"; + const functionName = dartGenerator.provideFunction_('colour_rgb', ` +String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(num r, num g, num b) { num rn = (Math.max(Math.min(r, 100), 0) * 2.55).round(); String rs = rn.toInt().toRadixString(16); rs = '0$rs'; @@ -66,18 +65,22 @@ String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(num r, num g, num b) { } `); const code = functionName + '(' + red + ', ' + green + ', ' + blue + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['colour_blend'] = function(block) { +dartGenerator.forBlock['colour_blend'] = function(block) { // Blend two colours together. - const c1 = Dart.valueToCode(block, 'COLOUR1', Dart.ORDER_NONE) || "'#000000'"; - const c2 = Dart.valueToCode(block, 'COLOUR2', Dart.ORDER_NONE) || "'#000000'"; - const ratio = Dart.valueToCode(block, 'RATIO', Dart.ORDER_NONE) || 0.5; + const c1 = + dartGenerator.valueToCode(block, 'COLOUR1', Order.NONE) || "'#000000'"; + const c2 = + dartGenerator.valueToCode(block, 'COLOUR2', Order.NONE) || "'#000000'"; + const ratio = + dartGenerator.valueToCode(block, 'RATIO', Order.NONE) || 0.5; - Dart.definitions_['import_dart_math'] = "import 'dart:math' as Math;"; - const functionName = Dart.provideFunction_('colour_blend', ` -String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String c1, String c2, num ratio) { + dartGenerator.definitions_['import_dart_math'] = + "import 'dart:math' as Math;"; + const functionName = dartGenerator.provideFunction_('colour_blend', ` +String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(String c1, String c2, num ratio) { ratio = Math.max(Math.min(ratio, 1), 0); int r1 = int.parse('0x\${c1.substring(1, 3)}'); int g1 = int.parse('0x\${c1.substring(3, 5)}'); @@ -101,5 +104,5 @@ String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String c1, String c2, num ratio) { } `); const code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; diff --git a/generators/dart/lists.js b/generators/dart/lists.js index 35e7ec431..9a74cbbdb 100644 --- a/generators/dart/lists.js +++ b/generators/dart/lists.js @@ -12,75 +12,79 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.lists'); import {NameType} from '../../core/names.js'; -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator, Order} from '../dart.js'; -Dart.addReservedWords('Math'); +dartGenerator.addReservedWords('Math'); -Dart.forBlock['lists_create_empty'] = function(block) { +dartGenerator.forBlock['lists_create_empty'] = function(block) { // Create an empty list. - return ['[]', Dart.ORDER_ATOMIC]; + return ['[]', Order.ATOMIC]; }; -Dart.forBlock['lists_create_with'] = function(block) { +dartGenerator.forBlock['lists_create_with'] = function(block) { // Create a list with any number of elements of any type. const elements = new Array(block.itemCount_); for (let i = 0; i < block.itemCount_; i++) { - elements[i] = Dart.valueToCode(block, 'ADD' + i, Dart.ORDER_NONE) || 'null'; + elements[i] = + dartGenerator.valueToCode(block, 'ADD' + i, Order.NONE) || 'null'; } const code = '[' + elements.join(', ') + ']'; - return [code, Dart.ORDER_ATOMIC]; + return [code, Order.ATOMIC]; }; -Dart.forBlock['lists_repeat'] = function(block) { +dartGenerator.forBlock['lists_repeat'] = function(block) { // Create a list with one element repeated. - const element = Dart.valueToCode(block, 'ITEM', Dart.ORDER_NONE) || 'null'; - const repeatCount = Dart.valueToCode(block, 'NUM', Dart.ORDER_NONE) || '0'; + const element = + dartGenerator.valueToCode(block, 'ITEM', Order.NONE) || 'null'; + const repeatCount = + dartGenerator.valueToCode(block, 'NUM', Order.NONE) || '0'; const code = 'new List.filled(' + repeatCount + ', ' + element + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['lists_length'] = function(block) { +dartGenerator.forBlock['lists_length'] = function(block) { // String or array length. const list = - Dart.valueToCode(block, 'VALUE', Dart.ORDER_UNARY_POSTFIX) || '[]'; - return [list + '.length', Dart.ORDER_UNARY_POSTFIX]; + dartGenerator.valueToCode(block, 'VALUE', Order.UNARY_POSTFIX) || '[]'; + return [list + '.length', Order.UNARY_POSTFIX]; }; -Dart.forBlock['lists_isEmpty'] = function(block) { +dartGenerator.forBlock['lists_isEmpty'] = function(block) { // Is the string null or array empty? const list = - Dart.valueToCode(block, 'VALUE', Dart.ORDER_UNARY_POSTFIX) || '[]'; - return [list + '.isEmpty', Dart.ORDER_UNARY_POSTFIX]; + dartGenerator.valueToCode(block, 'VALUE', Order.UNARY_POSTFIX) || '[]'; + return [list + '.isEmpty', Order.UNARY_POSTFIX]; }; -Dart.forBlock['lists_indexOf'] = function(block) { +dartGenerator.forBlock['lists_indexOf'] = function(block) { // Find an item in the list. const operator = block.getFieldValue('END') === 'FIRST' ? 'indexOf' : 'lastIndexOf'; - const item = Dart.valueToCode(block, 'FIND', Dart.ORDER_NONE) || "''"; + const item = dartGenerator.valueToCode(block, 'FIND', Order.NONE) || "''"; const list = - Dart.valueToCode(block, 'VALUE', Dart.ORDER_UNARY_POSTFIX) || '[]'; + dartGenerator.valueToCode(block, 'VALUE', Order.UNARY_POSTFIX) || '[]'; const code = list + '.' + operator + '(' + item + ')'; if (block.workspace.options.oneBasedIndex) { - return [code + ' + 1', Dart.ORDER_ADDITIVE]; + return [code + ' + 1', Order.ADDITIVE]; } - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['lists_getIndex'] = function(block) { +dartGenerator.forBlock['lists_getIndex'] = function(block) { // Get element at index. // Note: Until January 2013 this block did not have MODE or WHERE inputs. const mode = block.getFieldValue('MODE') || 'GET'; const where = block.getFieldValue('WHERE') || 'FROM_START'; const listOrder = (where === 'RANDOM' || where === 'FROM_END') ? - Dart.ORDER_NONE : - Dart.ORDER_UNARY_POSTFIX; - let list = Dart.valueToCode(block, 'VALUE', listOrder) || '[]'; + Order.NONE : + Order.UNARY_POSTFIX; + let list = dartGenerator.valueToCode(block, 'VALUE', listOrder) || '[]'; // Cache non-trivial values to variables to prevent repeated look-ups. // Closure, which accesses and modifies 'list'. function cacheList() { - const listVar = Dart.nameDB_.getDistinctName('tmp_list', NameType.VARIABLE); + const listVar = + dartGenerator.nameDB_.getDistinctName('tmp_list', NameType.VARIABLE); const code = 'List ' + listVar + ' = ' + list + ';\n'; list = listVar; return code; @@ -92,10 +96,12 @@ Dart.forBlock['lists_getIndex'] = function(block) { !list.match(/^\w+$/)) { // `list` is an expression, so we may not evaluate it more than once. if (where === 'RANDOM') { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; // We can use multiple statements. let code = cacheList(); - const xVar = Dart.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE); + const xVar = + dartGenerator.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE); code += 'int ' + xVar + ' = new Math.Random().nextInt(' + list + '.length);\n'; code += list + '.removeAt(' + xVar + ');\n'; @@ -103,34 +109,36 @@ Dart.forBlock['lists_getIndex'] = function(block) { } else { // where === 'FROM_END' if (mode === 'REMOVE') { // We can use multiple statements. - const at = Dart.getAdjusted(block, 'AT', 1, false, Dart.ORDER_ADDITIVE); + const at = + dartGenerator.getAdjusted(block, 'AT', 1, false, Order.ADDITIVE); let code = cacheList(); code += list + '.removeAt(' + list + '.length' + ' - ' + at + ');\n'; return code; } else if (mode === 'GET') { - const at = Dart.getAdjusted(block, 'AT', 1); + const at = dartGenerator.getAdjusted(block, 'AT', 1); // We need to create a procedure to avoid reevaluating values. - const functionName = Dart.provideFunction_('lists_get_from_end', ` -dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List my_list, num x) { + const functionName = dartGenerator.provideFunction_('lists_get_from_end', ` +dynamic ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List my_list, num x) { x = my_list.length - x; return my_list[x]; } `); const code = functionName + '(' + list + ', ' + at + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'GET_REMOVE') { - const at = Dart.getAdjusted(block, 'AT', 1); + const at = dartGenerator.getAdjusted(block, 'AT', 1); // We need to create a procedure to avoid reevaluating values. - const functionName = Dart.provideFunction_('lists_remove_from_end', ` -dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List my_list, num x) { + const functionName = + dartGenerator.provideFunction_('lists_remove_from_end', ` +dynamic ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List my_list, num x) { x = my_list.length - x; return my_list.removeAt(x); } `); const code = functionName + '(' + list + ', ' + at + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } } } else { @@ -140,10 +148,10 @@ dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List my_list, num x) { case 'FIRST': if (mode === 'GET') { const code = list + '.first'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'GET_REMOVE') { const code = list + '.removeAt(0)'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'REMOVE') { return list + '.removeAt(0);\n'; } @@ -151,36 +159,37 @@ dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List my_list, num x) { case 'LAST': if (mode === 'GET') { const code = list + '.last'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'GET_REMOVE') { const code = list + '.removeLast()'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'REMOVE') { return list + '.removeLast();\n'; } break; case 'FROM_START': { - const at = Dart.getAdjusted(block, 'AT'); + const at = dartGenerator.getAdjusted(block, 'AT'); if (mode === 'GET') { const code = list + '[' + at + ']'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'GET_REMOVE') { const code = list + '.removeAt(' + at + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'REMOVE') { return list + '.removeAt(' + at + ');\n'; } break; } case 'FROM_END': { - const at = Dart.getAdjusted(block, 'AT', 1, false, Dart.ORDER_ADDITIVE); + const at = + dartGenerator.getAdjusted(block, 'AT', 1, false, Order.ADDITIVE); if (mode === 'GET') { const code = list + '[' + list + '.length - ' + at + ']'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'GET_REMOVE' || mode === 'REMOVE') { const code = list + '.removeAt(' + list + '.length - ' + at + ')'; if (mode === 'GET_REMOVE') { - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'REMOVE') { return code + ';\n'; } @@ -188,33 +197,36 @@ dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List my_list, num x) { break; } case 'RANDOM': - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; if (mode === 'REMOVE') { // We can use multiple statements. - const xVar = Dart.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE); + const xVar = + dartGenerator.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE); let code = 'int ' + xVar + ' = new Math.Random().nextInt(' + list + '.length);\n'; code += list + '.removeAt(' + xVar + ');\n'; return code; } else if (mode === 'GET') { - const functionName = Dart.provideFunction_('lists_get_random_item', ` -dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List my_list) { + const functionName = + dartGenerator.provideFunction_('lists_get_random_item', ` +dynamic ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List my_list) { int x = new Math.Random().nextInt(my_list.length); return my_list[x]; } `); const code = functionName + '(' + list + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } else if (mode === 'GET_REMOVE') { const functionName = - Dart.provideFunction_('lists_remove_random_item', ` -dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List my_list) { + dartGenerator.provideFunction_('lists_remove_random_item', ` +dynamic ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List my_list) { int x = new Math.Random().nextInt(my_list.length); return my_list.removeAt(x); } `); const code = functionName + '(' + list + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } break; } @@ -222,20 +234,23 @@ dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List my_list) { throw Error('Unhandled combination (lists_getIndex).'); }; -Dart.forBlock['lists_setIndex'] = function(block) { +dartGenerator.forBlock['lists_setIndex'] = function(block) { // Set element at index. // Note: Until February 2013 this block did not have MODE or WHERE inputs. const mode = block.getFieldValue('MODE') || 'GET'; const where = block.getFieldValue('WHERE') || 'FROM_START'; - let list = Dart.valueToCode(block, 'LIST', Dart.ORDER_UNARY_POSTFIX) || '[]'; - const value = Dart.valueToCode(block, 'TO', Dart.ORDER_ASSIGNMENT) || 'null'; + let list = + dartGenerator.valueToCode(block, 'LIST', Order.UNARY_POSTFIX) || '[]'; + const value = + dartGenerator.valueToCode(block, 'TO', Order.ASSIGNMENT) || 'null'; // Cache non-trivial values to variables to prevent repeated look-ups. // Closure, which accesses and modifies 'list'. function cacheList() { if (list.match(/^\w+$/)) { return ''; } - const listVar = Dart.nameDB_.getDistinctName('tmp_list', NameType.VARIABLE); + const listVar = + dartGenerator.nameDB_.getDistinctName('tmp_list', NameType.VARIABLE); const code = 'List ' + listVar + ' = ' + list + ';\n'; list = listVar; return code; @@ -258,7 +273,7 @@ Dart.forBlock['lists_setIndex'] = function(block) { } break; case 'FROM_START': { - const at = Dart.getAdjusted(block, 'AT'); + const at = dartGenerator.getAdjusted(block, 'AT'); if (mode === 'SET') { return list + '[' + at + '] = ' + value + ';\n'; } else if (mode === 'INSERT') { @@ -267,7 +282,8 @@ Dart.forBlock['lists_setIndex'] = function(block) { break; } case 'FROM_END': { - const at = Dart.getAdjusted(block, 'AT', 1, false, Dart.ORDER_ADDITIVE); + const at = + dartGenerator.getAdjusted(block, 'AT', 1, false, Order.ADDITIVE); let code = cacheList(); if (mode === 'SET') { code += list + '[' + list + '.length - ' + at + '] = ' + value + ';\n'; @@ -280,9 +296,11 @@ Dart.forBlock['lists_setIndex'] = function(block) { break; } case 'RANDOM': { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; let code = cacheList(); - const xVar = Dart.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE); + const xVar = + dartGenerator.nameDB_.getDistinctName('tmp_x', NameType.VARIABLE); code += 'int ' + xVar + ' = new Math.Random().nextInt(' + list + '.length);\n'; if (mode === 'SET') { @@ -298,10 +316,10 @@ Dart.forBlock['lists_setIndex'] = function(block) { throw Error('Unhandled combination (lists_setIndex).'); }; -Dart.forBlock['lists_getSublist'] = function(block) { +dartGenerator.forBlock['lists_getSublist'] = function(block) { // Get sublist. const list = - Dart.valueToCode(block, 'LIST', Dart.ORDER_UNARY_POSTFIX) || '[]'; + dartGenerator.valueToCode(block, 'LIST', Order.UNARY_POSTFIX) || '[]'; const where1 = block.getFieldValue('WHERE1'); const where2 = block.getFieldValue('WHERE2'); let code; @@ -312,10 +330,10 @@ Dart.forBlock['lists_getSublist'] = function(block) { let at1; switch (where1) { case 'FROM_START': - at1 = Dart.getAdjusted(block, 'AT1'); + at1 = dartGenerator.getAdjusted(block, 'AT1'); break; case 'FROM_END': - at1 = Dart.getAdjusted(block, 'AT1', 1, false, Dart.ORDER_ADDITIVE); + at1 = dartGenerator.getAdjusted(block, 'AT1', 1, false, Order.ADDITIVE); at1 = list + '.length - ' + at1; break; case 'FIRST': @@ -327,10 +345,10 @@ Dart.forBlock['lists_getSublist'] = function(block) { let at2; switch (where2) { case 'FROM_START': - at2 = Dart.getAdjusted(block, 'AT2', 1); + at2 = dartGenerator.getAdjusted(block, 'AT2', 1); break; case 'FROM_END': - at2 = Dart.getAdjusted(block, 'AT2', 0, false, Dart.ORDER_ADDITIVE); + at2 = dartGenerator.getAdjusted(block, 'AT2', 0, false, Order.ADDITIVE); at2 = list + '.length - ' + at2; break; case 'LAST': @@ -345,10 +363,10 @@ Dart.forBlock['lists_getSublist'] = function(block) { code = list + '.sublist(' + at1 + ', ' + at2 + ')'; } } else { - const at1 = Dart.getAdjusted(block, 'AT1'); - const at2 = Dart.getAdjusted(block, 'AT2'); - const functionName = Dart.provideFunction_('lists_get_sublist', ` -List ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List list, String where1, num at1, String where2, num at2) { + const at1 = dartGenerator.getAdjusted(block, 'AT1'); + const at2 = dartGenerator.getAdjusted(block, 'AT2'); + const functionName = dartGenerator.provideFunction_('lists_get_sublist', ` +List ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List list, String where1, num at1, String where2, num at2) { int getAt(String where, num at) { if (where == 'FROM_END') { at = list.length - 1 - at; @@ -369,16 +387,16 @@ List ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List list, String where1, num at1, Strin code = functionName + '(' + list + ', \'' + where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; } - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['lists_sort'] = function(block) { +dartGenerator.forBlock['lists_sort'] = function(block) { // Block for sorting a list. - const list = Dart.valueToCode(block, 'LIST', Dart.ORDER_NONE) || '[]'; + const list = dartGenerator.valueToCode(block, 'LIST', Order.NONE) || '[]'; const direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1; const type = block.getFieldValue('TYPE'); - const sortFunctionName = Dart.provideFunction_('lists_sort', ` -List ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List list, String type, int direction) { + const sortFunctionName = dartGenerator.provideFunction_('lists_sort', ` +List ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List list, String type, int direction) { var compareFuncs = { 'NUMERIC': (a, b) => (direction * a.compareTo(b)).toInt(), 'TEXT': (a, b) => direction * a.toString().compareTo(b.toString()), @@ -395,14 +413,15 @@ List ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List list, String type, int direction) { return [ sortFunctionName + '(' + list + ', ' + '"' + type + '", ' + direction + ')', - Dart.ORDER_UNARY_POSTFIX + Order.UNARY_POSTFIX ]; }; -Dart.forBlock['lists_split'] = function(block) { +dartGenerator.forBlock['lists_split'] = function(block) { // Block for splitting text into a list, or joining a list into text. - let input = Dart.valueToCode(block, 'INPUT', Dart.ORDER_UNARY_POSTFIX); - const delimiter = Dart.valueToCode(block, 'DELIM', Dart.ORDER_NONE) || "''"; + let input = dartGenerator.valueToCode(block, 'INPUT', Order.UNARY_POSTFIX); + const delimiter = + dartGenerator.valueToCode(block, 'DELIM', Order.NONE) || "''"; const mode = block.getFieldValue('MODE'); let functionName; if (mode === 'SPLIT') { @@ -419,13 +438,13 @@ Dart.forBlock['lists_split'] = function(block) { throw Error('Unknown mode: ' + mode); } const code = input + '.' + functionName + '(' + delimiter + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['lists_reverse'] = function(block) { +dartGenerator.forBlock['lists_reverse'] = function(block) { // Block for reversing a list. - const list = Dart.valueToCode(block, 'LIST', Dart.ORDER_NONE) || '[]'; + const list = dartGenerator.valueToCode(block, 'LIST', Order.NONE) || '[]'; // XXX What should the operator precedence be for a `new`? const code = 'new List.from(' + list + '.reversed)'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; diff --git a/generators/dart/logic.js b/generators/dart/logic.js index 743c54fe1..e98929f78 100644 --- a/generators/dart/logic.js +++ b/generators/dart/logic.js @@ -11,25 +11,26 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.logic'); -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator, Order} from '../dart.js'; -Dart.forBlock['controls_if'] = function(block) { +dartGenerator.forBlock['controls_if'] = function(block) { // If/elseif/else condition. let n = 0; let code = '', branchCode, conditionCode; - if (Dart.STATEMENT_PREFIX) { + if (dartGenerator.STATEMENT_PREFIX) { // Automatic prefix insertion is switched off for this block. Add manually. - code += Dart.injectId(Dart.STATEMENT_PREFIX, block); + code += dartGenerator.injectId(dartGenerator.STATEMENT_PREFIX, block); } do { conditionCode = - Dart.valueToCode(block, 'IF' + n, Dart.ORDER_NONE) || 'false'; - branchCode = Dart.statementToCode(block, 'DO' + n); - if (Dart.STATEMENT_SUFFIX) { + dartGenerator.valueToCode(block, 'IF' + n, Order.NONE) || 'false'; + branchCode = dartGenerator.statementToCode(block, 'DO' + n); + if (dartGenerator.STATEMENT_SUFFIX) { branchCode = - Dart.prefixLines( - Dart.injectId(Dart.STATEMENT_SUFFIX, block), Dart.INDENT) + + dartGenerator.prefixLines( + dartGenerator.injectId( + dartGenerator.STATEMENT_SUFFIX, block), dartGenerator.INDENT) + branchCode; } code += (n > 0 ? 'else ' : '') + 'if (' + conditionCode + ') {\n' + @@ -37,12 +38,13 @@ Dart.forBlock['controls_if'] = function(block) { n++; } while (block.getInput('IF' + n)); - if (block.getInput('ELSE') || Dart.STATEMENT_SUFFIX) { - branchCode = Dart.statementToCode(block, 'ELSE'); - if (Dart.STATEMENT_SUFFIX) { + if (block.getInput('ELSE') || dartGenerator.STATEMENT_SUFFIX) { + branchCode = dartGenerator.statementToCode(block, 'ELSE'); + if (dartGenerator.STATEMENT_SUFFIX) { branchCode = - Dart.prefixLines( - Dart.injectId(Dart.STATEMENT_SUFFIX, block), Dart.INDENT) + + dartGenerator.prefixLines( + dartGenerator.injectId( + dartGenerator.STATEMENT_SUFFIX, block), dartGenerator.INDENT) + branchCode; } code += ' else {\n' + branchCode + '}'; @@ -50,29 +52,30 @@ Dart.forBlock['controls_if'] = function(block) { return code + '\n'; }; -Dart.forBlock['controls_ifelse'] = Dart.forBlock['controls_if']; +dartGenerator.forBlock['controls_ifelse'] = + dartGenerator.forBlock['controls_if']; -Dart.forBlock['logic_compare'] = function(block) { +dartGenerator.forBlock['logic_compare'] = function(block) { // Comparison operator. const OPERATORS = {'EQ': '==', 'NEQ': '!=', 'LT': '<', 'LTE': '<=', 'GT': '>', 'GTE': '>='}; const operator = OPERATORS[block.getFieldValue('OP')]; const order = (operator === '==' || operator === '!=') ? - Dart.ORDER_EQUALITY : - Dart.ORDER_RELATIONAL; - const argument0 = Dart.valueToCode(block, 'A', order) || '0'; - const argument1 = Dart.valueToCode(block, 'B', order) || '0'; + Order.EQUALITY : + Order.RELATIONAL; + const argument0 = dartGenerator.valueToCode(block, 'A', order) || '0'; + const argument1 = dartGenerator.valueToCode(block, 'B', order) || '0'; const code = argument0 + ' ' + operator + ' ' + argument1; return [code, order]; }; -Dart.forBlock['logic_operation'] = function(block) { +dartGenerator.forBlock['logic_operation'] = function(block) { // Operations 'and', 'or'. const operator = (block.getFieldValue('OP') === 'AND') ? '&&' : '||'; const order = - (operator === '&&') ? Dart.ORDER_LOGICAL_AND : Dart.ORDER_LOGICAL_OR; - let argument0 = Dart.valueToCode(block, 'A', order); - let argument1 = Dart.valueToCode(block, 'B', order); + (operator === '&&') ? Order.LOGICAL_AND : Order.LOGICAL_OR; + let argument0 = dartGenerator.valueToCode(block, 'A', order); + let argument1 = dartGenerator.valueToCode(block, 'B', order); if (!argument0 && !argument1) { // If there are no arguments, then the return value is false. argument0 = 'false'; @@ -91,33 +94,33 @@ Dart.forBlock['logic_operation'] = function(block) { return [code, order]; }; -Dart.forBlock['logic_negate'] = function(block) { +dartGenerator.forBlock['logic_negate'] = function(block) { // Negation. - const order = Dart.ORDER_UNARY_PREFIX; - const argument0 = Dart.valueToCode(block, 'BOOL', order) || 'true'; + const order = Order.UNARY_PREFIX; + const argument0 = dartGenerator.valueToCode(block, 'BOOL', order) || 'true'; const code = '!' + argument0; return [code, order]; }; -Dart.forBlock['logic_boolean'] = function(block) { +dartGenerator.forBlock['logic_boolean'] = function(block) { // Boolean values true and false. const code = (block.getFieldValue('BOOL') === 'TRUE') ? 'true' : 'false'; - return [code, Dart.ORDER_ATOMIC]; + return [code, Order.ATOMIC]; }; -Dart.forBlock['logic_null'] = function(block) { +dartGenerator.forBlock['logic_null'] = function(block) { // Null data type. - return ['null', Dart.ORDER_ATOMIC]; + return ['null', Order.ATOMIC]; }; -Dart.forBlock['logic_ternary'] = function(block) { +dartGenerator.forBlock['logic_ternary'] = function(block) { // Ternary operator. const value_if = - Dart.valueToCode(block, 'IF', Dart.ORDER_CONDITIONAL) || 'false'; + dartGenerator.valueToCode(block, 'IF', Order.CONDITIONAL) || 'false'; const value_then = - Dart.valueToCode(block, 'THEN', Dart.ORDER_CONDITIONAL) || 'null'; + dartGenerator.valueToCode(block, 'THEN', Order.CONDITIONAL) || 'null'; const value_else = - Dart.valueToCode(block, 'ELSE', Dart.ORDER_CONDITIONAL) || 'null'; + dartGenerator.valueToCode(block, 'ELSE', Order.CONDITIONAL) || 'null'; const code = value_if + ' ? ' + value_then + ' : ' + value_else; - return [code, Dart.ORDER_CONDITIONAL]; + return [code, Order.CONDITIONAL]; }; diff --git a/generators/dart/loops.js b/generators/dart/loops.js index 3c507704e..f57bc1811 100644 --- a/generators/dart/loops.js +++ b/generators/dart/loops.js @@ -11,12 +11,12 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.loops'); -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator, Order} from '../dart.js'; import * as stringUtils from '../../core/utils/string.js'; import {NameType} from '../../core/names.js'; -Dart.forBlock['controls_repeat_ext'] = function(block) { +dartGenerator.forBlock['controls_repeat_ext'] = function(block) { let repeats; // Repeat n times. if (block.getField('TIMES')) { @@ -24,15 +24,18 @@ Dart.forBlock['controls_repeat_ext'] = function(block) { repeats = String(Number(block.getFieldValue('TIMES'))); } else { // External number. - repeats = Dart.valueToCode(block, 'TIMES', Dart.ORDER_ASSIGNMENT) || '0'; + repeats = + dartGenerator.valueToCode(block, 'TIMES', Order.ASSIGNMENT) || '0'; } - let branch = Dart.statementToCode(block, 'DO'); - branch = Dart.addLoopTrap(branch, block); + let branch = dartGenerator.statementToCode(block, 'DO'); + branch = dartGenerator.addLoopTrap(branch, block); let code = ''; - const loopVar = Dart.nameDB_.getDistinctName('count', NameType.VARIABLE); + const loopVar = + dartGenerator.nameDB_.getDistinctName('count', NameType.VARIABLE); let endVar = repeats; if (!repeats.match(/^\w+$/) && !stringUtils.isNumber(repeats)) { - endVar = Dart.nameDB_.getDistinctName('repeat_end', NameType.VARIABLE); + endVar = + dartGenerator.nameDB_.getDistinctName('repeat_end', NameType.VARIABLE); code += 'var ' + endVar + ' = ' + repeats + ';\n'; } code += 'for (int ' + loopVar + ' = 0; ' + loopVar + ' < ' + endVar + '; ' + @@ -40,33 +43,37 @@ Dart.forBlock['controls_repeat_ext'] = function(block) { return code; }; -Dart.forBlock['controls_repeat'] = Dart.forBlock['controls_repeat_ext']; +dartGenerator.forBlock['controls_repeat'] = + dartGenerator.forBlock['controls_repeat_ext']; -Dart.forBlock['controls_whileUntil'] = function(block) { +dartGenerator.forBlock['controls_whileUntil'] = function(block) { // Do while/until loop. const until = block.getFieldValue('MODE') === 'UNTIL'; let argument0 = - Dart.valueToCode( - block, 'BOOL', until ? Dart.ORDER_UNARY_PREFIX : Dart.ORDER_NONE) || + dartGenerator.valueToCode( + block, 'BOOL', until ? Order.UNARY_PREFIX : Order.NONE) || 'false'; - let branch = Dart.statementToCode(block, 'DO'); - branch = Dart.addLoopTrap(branch, block); + let branch = dartGenerator.statementToCode(block, 'DO'); + branch = dartGenerator.addLoopTrap(branch, block); if (until) { argument0 = '!' + argument0; } return 'while (' + argument0 + ') {\n' + branch + '}\n'; }; -Dart.forBlock['controls_for'] = function(block) { +dartGenerator.forBlock['controls_for'] = function(block) { // For loop. const variable0 = - Dart.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); + dartGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); const argument0 = - Dart.valueToCode(block, 'FROM', Dart.ORDER_ASSIGNMENT) || '0'; - const argument1 = Dart.valueToCode(block, 'TO', Dart.ORDER_ASSIGNMENT) || '0'; - const increment = Dart.valueToCode(block, 'BY', Dart.ORDER_ASSIGNMENT) || '1'; - let branch = Dart.statementToCode(block, 'DO'); - branch = Dart.addLoopTrap(branch, block); + dartGenerator.valueToCode(block, 'FROM', Order.ASSIGNMENT) || '0'; + const argument1 = + dartGenerator.valueToCode(block, 'TO', Order.ASSIGNMENT) || '0'; + const increment = + dartGenerator.valueToCode(block, 'BY', Order.ASSIGNMENT) || '1'; + let branch = dartGenerator.statementToCode(block, 'DO'); + branch = dartGenerator.addLoopTrap(branch, block); let code; if (stringUtils.isNumber(argument0) && stringUtils.isNumber(argument1) && stringUtils.isNumber(increment)) { @@ -87,19 +94,22 @@ Dart.forBlock['controls_for'] = function(block) { let startVar = argument0; if (!argument0.match(/^\w+$/) && !stringUtils.isNumber(argument0)) { startVar = - Dart.nameDB_.getDistinctName(variable0 + '_start', NameType.VARIABLE); + dartGenerator.nameDB_.getDistinctName( + variable0 + '_start', NameType.VARIABLE); code += 'var ' + startVar + ' = ' + argument0 + ';\n'; } let endVar = argument1; if (!argument1.match(/^\w+$/) && !stringUtils.isNumber(argument1)) { endVar = - Dart.nameDB_.getDistinctName(variable0 + '_end', NameType.VARIABLE); + dartGenerator.nameDB_.getDistinctName( + variable0 + '_end', NameType.VARIABLE); code += 'var ' + endVar + ' = ' + argument1 + ';\n'; } // Determine loop direction at start, in case one of the bounds // changes during loop execution. const incVar = - Dart.nameDB_.getDistinctName(variable0 + '_inc', NameType.VARIABLE); + dartGenerator.nameDB_.getDistinctName( + variable0 + '_inc', NameType.VARIABLE); code += 'num ' + incVar + ' = '; if (stringUtils.isNumber(increment)) { code += Math.abs(increment) + ';\n'; @@ -107,7 +117,7 @@ Dart.forBlock['controls_for'] = function(block) { code += '(' + increment + ').abs();\n'; } code += 'if (' + startVar + ' > ' + endVar + ') {\n'; - code += Dart.INDENT + incVar + ' = -' + incVar + ';\n'; + code += dartGenerator.INDENT + incVar + ' = -' + incVar + ';\n'; code += '}\n'; code += 'for (' + variable0 + ' = ' + startVar + '; ' + incVar + ' >= 0 ? ' + variable0 + ' <= ' + endVar + ' : ' + variable0 + @@ -117,38 +127,39 @@ Dart.forBlock['controls_for'] = function(block) { return code; }; -Dart.forBlock['controls_forEach'] = function(block) { +dartGenerator.forBlock['controls_forEach'] = function(block) { // For each loop. const variable0 = - Dart.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); + dartGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); const argument0 = - Dart.valueToCode(block, 'LIST', Dart.ORDER_ASSIGNMENT) || '[]'; - let branch = Dart.statementToCode(block, 'DO'); - branch = Dart.addLoopTrap(branch, block); + dartGenerator.valueToCode(block, 'LIST', Order.ASSIGNMENT) || '[]'; + let branch = dartGenerator.statementToCode(block, 'DO'); + branch = dartGenerator.addLoopTrap(branch, block); const code = 'for (var ' + variable0 + ' in ' + argument0 + ') {\n' + branch + '}\n'; return code; }; -Dart.forBlock['controls_flow_statements'] = function(block) { +dartGenerator.forBlock['controls_flow_statements'] = function(block) { // Flow statements: continue, break. let xfix = ''; - if (Dart.STATEMENT_PREFIX) { + if (dartGenerator.STATEMENT_PREFIX) { // Automatic prefix insertion is switched off for this block. Add manually. - xfix += Dart.injectId(Dart.STATEMENT_PREFIX, block); + xfix += dartGenerator.injectId(dartGenerator.STATEMENT_PREFIX, block); } - if (Dart.STATEMENT_SUFFIX) { + if (dartGenerator.STATEMENT_SUFFIX) { // Inject any statement suffix here since the regular one at the end // will not get executed if the break/continue is triggered. - xfix += Dart.injectId(Dart.STATEMENT_SUFFIX, block); + xfix += dartGenerator.injectId(dartGenerator.STATEMENT_SUFFIX, block); } - if (Dart.STATEMENT_PREFIX) { + if (dartGenerator.STATEMENT_PREFIX) { const loop = block.getSurroundLoop(); if (loop && !loop.suppressPrefixSuffix) { // Inject loop's statement prefix here since the regular one at the end // of the loop will not get executed if 'continue' is triggered. // In the case of 'break', a prefix is needed due to the loop's suffix. - xfix += Dart.injectId(Dart.STATEMENT_PREFIX, loop); + xfix += dartGenerator.injectId(dartGenerator.STATEMENT_PREFIX, loop); } } switch (block.getFieldValue('FLOW')) { diff --git a/generators/dart/math.js b/generators/dart/math.js index 60c43a12a..b6bc35f8f 100644 --- a/generators/dart/math.js +++ b/generators/dart/math.js @@ -12,76 +12,78 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.math'); import {NameType} from '../../core/names.js'; -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator, Order} from '../dart.js'; -Dart.addReservedWords('Math'); +dartGenerator.addReservedWords('Math'); -Dart.forBlock['math_number'] = function(block) { +dartGenerator.forBlock['math_number'] = function(block) { // Numeric value. let code = Number(block.getFieldValue('NUM')); let order; if (code === Infinity) { code = 'double.infinity'; - order = Dart.ORDER_UNARY_POSTFIX; + order = Order.UNARY_POSTFIX; } else if (code === -Infinity) { code = '-double.infinity'; - order = Dart.ORDER_UNARY_PREFIX; + order = Order.UNARY_PREFIX; } else { - // -4.abs() returns -4 in Dart due to strange order of operation choices. + // -4.abs() returns -4 in dartGenerator due to strange order of operation choices. // -4 is actually an operator and a number. Reflect this in the order. - order = code < 0 ? Dart.ORDER_UNARY_PREFIX : Dart.ORDER_ATOMIC; + order = code < 0 ? Order.UNARY_PREFIX : Order.ATOMIC; } return [code, order]; }; -Dart.forBlock['math_arithmetic'] = function(block) { +dartGenerator.forBlock['math_arithmetic'] = function(block) { // Basic arithmetic operators, and power. const OPERATORS = { - 'ADD': [' + ', Dart.ORDER_ADDITIVE], - 'MINUS': [' - ', Dart.ORDER_ADDITIVE], - 'MULTIPLY': [' * ', Dart.ORDER_MULTIPLICATIVE], - 'DIVIDE': [' / ', Dart.ORDER_MULTIPLICATIVE], - 'POWER': [null, Dart.ORDER_NONE], // Handle power separately. + 'ADD': [' + ', Order.ADDITIVE], + 'MINUS': [' - ', Order.ADDITIVE], + 'MULTIPLY': [' * ', Order.MULTIPLICATIVE], + 'DIVIDE': [' / ', Order.MULTIPLICATIVE], + 'POWER': [null, Order.NONE], // Handle power separately. }; const tuple = OPERATORS[block.getFieldValue('OP')]; const operator = tuple[0]; const order = tuple[1]; - const argument0 = Dart.valueToCode(block, 'A', order) || '0'; - const argument1 = Dart.valueToCode(block, 'B', order) || '0'; + const argument0 = dartGenerator.valueToCode(block, 'A', order) || '0'; + const argument1 = dartGenerator.valueToCode(block, 'B', order) || '0'; let code; - // Power in Dart requires a special case since it has no operator. + // Power in dartGenerator requires a special case since it has no operator. if (!operator) { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; code = 'Math.pow(' + argument0 + ', ' + argument1 + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } code = argument0 + operator + argument1; return [code, order]; }; -Dart.forBlock['math_single'] = function(block) { +dartGenerator.forBlock['math_single'] = function(block) { // Math operators with single operand. const operator = block.getFieldValue('OP'); let code; let arg; if (operator === 'NEG') { // Negation is a special case given its different operator precedence. - arg = Dart.valueToCode(block, 'NUM', Dart.ORDER_UNARY_PREFIX) || '0'; + arg = dartGenerator.valueToCode(block, 'NUM', Order.UNARY_PREFIX) || '0'; if (arg[0] === '-') { - // --3 is not legal in Dart. + // --3 is not legal in dartGenerator. arg = ' ' + arg; } code = '-' + arg; - return [code, Dart.ORDER_UNARY_PREFIX]; + return [code, Order.UNARY_PREFIX]; } - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; if (operator === 'ABS' || operator.substring(0, 5) === 'ROUND') { - arg = Dart.valueToCode(block, 'NUM', Dart.ORDER_UNARY_POSTFIX) || '0'; + arg = dartGenerator.valueToCode(block, 'NUM', Order.UNARY_POSTFIX) || '0'; } else if (operator === 'SIN' || operator === 'COS' || operator === 'TAN') { - arg = Dart.valueToCode(block, 'NUM', Dart.ORDER_MULTIPLICATIVE) || '0'; + arg = dartGenerator.valueToCode(block, 'NUM', Order.MULTIPLICATIVE) || '0'; } else { - arg = Dart.valueToCode(block, 'NUM', Dart.ORDER_NONE) || '0'; + arg = dartGenerator.valueToCode(block, 'NUM', Order.NONE) || '0'; } // First, handle cases which generate values that don't need parentheses // wrapping the code. @@ -121,7 +123,7 @@ Dart.forBlock['math_single'] = function(block) { break; } if (code) { - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } // Second, handle cases which generate values that may need parentheses // wrapping the code. @@ -141,49 +143,50 @@ Dart.forBlock['math_single'] = function(block) { default: throw Error('Unknown math operator: ' + operator); } - return [code, Dart.ORDER_MULTIPLICATIVE]; + return [code, Order.MULTIPLICATIVE]; }; -Dart.forBlock['math_constant'] = function(block) { +dartGenerator.forBlock['math_constant'] = function(block) { // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. const CONSTANTS = { - 'PI': ['Math.pi', Dart.ORDER_UNARY_POSTFIX], - 'E': ['Math.e', Dart.ORDER_UNARY_POSTFIX], - 'GOLDEN_RATIO': ['(1 + Math.sqrt(5)) / 2', Dart.ORDER_MULTIPLICATIVE], - 'SQRT2': ['Math.sqrt2', Dart.ORDER_UNARY_POSTFIX], - 'SQRT1_2': ['Math.sqrt1_2', Dart.ORDER_UNARY_POSTFIX], - 'INFINITY': ['double.infinity', Dart.ORDER_ATOMIC], + 'PI': ['Math.pi', Order.UNARY_POSTFIX], + 'E': ['Math.e', Order.UNARY_POSTFIX], + 'GOLDEN_RATIO': ['(1 + Math.sqrt(5)) / 2', Order.MULTIPLICATIVE], + 'SQRT2': ['Math.sqrt2', Order.UNARY_POSTFIX], + 'SQRT1_2': ['Math.sqrt1_2', Order.UNARY_POSTFIX], + 'INFINITY': ['double.infinity', Order.ATOMIC], }; const constant = block.getFieldValue('CONSTANT'); if (constant !== 'INFINITY') { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; } return CONSTANTS[constant]; }; -Dart.forBlock['math_number_property'] = function(block) { +dartGenerator.forBlock['math_number_property'] = function(block) { // Check if a number is even, odd, prime, whole, positive, or negative // or if it is divisible by certain number. Returns true or false. const PROPERTIES = { - 'EVEN': [' % 2 == 0', Dart.ORDER_MULTIPLICATIVE, Dart.ORDER_EQUALITY], - 'ODD': [' % 2 == 1', Dart.ORDER_MULTIPLICATIVE, Dart.ORDER_EQUALITY], - 'WHOLE': [' % 1 == 0', Dart.ORDER_MULTIPLICATIVE, Dart.ORDER_EQUALITY], - 'POSITIVE': [' > 0', Dart.ORDER_RELATIONAL, Dart.ORDER_RELATIONAL], - 'NEGATIVE': [' < 0', Dart.ORDER_RELATIONAL, Dart.ORDER_RELATIONAL], - 'DIVISIBLE_BY': [null, Dart.ORDER_MULTIPLICATIVE, Dart.ORDER_EQUALITY], - 'PRIME': [null, Dart.ORDER_NONE, Dart.ORDER_UNARY_POSTFIX], + 'EVEN': [' % 2 == 0', Order.MULTIPLICATIVE, Order.EQUALITY], + 'ODD': [' % 2 == 1', Order.MULTIPLICATIVE, Order.EQUALITY], + 'WHOLE': [' % 1 == 0', Order.MULTIPLICATIVE, Order.EQUALITY], + 'POSITIVE': [' > 0', Order.RELATIONAL, Order.RELATIONAL], + 'NEGATIVE': [' < 0', Order.RELATIONAL, Order.RELATIONAL], + 'DIVISIBLE_BY': [null, Order.MULTIPLICATIVE, Order.EQUALITY], + 'PRIME': [null, Order.NONE, Order.UNARY_POSTFIX], }; const dropdownProperty = block.getFieldValue('PROPERTY'); const [suffix, inputOrder, outputOrder] = PROPERTIES[dropdownProperty]; - const numberToCheck = Dart.valueToCode(block, 'NUMBER_TO_CHECK', + const numberToCheck = dartGenerator.valueToCode(block, 'NUMBER_TO_CHECK', inputOrder) || '0'; let code; if (dropdownProperty === 'PRIME') { // Prime is a special case as it is not a one-liner test. - Dart.definitions_['import_dart_math'] = + dartGenerator.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const functionName = Dart.provideFunction_('math_isPrime', ` -bool ${Dart.FUNCTION_NAME_PLACEHOLDER_}(n) { + const functionName = dartGenerator.provideFunction_('math_isPrime', ` +bool ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(n) { // https://en.wikipedia.org/wiki/Primality_test#Naive_methods if (n == 2 || n == 3) { return true; @@ -204,10 +207,10 @@ bool ${Dart.FUNCTION_NAME_PLACEHOLDER_}(n) { `); code = functionName + '(' + numberToCheck + ')'; } else if (dropdownProperty === 'DIVISIBLE_BY') { - const divisor = Dart.valueToCode(block, 'DIVISOR', - Dart.ORDER_MULTIPLICATIVE) || '0'; + const divisor = dartGenerator.valueToCode(block, 'DIVISOR', + Order.MULTIPLICATIVE) || '0'; if (divisor === '0') { - return ['false', Dart.ORDER_ATOMIC]; + return ['false', Order.ATOMIC]; } code = numberToCheck + ' % ' + divisor + ' == 0'; } else { @@ -216,30 +219,31 @@ bool ${Dart.FUNCTION_NAME_PLACEHOLDER_}(n) { return [code, outputOrder]; }; -Dart.forBlock['math_change'] = function(block) { +dartGenerator.forBlock['math_change'] = function(block) { // Add to a variable in place. const argument0 = - Dart.valueToCode(block, 'DELTA', Dart.ORDER_ADDITIVE) || '0'; + dartGenerator.valueToCode(block, 'DELTA', Order.ADDITIVE) || '0'; const varName = - Dart.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); + dartGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); return varName + ' = (' + varName + ' is num ? ' + varName + ' : 0) + ' + argument0 + ';\n'; }; // Rounding functions have a single operand. -Dart.forBlock['math_round'] = Dart.forBlock['math_single']; +dartGenerator.forBlock['math_round'] = dartGenerator.forBlock['math_single']; // Trigonometry functions have a single operand. -Dart.forBlock['math_trig'] = Dart.forBlock['math_single']; +dartGenerator.forBlock['math_trig'] = dartGenerator.forBlock['math_single']; -Dart.forBlock['math_on_list'] = function(block) { +dartGenerator.forBlock['math_on_list'] = function(block) { // Math functions for lists. const func = block.getFieldValue('OP'); - const list = Dart.valueToCode(block, 'LIST', Dart.ORDER_NONE) || '[]'; + const list = dartGenerator.valueToCode(block, 'LIST', Order.NONE) || '[]'; let code; switch (func) { case 'SUM': { - const functionName = Dart.provideFunction_('math_sum', ` -num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { + const functionName = dartGenerator.provideFunction_('math_sum', ` +num ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List myList) { num sumVal = 0; myList.forEach((num entry) {sumVal += entry;}); return sumVal; @@ -249,9 +253,10 @@ num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { break; } case 'MIN': { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const functionName = Dart.provideFunction_('math_min', ` -num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + const functionName = dartGenerator.provideFunction_('math_min', ` +num ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List myList) { if (myList.isEmpty) return null; num minVal = myList[0]; myList.forEach((num entry) {minVal = Math.min(minVal, entry);}); @@ -262,9 +267,10 @@ num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { break; } case 'MAX': { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const functionName = Dart.provideFunction_('math_max', ` -num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + const functionName = dartGenerator.provideFunction_('math_max', ` +num ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List myList) { if (myList.isEmpty) return null; num maxVal = myList[0]; myList.forEach((num entry) {maxVal = Math.max(maxVal, entry);}); @@ -277,8 +283,8 @@ num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { case 'AVERAGE': { // This operation exclude null and values that are not int or float: // math_mean([null,null,"aString",1,9]) -> 5.0 - const functionName = Dart.provideFunction_('math_mean', ` -num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { + const functionName = dartGenerator.provideFunction_('math_mean', ` +num ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List myList) { // First filter list for numbers only. List localList = new List.from(myList); localList.removeWhere((a) => a is! num); @@ -292,8 +298,8 @@ num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { break; } case 'MEDIAN': { - const functionName = Dart.provideFunction_('math_median', ` -num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { + const functionName = dartGenerator.provideFunction_('math_median', ` +num ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List myList) { // First filter list for numbers only, then sort, then return middle value // or the average of two middle values if list has an even number of elements. List localList = new List.from(myList); @@ -312,12 +318,13 @@ num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { break; } case 'MODE': { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; // As a list of numbers can contain more than one mode, // the returned result is provided as an array. // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1] - const functionName = Dart.provideFunction_('math_modes', ` -List ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List values) { + const functionName = dartGenerator.provideFunction_('math_modes', ` +List ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List values) { List modes = []; List counts = []; int maxCount = 0; @@ -350,9 +357,11 @@ List ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List values) { break; } case 'STD_DEV': { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const functionName = Dart.provideFunction_('math_standard_deviation', ` -num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + const functionName = + dartGenerator.provideFunction_('math_standard_deviation', ` +num ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List myList) { // First filter list for numbers only. List numbers = new List.from(myList); numbers.removeWhere((a) => a is! num); @@ -370,9 +379,10 @@ num ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { break; } case 'RANDOM': { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const functionName = Dart.provideFunction_('math_random_item', ` -dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + const functionName = dartGenerator.provideFunction_('math_random_item', ` +dynamic ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(List myList) { int x = new Math.Random().nextInt(myList.length); return myList[x]; } @@ -383,38 +393,41 @@ dynamic ${Dart.FUNCTION_NAME_PLACEHOLDER_}(List myList) { default: throw Error('Unknown operator: ' + func); } - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['math_modulo'] = function(block) { +dartGenerator.forBlock['math_modulo'] = function(block) { // Remainder computation. const argument0 = - Dart.valueToCode(block, 'DIVIDEND', Dart.ORDER_MULTIPLICATIVE) || '0'; + dartGenerator.valueToCode(block, 'DIVIDEND', Order.MULTIPLICATIVE) || '0'; const argument1 = - Dart.valueToCode(block, 'DIVISOR', Dart.ORDER_MULTIPLICATIVE) || '0'; + dartGenerator.valueToCode(block, 'DIVISOR', Order.MULTIPLICATIVE) || '0'; const code = argument0 + ' % ' + argument1; - return [code, Dart.ORDER_MULTIPLICATIVE]; + return [code, Order.MULTIPLICATIVE]; }; -Dart.forBlock['math_constrain'] = function(block) { +dartGenerator.forBlock['math_constrain'] = function(block) { // Constrain a number between two limits. - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const argument0 = Dart.valueToCode(block, 'VALUE', Dart.ORDER_NONE) || '0'; - const argument1 = Dart.valueToCode(block, 'LOW', Dart.ORDER_NONE) || '0'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + const argument0 = + dartGenerator.valueToCode(block, 'VALUE', Order.NONE) || '0'; + const argument1 = dartGenerator.valueToCode(block, 'LOW', Order.NONE) || '0'; const argument2 = - Dart.valueToCode(block, 'HIGH', Dart.ORDER_NONE) || 'double.infinity'; + dartGenerator.valueToCode(block, 'HIGH', Order.NONE) || 'double.infinity'; const code = 'Math.min(Math.max(' + argument0 + ', ' + argument1 + '), ' + argument2 + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['math_random_int'] = function(block) { +dartGenerator.forBlock['math_random_int'] = function(block) { // Random integer between [X] and [Y]. - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const argument0 = Dart.valueToCode(block, 'FROM', Dart.ORDER_NONE) || '0'; - const argument1 = Dart.valueToCode(block, 'TO', Dart.ORDER_NONE) || '0'; - const functionName = Dart.provideFunction_('math_random_int', ` -int ${Dart.FUNCTION_NAME_PLACEHOLDER_}(num a, num b) { + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + const argument0 = dartGenerator.valueToCode(block, 'FROM', Order.NONE) || '0'; + const argument1 = dartGenerator.valueToCode(block, 'TO', Order.NONE) || '0'; + const functionName = dartGenerator.provideFunction_('math_random_int', ` +int ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(num a, num b) { if (a > b) { // Swap a and b to ensure a is smaller. num c = a; @@ -425,22 +438,24 @@ int ${Dart.FUNCTION_NAME_PLACEHOLDER_}(num a, num b) { } `); const code = functionName + '(' + argument0 + ', ' + argument1 + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['math_random_float'] = function(block) { +dartGenerator.forBlock['math_random_float'] = function(block) { // Random fraction between 0 and 1. - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - return ['new Math.Random().nextDouble()', Dart.ORDER_UNARY_POSTFIX]; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + return ['new Math.Random().nextDouble()', Order.UNARY_POSTFIX]; }; -Dart.forBlock['math_atan2'] = function(block) { +dartGenerator.forBlock['math_atan2'] = function(block) { // Arctangent of point (X, Y) in degrees from -180 to 180. - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const argument0 = Dart.valueToCode(block, 'X', Dart.ORDER_NONE) || '0'; - const argument1 = Dart.valueToCode(block, 'Y', Dart.ORDER_NONE) || '0'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + const argument0 = dartGenerator.valueToCode(block, 'X', Order.NONE) || '0'; + const argument1 = dartGenerator.valueToCode(block, 'Y', Order.NONE) || '0'; return [ 'Math.atan2(' + argument1 + ', ' + argument0 + ') / Math.pi * 180', - Dart.ORDER_MULTIPLICATIVE + Order.MULTIPLICATIVE ]; }; diff --git a/generators/dart/procedures.js b/generators/dart/procedures.js index bce63c687..d86cd2f7c 100644 --- a/generators/dart/procedures.js +++ b/generators/dart/procedures.js @@ -12,93 +12,99 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.procedures'); import {NameType} from '../../core/names.js'; -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator, Order} from '../dart.js'; -Dart.forBlock['procedures_defreturn'] = function(block) { +dartGenerator.forBlock['procedures_defreturn'] = function(block) { // Define a procedure with a return value. const funcName = - Dart.nameDB_.getName(block.getFieldValue('NAME'), NameType.PROCEDURE); + dartGenerator.nameDB_.getName( + block.getFieldValue('NAME'), NameType.PROCEDURE); let xfix1 = ''; - if (Dart.STATEMENT_PREFIX) { - xfix1 += Dart.injectId(Dart.STATEMENT_PREFIX, block); + if (dartGenerator.STATEMENT_PREFIX) { + xfix1 += dartGenerator.injectId(dartGenerator.STATEMENT_PREFIX, block); } - if (Dart.STATEMENT_SUFFIX) { - xfix1 += Dart.injectId(Dart.STATEMENT_SUFFIX, block); + if (dartGenerator.STATEMENT_SUFFIX) { + xfix1 += dartGenerator.injectId(dartGenerator.STATEMENT_SUFFIX, block); } if (xfix1) { - xfix1 = Dart.prefixLines(xfix1, Dart.INDENT); + xfix1 = dartGenerator.prefixLines(xfix1, dartGenerator.INDENT); } let loopTrap = ''; - if (Dart.INFINITE_LOOP_TRAP) { - loopTrap = Dart.prefixLines( - Dart.injectId(Dart.INFINITE_LOOP_TRAP, block), Dart.INDENT); + if (dartGenerator.INFINITE_LOOP_TRAP) { + loopTrap = dartGenerator.prefixLines( + dartGenerator.injectId(dartGenerator.INFINITE_LOOP_TRAP, block), + dartGenerator.INDENT); } - const branch = Dart.statementToCode(block, 'STACK'); - let returnValue = Dart.valueToCode(block, 'RETURN', Dart.ORDER_NONE) || ''; + const branch = dartGenerator.statementToCode(block, 'STACK'); + let returnValue = + dartGenerator.valueToCode(block, 'RETURN', Order.NONE) || ''; let xfix2 = ''; if (branch && returnValue) { // After executing the function body, revisit this block for the return. xfix2 = xfix1; } if (returnValue) { - returnValue = Dart.INDENT + 'return ' + returnValue + ';\n'; + returnValue = dartGenerator.INDENT + 'return ' + returnValue + ';\n'; } const returnType = returnValue ? 'dynamic' : 'void'; const args = []; const variables = block.getVars(); for (let i = 0; i < variables.length; i++) { - args[i] = Dart.nameDB_.getName(variables[i], NameType.VARIABLE); + args[i] = dartGenerator.nameDB_.getName(variables[i], NameType.VARIABLE); } let code = returnType + ' ' + funcName + '(' + args.join(', ') + ') {\n' + xfix1 + loopTrap + branch + xfix2 + returnValue + '}'; - code = Dart.scrub_(block, code); + code = dartGenerator.scrub_(block, code); // Add % so as not to collide with helper functions in definitions list. - Dart.definitions_['%' + funcName] = code; + dartGenerator.definitions_['%' + funcName] = code; return null; }; // Defining a procedure without a return value uses the same generator as // a procedure with a return value. -Dart.forBlock['procedures_defnoreturn'] = Dart.forBlock['procedures_defreturn']; +dartGenerator.forBlock['procedures_defnoreturn'] = dartGenerator.forBlock['procedures_defreturn']; -Dart.forBlock['procedures_callreturn'] = function(block) { +dartGenerator.forBlock['procedures_callreturn'] = function(block) { // Call a procedure with a return value. const funcName = - Dart.nameDB_.getName(block.getFieldValue('NAME'), NameType.PROCEDURE); + dartGenerator.nameDB_.getName( + block.getFieldValue('NAME'),NameType.PROCEDURE); const args = []; const variables = block.getVars(); for (let i = 0; i < variables.length; i++) { - args[i] = Dart.valueToCode(block, 'ARG' + i, Dart.ORDER_NONE) || 'null'; + args[i] = dartGenerator.valueToCode(block, 'ARG' + i, Order.NONE) || 'null'; } let code = funcName + '(' + args.join(', ') + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['procedures_callnoreturn'] = function(block) { +dartGenerator.forBlock['procedures_callnoreturn'] = function(block) { // Call a procedure with no return value. // Generated code is for a function call as a statement is the same as a // function call as a value, with the addition of line ending. - const tuple = Dart.forBlock['procedures_callreturn'](block); + const tuple = dartGenerator.forBlock['procedures_callreturn'](block); return tuple[0] + ';\n'; }; -Dart.forBlock['procedures_ifreturn'] = function(block) { +dartGenerator.forBlock['procedures_ifreturn'] = function(block) { // Conditionally return value from a procedure. const condition = - Dart.valueToCode(block, 'CONDITION', Dart.ORDER_NONE) || 'false'; + dartGenerator.valueToCode(block, 'CONDITION', Order.NONE) || 'false'; let code = 'if (' + condition + ') {\n'; - if (Dart.STATEMENT_SUFFIX) { + if (dartGenerator.STATEMENT_SUFFIX) { // Inject any statement suffix here since the regular one at the end // will not get executed if the return is triggered. - code += Dart.prefixLines( - Dart.injectId(Dart.STATEMENT_SUFFIX, block), Dart.INDENT); + code += dartGenerator.prefixLines( + dartGenerator.injectId( + dartGenerator.STATEMENT_SUFFIX, block), dartGenerator.INDENT); } if (block.hasReturnValue_) { - const value = Dart.valueToCode(block, 'VALUE', Dart.ORDER_NONE) || 'null'; - code += Dart.INDENT + 'return ' + value + ';\n'; + const value = + dartGenerator.valueToCode(block, 'VALUE', Order.NONE) || 'null'; + code += dartGenerator.INDENT + 'return ' + value + ';\n'; } else { - code += Dart.INDENT + 'return;\n'; + code += dartGenerator.INDENT + 'return;\n'; } code += '}\n'; return code; diff --git a/generators/dart/text.js b/generators/dart/text.js index ad2463c0b..de6f011d1 100644 --- a/generators/dart/text.js +++ b/generators/dart/text.js @@ -12,153 +12,157 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.texts'); import {NameType} from '../../core/names.js'; -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator, Order} from '../dart.js'; -Dart.addReservedWords('Html,Math'); +dartGenerator.addReservedWords('Html,Math'); -Dart.forBlock['text'] = function(block) { +dartGenerator.forBlock['text'] = function(block) { // Text value. - const code = Dart.quote_(block.getFieldValue('TEXT')); - return [code, Dart.ORDER_ATOMIC]; + const code = dartGenerator.quote_(block.getFieldValue('TEXT')); + return [code, Order.ATOMIC]; }; -Dart.forBlock['text_multiline'] = function(block) { +dartGenerator.forBlock['text_multiline'] = function(block) { // Text value. - const code = Dart.multiline_quote_(block.getFieldValue('TEXT')); + const code = dartGenerator.multiline_quote_(block.getFieldValue('TEXT')); const order = - code.indexOf('+') !== -1 ? Dart.ORDER_ADDITIVE : Dart.ORDER_ATOMIC; + code.indexOf('+') !== -1 ? Order.ADDITIVE : Order.ATOMIC; return [code, order]; }; -Dart.forBlock['text_join'] = function(block) { +dartGenerator.forBlock['text_join'] = function(block) { // Create a string made up of any number of elements of any type. switch (block.itemCount_) { case 0: - return ["''", Dart.ORDER_ATOMIC]; + return ["''", Order.ATOMIC]; case 1: { const element = - Dart.valueToCode(block, 'ADD0', Dart.ORDER_UNARY_POSTFIX) || "''"; + dartGenerator.valueToCode(block, 'ADD0', Order.UNARY_POSTFIX) || "''"; const code = element + '.toString()'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } default: { const elements = new Array(block.itemCount_); for (let i = 0; i < block.itemCount_; i++) { elements[i] = - Dart.valueToCode(block, 'ADD' + i, Dart.ORDER_NONE) || "''"; + dartGenerator.valueToCode(block, 'ADD' + i, Order.NONE) || "''"; } const code = '[' + elements.join(',') + '].join()'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } } }; -Dart.forBlock['text_append'] = function(block) { +dartGenerator.forBlock['text_append'] = function(block) { // Append to a variable in place. const varName = - Dart.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); - const value = Dart.valueToCode(block, 'TEXT', Dart.ORDER_NONE) || "''"; + dartGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); + const value = dartGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; return varName + ' = [' + varName + ', ' + value + '].join();\n'; }; -Dart.forBlock['text_length'] = function(block) { +dartGenerator.forBlock['text_length'] = function(block) { // String or array length. const text = - Dart.valueToCode(block, 'VALUE', Dart.ORDER_UNARY_POSTFIX) || "''"; - return [text + '.length', Dart.ORDER_UNARY_POSTFIX]; + dartGenerator.valueToCode(block, 'VALUE', Order.UNARY_POSTFIX) || "''"; + return [text + '.length', Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_isEmpty'] = function(block) { +dartGenerator.forBlock['text_isEmpty'] = function(block) { // Is the string null or array empty? const text = - Dart.valueToCode(block, 'VALUE', Dart.ORDER_UNARY_POSTFIX) || "''"; - return [text + '.isEmpty', Dart.ORDER_UNARY_POSTFIX]; + dartGenerator.valueToCode(block, 'VALUE', Order.UNARY_POSTFIX) || "''"; + return [text + '.isEmpty', Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_indexOf'] = function(block) { +dartGenerator.forBlock['text_indexOf'] = function(block) { // Search the text for a substring. const operator = block.getFieldValue('END') === 'FIRST' ? 'indexOf' : 'lastIndexOf'; - const substring = Dart.valueToCode(block, 'FIND', Dart.ORDER_NONE) || "''"; + const substring = + dartGenerator.valueToCode(block, 'FIND', Order.NONE) || "''"; const text = - Dart.valueToCode(block, 'VALUE', Dart.ORDER_UNARY_POSTFIX) || "''"; + dartGenerator.valueToCode(block, 'VALUE', Order.UNARY_POSTFIX) || "''"; const code = text + '.' + operator + '(' + substring + ')'; if (block.workspace.options.oneBasedIndex) { - return [code + ' + 1', Dart.ORDER_ADDITIVE]; + return [code + ' + 1', Order.ADDITIVE]; } - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_charAt'] = function(block) { +dartGenerator.forBlock['text_charAt'] = function(block) { // Get letter at index. // Note: Until January 2013 this block did not have the WHERE input. const where = block.getFieldValue('WHERE') || 'FROM_START'; const textOrder = (where === 'FIRST' || where === 'FROM_START') ? - Dart.ORDER_UNARY_POSTFIX : - Dart.ORDER_NONE; - const text = Dart.valueToCode(block, 'VALUE', textOrder) || "''"; + Order.UNARY_POSTFIX : + Order.NONE; + const text = dartGenerator.valueToCode(block, 'VALUE', textOrder) || "''"; let at; switch (where) { case 'FIRST': { const code = text + '[0]'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } case 'FROM_START': { - at = Dart.getAdjusted(block, 'AT'); + at = dartGenerator.getAdjusted(block, 'AT'); const code = text + '[' + at + ']'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } case 'LAST': at = 1; // Fall through. case 'FROM_END': { - at = Dart.getAdjusted(block, 'AT', 1); - const functionName = Dart.provideFunction_('text_get_from_end', ` -String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String text, num x) { + at = dartGenerator.getAdjusted(block, 'AT', 1); + const functionName = dartGenerator.provideFunction_('text_get_from_end', ` +String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(String text, num x) { return text[text.length - x]; } `); const code = functionName + '(' + text + ', ' + at + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } case 'RANDOM': { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; - const functionName = Dart.provideFunction_('text_random_letter', ` -String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String text) { + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; + const functionName = + dartGenerator.provideFunction_('text_random_letter', ` +String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(String text) { int x = new Math.Random().nextInt(text.length); return text[x]; } `); const code = functionName + '(' + text + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; } } throw Error('Unhandled option (text_charAt).'); }; -Dart.forBlock['text_getSubstring'] = function(block) { +dartGenerator.forBlock['text_getSubstring'] = function(block) { // Get substring. const where1 = block.getFieldValue('WHERE1'); const where2 = block.getFieldValue('WHERE2'); const requiresLengthCall = (where1 !== 'FROM_END' && where2 === 'FROM_START'); const textOrder = - requiresLengthCall ? Dart.ORDER_UNARY_POSTFIX : Dart.ORDER_NONE; - const text = Dart.valueToCode(block, 'STRING', textOrder) || "''"; + requiresLengthCall ? Order.UNARY_POSTFIX : Order.NONE; + const text = dartGenerator.valueToCode(block, 'STRING', textOrder) || "''"; let code; if (where1 === 'FIRST' && where2 === 'LAST') { code = text; - return [code, Dart.ORDER_NONE]; + return [code, Order.NONE]; } else if (text.match(/^'?\w+'?$/) || requiresLengthCall) { // If the text is a variable or literal or doesn't require a call for // length, don't generate a helper function. let at1; switch (where1) { case 'FROM_START': - at1 = Dart.getAdjusted(block, 'AT1'); + at1 = dartGenerator.getAdjusted(block, 'AT1'); break; case 'FROM_END': - at1 = Dart.getAdjusted(block, 'AT1', 1, false, Dart.ORDER_ADDITIVE); + at1 = dartGenerator.getAdjusted(block, 'AT1', 1, false, Order.ADDITIVE); at1 = text + '.length - ' + at1; break; case 'FIRST': @@ -170,10 +174,10 @@ Dart.forBlock['text_getSubstring'] = function(block) { let at2; switch (where2) { case 'FROM_START': - at2 = Dart.getAdjusted(block, 'AT2', 1); + at2 = dartGenerator.getAdjusted(block, 'AT2', 1); break; case 'FROM_END': - at2 = Dart.getAdjusted(block, 'AT2', 0, false, Dart.ORDER_ADDITIVE); + at2 = dartGenerator.getAdjusted(block, 'AT2', 0, false, Order.ADDITIVE); at2 = text + '.length - ' + at2; break; case 'LAST': @@ -188,10 +192,11 @@ Dart.forBlock['text_getSubstring'] = function(block) { code = text + '.substring(' + at1 + ', ' + at2 + ')'; } } else { - const at1 = Dart.getAdjusted(block, 'AT1'); - const at2 = Dart.getAdjusted(block, 'AT2'); - const functionName = Dart.provideFunction_('text_get_substring', ` -String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String text, String where1, num at1, String where2, num at2) { + const at1 = dartGenerator.getAdjusted(block, 'AT1'); + const at2 = dartGenerator.getAdjusted(block, 'AT2'); + const functionName = + dartGenerator.provideFunction_('text_get_substring', ` +String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(String text, String where1, num at1, String where2, num at2) { int getAt(String where, num at) { if (where == 'FROM_END') { at = text.length - 1 - at; @@ -212,10 +217,10 @@ String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String text, String where1, num at1, S code = functionName + '(' + text + ', \'' + where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; } - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_changeCase'] = function(block) { +dartGenerator.forBlock['text_changeCase'] = function(block) { // Change capitalization. const OPERATORS = { 'UPPERCASE': '.toUpperCase()', @@ -223,16 +228,16 @@ Dart.forBlock['text_changeCase'] = function(block) { 'TITLECASE': null }; const operator = OPERATORS[block.getFieldValue('CASE')]; - const textOrder = operator ? Dart.ORDER_UNARY_POSTFIX : Dart.ORDER_NONE; - const text = Dart.valueToCode(block, 'TEXT', textOrder) || "''"; + const textOrder = operator ? Order.UNARY_POSTFIX : Order.NONE; + const text = dartGenerator.valueToCode(block, 'TEXT', textOrder) || "''"; let code; if (operator) { - // Upper and lower case are functions built into Dart. + // Upper and lower case are functions built into dartGenerator. code = text + operator; } else { - // Title case is not a native Dart function. Define one. - const functionName = Dart.provideFunction_('text_toTitleCase', ` -String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String str) { + // Title case is not a native dartGenerator function. Define one. + const functionName = dartGenerator.provideFunction_('text_toTitleCase', ` +String ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(String str) { RegExp exp = new RegExp(r'\\b'); List list = str.split(exp); final title = new StringBuffer(); @@ -249,10 +254,10 @@ String ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String str) { `); code = functionName + '(' + text + ')'; } - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_trim'] = function(block) { +dartGenerator.forBlock['text_trim'] = function(block) { // Trim spaces. const OPERATORS = { 'LEFT': '.replaceFirst(new RegExp(r\'^\\s+\'), \'\')', @@ -261,44 +266,47 @@ Dart.forBlock['text_trim'] = function(block) { }; const operator = OPERATORS[block.getFieldValue('MODE')]; const text = - Dart.valueToCode(block, 'TEXT', Dart.ORDER_UNARY_POSTFIX) || "''"; - return [text + operator, Dart.ORDER_UNARY_POSTFIX]; + dartGenerator.valueToCode(block, 'TEXT', Order.UNARY_POSTFIX) || "''"; + return [text + operator, Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_print'] = function(block) { +dartGenerator.forBlock['text_print'] = function(block) { // Print statement. - const msg = Dart.valueToCode(block, 'TEXT', Dart.ORDER_NONE) || "''"; + const msg = dartGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; return 'print(' + msg + ');\n'; }; -Dart.forBlock['text_prompt_ext'] = function(block) { +dartGenerator.forBlock['text_prompt_ext'] = function(block) { // Prompt function. - Dart.definitions_['import_dart_html'] = 'import \'dart:html\' as Html;'; + dartGenerator.definitions_['import_dart_html'] = + 'import \'dart:html\' as Html;'; let msg; if (block.getField('TEXT')) { // Internal message. - msg = Dart.quote_(block.getFieldValue('TEXT')); + msg = dartGenerator.quote_(block.getFieldValue('TEXT')); } else { // External message. - msg = Dart.valueToCode(block, 'TEXT', Dart.ORDER_NONE) || "''"; + msg = dartGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; } let code = 'Html.window.prompt(' + msg + ', \'\')'; const toNumber = block.getFieldValue('TYPE') === 'NUMBER'; if (toNumber) { - Dart.definitions_['import_dart_math'] = 'import \'dart:math\' as Math;'; + dartGenerator.definitions_['import_dart_math'] = + 'import \'dart:math\' as Math;'; code = 'Math.parseDouble(' + code + ')'; } - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_prompt'] = Dart.forBlock['text_prompt_ext']; +dartGenerator.forBlock['text_prompt'] = + dartGenerator.forBlock['text_prompt_ext']; -Dart.forBlock['text_count'] = function(block) { - const text = Dart.valueToCode(block, 'TEXT', Dart.ORDER_NONE) || "''"; - const sub = Dart.valueToCode(block, 'SUB', Dart.ORDER_NONE) || "''"; - // Substring count is not a native Dart function. Define one. - const functionName = Dart.provideFunction_('text_count', ` -int ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String haystack, String needle) { +dartGenerator.forBlock['text_count'] = function(block) { + const text = dartGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''"; + const sub = dartGenerator.valueToCode(block, 'SUB', Order.NONE) || "''"; + // Substring count is not a native dartGenerator function. Define one. + const functionName = dartGenerator.provideFunction_('text_count', ` +int ${dartGenerator.FUNCTION_NAME_PLACEHOLDER_}(String haystack, String needle) { if (needle.length == 0) { return haystack.length + 1; } @@ -315,24 +323,24 @@ int ${Dart.FUNCTION_NAME_PLACEHOLDER_}(String haystack, String needle) { } `); const code = functionName + '(' + text + ', ' + sub + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_replace'] = function(block) { +dartGenerator.forBlock['text_replace'] = function(block) { const text = - Dart.valueToCode(block, 'TEXT', Dart.ORDER_UNARY_POSTFIX) || "''"; - const from = Dart.valueToCode(block, 'FROM', Dart.ORDER_NONE) || "''"; - const to = Dart.valueToCode(block, 'TO', Dart.ORDER_NONE) || "''"; + dartGenerator.valueToCode(block, 'TEXT', Order.UNARY_POSTFIX) || "''"; + const from = dartGenerator.valueToCode(block, 'FROM', Order.NONE) || "''"; + const to = dartGenerator.valueToCode(block, 'TO', Order.NONE) || "''"; const code = text + '.replaceAll(' + from + ', ' + to + ')'; - return [code, Dart.ORDER_UNARY_POSTFIX]; + return [code, Order.UNARY_POSTFIX]; }; -Dart.forBlock['text_reverse'] = function(block) { - // There isn't a sensible way to do this in Dart. See: +dartGenerator.forBlock['text_reverse'] = function(block) { + // There isn't a sensible way to do this in dartGenerator. See: // http://stackoverflow.com/a/21613700/3529104 // Implementing something is possibly better than not implementing anything? const text = - Dart.valueToCode(block, 'TEXT', Dart.ORDER_UNARY_POSTFIX) || "''"; + dartGenerator.valueToCode(block, 'TEXT', Order.UNARY_POSTFIX) || "''"; const code = 'new String.fromCharCodes(' + text + '.runes.toList().reversed)'; - return [code, Dart.ORDER_UNARY_PREFIX]; + return [code, Order.UNARY_PREFIX]; }; diff --git a/generators/dart/variables.js b/generators/dart/variables.js index d6d62584c..930f6d342 100644 --- a/generators/dart/variables.js +++ b/generators/dart/variables.js @@ -12,21 +12,23 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.variables'); import {NameType} from '../../core/names.js'; -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator, Order} from '../dart.js'; -Dart.forBlock['variables_get'] = function(block) { +dartGenerator.forBlock['variables_get'] = function(block) { // Variable getter. const code = - Dart.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); - return [code, Dart.ORDER_ATOMIC]; + dartGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); + return [code, Order.ATOMIC]; }; -Dart.forBlock['variables_set'] = function(block) { +dartGenerator.forBlock['variables_set'] = function(block) { // Variable setter. const argument0 = - Dart.valueToCode(block, 'VALUE', Dart.ORDER_ASSIGNMENT) || '0'; + dartGenerator.valueToCode(block, 'VALUE', Order.ASSIGNMENT) || '0'; const varName = - Dart.nameDB_.getName(block.getFieldValue('VAR'), NameType.VARIABLE); + dartGenerator.nameDB_.getName( + block.getFieldValue('VAR'), NameType.VARIABLE); return varName + ' = ' + argument0 + ';\n'; }; diff --git a/generators/dart/variables_dynamic.js b/generators/dart/variables_dynamic.js index d3ada9aa6..6b33f4b59 100644 --- a/generators/dart/variables_dynamic.js +++ b/generators/dart/variables_dynamic.js @@ -11,10 +11,12 @@ import * as goog from '../../closure/goog/goog.js'; goog.declareModuleId('Blockly.Dart.variablesDynamic'); -import {dartGenerator as Dart} from '../dart.js'; +import {dartGenerator} from '../dart.js'; import './variables.js'; -// Dart is dynamically typed. -Dart.forBlock['variables_get_dynamic'] = Dart.forBlock['variables_get']; -Dart.forBlock['variables_set_dynamic'] = Dart.forBlock['variables_set']; +// dartGenerator is dynamically typed. +dartGenerator.forBlock['variables_get_dynamic'] = + dartGenerator.forBlock['variables_get']; +dartGenerator.forBlock['variables_set_dynamic'] = + dartGenerator.forBlock['variables_set'];